diff --git a/.github/workflows/build-app-wxpython.yml b/.github/workflows/build-app-wxpython.yml index 1b33575ae3..f795ef8964 100644 --- a/.github/workflows/build-app-wxpython.yml +++ b/.github/workflows/build-app-wxpython.yml @@ -38,7 +38,7 @@ jobs: # p12-password: ${{ secrets.MAC_NOTARIZATION_PASSWORD }} - name: Codesign Binary - run: 'codesign -s "${{ env.MAC_CODESIGN_IDENTITY }}" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"' + run: 'codesign -s "${{ env.MAC_CODESIGN_IDENTITY }}" -v --force --deep --timestamp --entitlements ./ci_tooling/entitlements/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"' - name: Package Binary run: cd dist; ditto -c -k --sequesterRsrc --keepParent OpenCore-Patcher.app ../OpenCore-Patcher-wxPython.app.zip @@ -47,7 +47,7 @@ jobs: run: xcrun notarytool submit OpenCore-Patcher-wxPython.app.zip --apple-id "${{ env.MAC_NOTARIZATION_USERNAME }}" --password "${{ env.MAC_NOTARIZATION_PASSWORD }}" --team-id "${{ env.MAC_NOTARIZATION_TEAM_ID }}" - name: Generate support package - run: /usr/local/bin/packagesbuild ./payloads/InstallPackage/AutoPkg-Assets-Setup.pkgproj + run: /usr/local/bin/packagesbuild ./ci_tooling/autopkg/AutoPkg-Assets-Setup.pkgproj - name: Prepare App for Upload run: mv ./OpenCore-Patcher-wxPython.app.zip ./OpenCore-Patcher-GUI.app.zip diff --git a/Build-Binary.command b/Build-Binary.command index 6a451da5b9..eb9953d3e4 100755 --- a/Build-Binary.command +++ b/Build-Binary.command @@ -1,7 +1,7 @@ #!/usr/bin/env python3 - -# Generate stand alone application for OpenCore-Patcher -# Copyright (C) 2022-2023 - Mykola Grymalyuk +""" +Build-Binary.command: Generate stand alone application for OpenCore-Patcher +""" import os import sys @@ -12,7 +12,7 @@ import subprocess from pathlib import Path -from resources import constants +from opencore_legacy_patcher import constants class CreateBinary: @@ -229,7 +229,6 @@ class CreateBinary: "Config", "Drivers", "Icon", - "InstallPackage", "Kexts", "OpenCore", "Tools", @@ -237,10 +236,7 @@ class CreateBinary: ] whitelist_files = [ - "entitlements.plist", - "launcher.sh", - "OC-Patcher-TUI.icns", - "OC-Patcher.icns", + ] diff --git a/OpenCore-Patcher-GUI.command b/OpenCore-Patcher-GUI.command index ad809085a7..8cc77a79f6 100755 --- a/OpenCore-Patcher-GUI.command +++ b/OpenCore-Patcher-GUI.command @@ -1,6 +1,9 @@ #!/usr/bin/env python3 -# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk -from resources import main +""" +PyInstaller Entry Point +""" + +from opencore_legacy_patcher import main if __name__ == '__main__': - main.OpenCoreLegacyPatcher() \ No newline at end of file + main() \ No newline at end of file diff --git a/OpenCore-Patcher-GUI.spec b/OpenCore-Patcher-GUI.spec index 257f4feb64..c3d67bf6dd 100644 --- a/OpenCore-Patcher-GUI.spec +++ b/OpenCore-Patcher-GUI.spec @@ -13,7 +13,7 @@ from PyInstaller.building.build_main import Analysis sys.path.append(os.path.abspath(os.getcwd())) -from resources import constants +from opencore_legacy_patcher import constants block_cipher = None @@ -70,7 +70,7 @@ coll = COLLECT(exe, app = BUNDLE(coll, name='OpenCore-Patcher.app', - icon="payloads/OC-Patcher.icns", + icon="payloads/Icon/AppIcons/OC-Patcher.icns", bundle_identifier="com.dortania.opencore-legacy-patcher", info_plist={ "CFBundleName": "OpenCore Legacy Patcher", diff --git a/payloads/InstallPackage/AutoPkg-Assets-Setup.pkgproj b/ci_tooling/autopkg/AutoPkg-Assets-Setup.pkgproj similarity index 100% rename from payloads/InstallPackage/AutoPkg-Assets-Setup.pkgproj rename to ci_tooling/autopkg/AutoPkg-Assets-Setup.pkgproj diff --git a/payloads/InstallPackage/intro.txt b/ci_tooling/autopkg/intro.txt similarity index 100% rename from payloads/InstallPackage/intro.txt rename to ci_tooling/autopkg/intro.txt diff --git a/payloads/InstallPackage/postinstall.sh b/ci_tooling/autopkg/postinstall.sh similarity index 100% rename from payloads/InstallPackage/postinstall.sh rename to ci_tooling/autopkg/postinstall.sh diff --git a/payloads/InstallPackage/preinstall.sh b/ci_tooling/autopkg/preinstall.sh similarity index 100% rename from payloads/InstallPackage/preinstall.sh rename to ci_tooling/autopkg/preinstall.sh diff --git a/payloads/entitlements.plist b/ci_tooling/entitlements/entitlements.plist similarity index 100% rename from payloads/entitlements.plist rename to ci_tooling/entitlements/entitlements.plist diff --git a/data/amfi_data.py b/data/amfi_data.py deleted file mode 100644 index 1dbcf2a5a6..0000000000 --- a/data/amfi_data.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (C) 2022, Mykola Grymalyuk - -# Within AppleMobileFileIntegrity.kext, Apple has a bitmask-based boot-arg (ex. amfi=128) -# Below information is from reversed values in 13.0 Beta 6's AppleMobileFileIntegrity.kext -# Currently only 'amfi=3' has been used by Apple publicly -# - 0x3 used in 11.0.1 dyld source: -# - https://github.com/apple-oss-distributions/dyld/blob/5c9192436bb195e7a8fe61f22a229ee3d30d8222/testing/test-cases/kernel-hello-world.dtest/main.c#L2 - -import enum - -class AppleMobileFileIntegrity(enum.IntEnum): - # Names set are solely for readability - # Internal names are unknown - AMFI_ALLOW_TASK_FOR_PID: int = 0x1 # Allow Task for PID (alt. amfi_unrestrict_task_for_pid=0x1) - AMFI_ALLOW_INVALID_SIGNATURE: int = 0x2 # Reduce sig enforcement (alt. amfi_allow_any_signature=0x1) - AMFI_LV_ENFORCE_THIRD_PARTY: int = 0x4 # Don't mark external binaries as platform binaries - AMFI_UNKNOWN_1: int = 0x8 - AMFI_UNKNOWN_2: int = 0x10 - AMFI_UNKNOWN_3: int = 0x20 - AMFI_UNKNOWN_4: int = 0x40 - AMFI_ALLOW_EVERYTHING: int = 0x80 # Disable sig enforcement and Library Validation (alt. amfi_get_out_of_my_way=0x1) - - -# Internally within AMFI.kext, Apple references 0x2 and 0x80 as both 'Disable signature enforcement' -# However 0x80 is a higher privilege than 0x2, and breaks TCC support in OS (ex. Camera, Microphone, etc prompts) - -# Supported boot-args within AMFI.kext, last compared against 13.0 Beta 6 -# -# Within _initializeAppleMobileFileIntegrity(): -# - amfi_unrestrict_task_for_pid=0x1 -# - amfi_dev_mode_policy=0x1 -# - amfi_allow_any_signature=0x1 -# - amfi_get_out_of_my_way=0x1 -# - amfi_unrestricted_local_signing=0x1 -# - pmap_cs_unrestricted_local_signing=0x1 -# - amfi_ready_to_roll=0x1 -# - cs_enforcement_disable=0x1 -# -# Within AMFIInitializeLocalSigningPublicKey(): -# - -restore -# -# Within macOSPolicyConfigurationInit(): -# - amfi_force_policy=0x1 -# - amfi_block_unsigned_code=0x1 -# - amfi_force_cs_kill=0x1 -# - amfi_hsp_disable=0x1 -# - amfi_hsp_logging=0x1 -# - amfi_allow_bni_as_platform=0x1 -# - amfi_allow_non_platform=0x1 -# - amfi_prevent_old_entitled_platform_binaries=0x1 -# - amfi_allow_only_tc=0x1 -# - amfi_allow_only_tc_override=0x1 -# -# Within configurationSettingsInit() -# - amfi_enforce_launch_constraints=0x1 -# - amfi_allow_3p_launch_constraints=0x1 -# - BATS_TESTPLAN_ID="Custom Team ID" \ No newline at end of file diff --git a/opencore_legacy_patcher/__init__.py b/opencore_legacy_patcher/__init__.py new file mode 100644 index 0000000000..c19240578e --- /dev/null +++ b/opencore_legacy_patcher/__init__.py @@ -0,0 +1 @@ +from .application_entry import main \ No newline at end of file diff --git a/resources/main.py b/opencore_legacy_patcher/application_entry.py similarity index 92% rename from resources/main.py rename to opencore_legacy_patcher/application_entry.py index e0448c12e6..df30d21655 100644 --- a/resources/main.py +++ b/opencore_legacy_patcher/application_entry.py @@ -1,24 +1,31 @@ -# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk +""" +application_entry.py: Project entry point +""" import os import sys import time import logging import threading + from pathlib import Path -from resources.wx_gui import gui_entry -from resources import ( - constants, - utilities, +from . import constants + +from .wx_gui import gui_entry + +from .detections import ( device_probe, - os_probe, + os_probe +) +from .utilities import ( + utilities, defaults, arguments, reroute_payloads, commit_info, logging_handler, - analytics_handler, + analytics_handler ) @@ -43,7 +50,7 @@ def _generate_base_data(self) -> None: Generate base data required for the patcher to run """ - self.constants.wxpython_variant: bool = True + self.constants.wxpython_variant = True # Ensure we live after parent process dies (ie. LaunchAgent) os.setpgrp() @@ -111,3 +118,9 @@ def _generate_base_data(self) -> None: time.sleep(0.1) arguments.arguments(self.constants) + +def main(): + """ + Main entry point + """ + OpenCoreLegacyPatcher() \ No newline at end of file diff --git a/resources/constants.py b/opencore_legacy_patcher/constants.py similarity index 99% rename from resources/constants.py rename to opencore_legacy_patcher/constants.py index ebf94cbcc1..8a814ab76e 100644 --- a/resources/constants.py +++ b/opencore_legacy_patcher/constants.py @@ -1,13 +1,13 @@ -# pylint: disable=multiple-statements -# Defines versioning, file paths and other settings for the patcher -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +constants.py: Defines versioning, file paths and other settings for the patcher +""" -from pathlib import Path -from typing import Optional +from pathlib import Path +from typing import Optional from packaging import version -from resources import device_probe -from data import os_data +from .datasets import os_data +from .detections import device_probe class Constants: @@ -739,7 +739,7 @@ def icns_resource_path(self): @property def app_icon_path(self): - return self.payload_path / Path("OC-Patcher.icns") + return self.payload_path / Path("Icon/AppIcons/OC-Patcher.icns") @property def icon_path_external(self): diff --git a/opencore_legacy_patcher/datasets/amfi_data.py b/opencore_legacy_patcher/datasets/amfi_data.py new file mode 100644 index 0000000000..3a0ab9bfa9 --- /dev/null +++ b/opencore_legacy_patcher/datasets/amfi_data.py @@ -0,0 +1,63 @@ +""" +amfi_data.py: AppleMobileFileIntegrity Bitmask Data +""" + +""" +Within AppleMobileFileIntegrity.kext, Apple has a bitmask-based boot-arg (ex. amfi=128) +Below information is from reversed values in 13.0 Beta 6's AppleMobileFileIntegrity.kext +Currently only 'amfi=3' has been used by Apple publicly +- 0x3 used in 11.0.1 dyld source: + - https://github.com/apple-oss-distributions/dyld/blob/5c9192436bb195e7a8fe61f22a229ee3d30d8222/testing/test-cases/kernel-hello-world.dtest/main.c#L2 +""" + +import enum + + +class AppleMobileFileIntegrity(enum.IntEnum): + # Names set are solely for readability + # Internal names are unknown + AMFI_ALLOW_TASK_FOR_PID: int = 0x1 # Allow Task for PID (alt. amfi_unrestrict_task_for_pid=0x1) + AMFI_ALLOW_INVALID_SIGNATURE: int = 0x2 # Reduce sig enforcement (alt. amfi_allow_any_signature=0x1) + AMFI_LV_ENFORCE_THIRD_PARTY: int = 0x4 # Don't mark external binaries as platform binaries + AMFI_UNKNOWN_1: int = 0x8 + AMFI_UNKNOWN_2: int = 0x10 + AMFI_UNKNOWN_3: int = 0x20 + AMFI_UNKNOWN_4: int = 0x40 + AMFI_ALLOW_EVERYTHING: int = 0x80 # Disable sig enforcement and Library Validation (alt. amfi_get_out_of_my_way=0x1) + +""" +Internally within AMFI.kext, Apple references 0x2 and 0x80 as both 'Disable signature enforcement' +However 0x80 is a higher privilege than 0x2, and breaks TCC support in OS (ex. Camera, Microphone, etc prompts) + +Supported boot-args within AMFI.kext, last compared against 13.0 Beta 6 + + Within _initializeAppleMobileFileIntegrity(): + - amfi_unrestrict_task_for_pid=0x1 + - amfi_dev_mode_policy=0x1 + - amfi_allow_any_signature=0x1 + - amfi_get_out_of_my_way=0x1 + - amfi_unrestricted_local_signing=0x1 + - pmap_cs_unrestricted_local_signing=0x1 + - amfi_ready_to_roll=0x1 + - cs_enforcement_disable=0x1 + + Within AMFIInitializeLocalSigningPublicKey(): + - -restore + + Within macOSPolicyConfigurationInit(): + - amfi_force_policy=0x1 + - amfi_block_unsigned_code=0x1 + - amfi_force_cs_kill=0x1 + - amfi_hsp_disable=0x1 + - amfi_hsp_logging=0x1 + - amfi_allow_bni_as_platform=0x1 + - amfi_allow_non_platform=0x1 + - amfi_prevent_old_entitled_platform_binaries=0x1 + - amfi_allow_only_tc=0x1 + - amfi_allow_only_tc_override=0x1 + + Within configurationSettingsInit() + - amfi_enforce_launch_constraints=0x1 + - amfi_allow_3p_launch_constraints=0x1 + - BATS_TESTPLAN_ID="Custom Team ID" +""" \ No newline at end of file diff --git a/data/bluetooth_data.py b/opencore_legacy_patcher/datasets/bluetooth_data.py similarity index 89% rename from data/bluetooth_data.py rename to opencore_legacy_patcher/datasets/bluetooth_data.py index da76bf2380..7409aa10f3 100644 --- a/data/bluetooth_data.py +++ b/opencore_legacy_patcher/datasets/bluetooth_data.py @@ -1,3 +1,7 @@ +""" +bluetooth_data.py: Enum for Bluetooth Chipsets +""" + import enum diff --git a/data/cpu_data.py b/opencore_legacy_patcher/datasets/cpu_data.py similarity index 93% rename from data/cpu_data.py rename to opencore_legacy_patcher/datasets/cpu_data.py index 49a6766b2e..fde9221a49 100644 --- a/data/cpu_data.py +++ b/opencore_legacy_patcher/datasets/cpu_data.py @@ -1,3 +1,7 @@ +""" +cpu_data.py: CPU Generation Data +""" + import enum diff --git a/data/css_data.py b/opencore_legacy_patcher/datasets/css_data.py similarity index 99% rename from data/css_data.py rename to opencore_legacy_patcher/datasets/css_data.py index 76cd98835e..49ca8735fe 100644 --- a/data/css_data.py +++ b/opencore_legacy_patcher/datasets/css_data.py @@ -1,4 +1,9 @@ -# Comprised of https://github.com/sindresorhus/github-markdown-css and additions for OCLP +""" +css_data.py: CSS data for project's update window + +Comprised of https://github.com/sindresorhus/github-markdown-css and additions for OCLP +""" + updater_css = """ diff --git a/data/example_data.py b/opencore_legacy_patcher/datasets/example_data.py similarity index 99% rename from data/example_data.py rename to opencore_legacy_patcher/datasets/example_data.py index 99a1fc0864..d0a6dea874 100644 --- a/data/example_data.py +++ b/opencore_legacy_patcher/datasets/example_data.py @@ -1,6 +1,9 @@ -# Example Hardware probe of multiple models -# To be used when running validation tests -from resources import device_probe +""" +example_data.py: Sample Hardware probes, for use in OpenCore Legacy Patcher validation +""" + +from ..detections import device_probe + class MacBook: diff --git a/data/model_array.py b/opencore_legacy_patcher/datasets/model_array.py similarity index 98% rename from data/model_array.py rename to opencore_legacy_patcher/datasets/model_array.py index 3f7fa69e28..ff76d01d87 100644 --- a/data/model_array.py +++ b/opencore_legacy_patcher/datasets/model_array.py @@ -1,5 +1,8 @@ -# Lists all models and required patches -# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk +""" +model_array.py: Datasets for different models +""" + + SupportedSMBIOS = [ # MacBook "MacBook5,1", diff --git a/data/os_data.py b/opencore_legacy_patcher/datasets/os_data.py similarity index 99% rename from data/os_data.py rename to opencore_legacy_patcher/datasets/os_data.py index bc6e51655d..3e16bf5faa 100644 --- a/data/os_data.py +++ b/opencore_legacy_patcher/datasets/os_data.py @@ -1,6 +1,11 @@ -from curses.ascii import isdigit +""" +os_data.py: OS Version Data +""" + import enum +from curses.ascii import isdigit + class os_data(enum.IntEnum): # OS Versions, Based off Major Kernel Version diff --git a/data/pci_data.py b/opencore_legacy_patcher/datasets/pci_data.py similarity index 99% rename from data/pci_data.py rename to opencore_legacy_patcher/datasets/pci_data.py index 53a81e9792..35f5585adb 100644 --- a/data/pci_data.py +++ b/opencore_legacy_patcher/datasets/pci_data.py @@ -1,4 +1,8 @@ -# Array of Device IDs for different devices +""" +pci_data.py: PCI Device IDs for different vendors and devices +""" + + class nvidia_ids: # Courteous of envytools as well as MacRumors: # https://envytools.readthedocs.io/en/latest/hw/pciid.html diff --git a/data/sip_data.py b/opencore_legacy_patcher/datasets/sip_data.py similarity index 99% rename from data/sip_data.py rename to opencore_legacy_patcher/datasets/sip_data.py index 393988d7ef..74a026bb11 100644 --- a/data/sip_data.py +++ b/opencore_legacy_patcher/datasets/sip_data.py @@ -1,4 +1,10 @@ -from data import os_data +""" +sip_data.py: System Integrity Protection Data +""" + +from . import os_data + + class system_integrity_protection: csr_values = { # Source: macOS 11.4 (XNU's csr.h) diff --git a/data/smbios_data.py b/opencore_legacy_patcher/datasets/smbios_data.py similarity index 99% rename from data/smbios_data.py rename to opencore_legacy_patcher/datasets/smbios_data.py index 78170dff21..011b2100ec 100644 --- a/data/smbios_data.py +++ b/opencore_legacy_patcher/datasets/smbios_data.py @@ -1,24 +1,35 @@ -# Defines Model Data -# Terms: -# AAPL: AppleInternal Model (ie. not released to public) -# Board ID: The board ID is a unique identifier for the motherboard. -# Firmware Features: Hex bitmask denoting supported abilities of firmware. (ie. APFS, Large BaseSystem, etc.) -# Secure Boot Model: T2/Apple Silicon Model Identifier -# CPU Generation: Stock CPU supported by the board (generally lowest generation) -# Wireless Model: Driver used for wireless networking -# Bluetooth Model: Chipset model -# Screen Size: Size of the screen in inches (generally lowest size if multiple in same model) -# UGA Graphics: If model needs UGA to GOP conversion -# Ethernet Chipset: Vendor of the ethernet chipset (if multiple unique chipset within Vendor, chipset name is used) -# nForce Chipset: If model uses nForce chipset -# Switchable GPUs: If model uses a GMUX -# Stock GPUs: GPUs variations shipped +""" +smbios_data.py: SMBIOS Dictionary for model data +""" -# Reference: -# https://github.com/acidanthera/OpenCorePkg/blob/master/Library/OcMacInfoLib/AutoGenerated.c +""" +Terms: + AAPL: AppleInternal Model (ie. not released to public) + Board ID: The board ID is a unique identifier for the motherboard. + Firmware Features: Hex bitmask denoting supported abilities of firmware. (ie. APFS, Large BaseSystem, etc.) + Secure Boot Model: T2/Apple Silicon Model Identifier + CPU Generation: Stock CPU supported by the board (generally lowest generation) + Wireless Model: Driver used for wireless networking + Bluetooth Model: Chipset model + Screen Size: Size of the screen in inches (generally lowest size if multiple in same model) + UGA Graphics: If model needs UGA to GOP conversion + Ethernet Chipset: Vendor of the ethernet chipset (if multiple unique chipset within Vendor, chipset name is used) + nForce Chipset: If model uses nForce chipset + Switchable GPUs: If model uses a GMUX + Stock GPUs: GPUs variations shipped + +Reference: + https://github.com/acidanthera/OpenCorePkg/blob/master/Library/OcMacInfoLib/AutoGenerated.c +""" + +from ..detections import device_probe + +from . import ( + cpu_data, + os_data, + bluetooth_data +) -from resources import device_probe -from data import cpu_data, os_data, bluetooth_data smbios_dictionary = { "MacBook1,1": { diff --git a/data/sys_patch_dict.py b/opencore_legacy_patcher/datasets/sys_patch_dict.py similarity index 99% rename from data/sys_patch_dict.py rename to opencore_legacy_patcher/datasets/sys_patch_dict.py index 417b410dc3..0227a10bbf 100644 --- a/data/sys_patch_dict.py +++ b/opencore_legacy_patcher/datasets/sys_patch_dict.py @@ -1,9 +1,10 @@ -# Dictionary defining patch sets used during Root Volume patching (sys_patch.py) -# Copyright (C) 2022-2023, Mykola Grymalyuk +""" +sys_patch_dict.py: Dictionary defining patch sets used during Root Volume patching (sys_patch.py) +""" import packaging.version -from data import os_data +from . import os_data class SystemPatchDictionary(): diff --git a/data/usb_data.py b/opencore_legacy_patcher/datasets/usb_data.py similarity index 94% rename from data/usb_data.py rename to opencore_legacy_patcher/datasets/usb_data.py index 2ffb7f1944..affdfdc98c 100644 --- a/data/usb_data.py +++ b/opencore_legacy_patcher/datasets/usb_data.py @@ -1,7 +1,12 @@ +""" +usb_data.py: USB Device IDs for different vendors and devices +""" + + class AppleIDs: # All top case devices use Vendor ID 05ac Modern_AppleUSBTCKeyboard = [ - 0x223, + 0x223, 0x224, 0x225, 0x230, @@ -53,7 +58,7 @@ class AppleIDs: 0x22a, 0x22b ] - + AppleUSBTrackpad = [ 0x20e, 0x20f, @@ -75,7 +80,7 @@ class AppleIDs: ] AppleUSBMultiTouch = [ - 0x223, + 0x223, 0x224, 0x225, 0x230, diff --git a/data/video_bios_data.py b/opencore_legacy_patcher/datasets/video_bios_data.py similarity index 99% rename from data/video_bios_data.py rename to opencore_legacy_patcher/datasets/video_bios_data.py index ef7d2d0aa0..3ea6623a2b 100644 --- a/data/video_bios_data.py +++ b/opencore_legacy_patcher/datasets/video_bios_data.py @@ -1,11 +1,16 @@ -# iMac MXM adopted legacy video BIOS for device property injection -# create by Internetzel and Ausdauersportler -# -# technical details on -# https://github.com/Ausdauersportler/IMAC-EFI-BOOT-SCREEN -# recipe to build a iMac compatible NAVI vBIOS -# https://github.com/Ausdauersportler/IMAC-EFI-BOOT-SCREEN/wiki/ObjectInfoNavi -# +""" +vbios_bios_data.py: VBIOS data for iMac MXM +""" + +""" +iMac MXM adopted legacy video BIOS for device property injection +create by Internetzel and Ausdauersportler + +technical details on +https://github.com/Ausdauersportler/IMAC-EFI-BOOT-SCREEN +recipe to build a iMac compatible NAVI vBIOS +https://github.com/Ausdauersportler/IMAC-EFI-BOOT-SCREEN/wiki/ObjectInfoNavi +""" RX5500XT_64K = "55AA70E93703000000000000000000000000000000000000E8020000000049424D70D08E000000000000000000000004203736313239353532300000000000000000000000000000C00200000000000031302F31322F32302030353A3330000032000000E9250400E92F040000008C010A000000000000000B000E81871F50000000000001000100013088791E45A879140210BDC16F1CCFF9FF1F000000000000C4AFF83F000000000000000000407338AB467344730C0005003103D031375500F8801042F0DF03002C232020024802488CE600001EA8000F8008F03EA768747871782100210001002CC04C60192000300003800C0C00003610075280180C0E0A00000004F002000000080000000000084018107001000020000000040000001C040000C800000030000000000000084000000000000000000000001C32001C5E049000000000000000000000000000000000E42709401018006400000000C098070000407A01A000280000008010900118000008008081470100F0A11F11300000000020000000000000003131332D454D32344738472D533030004E4156493134005043495F45585052455353004744445236000D0A4E41564931342047616D696E6720585458204131204B394131325143412E534C42203230323020323333332F31343937342020202020202020202020202020202020202020202020202020200D0A000D0A200D0A0028432920313938382D323031382C20416476616E636564204D6963726F20446576696365732C20496E632E0041544F4D42494F53424B2D414D44205645523031372E3030322E3030302E3030302E303030303030004B394131325143412E534C420032313834313436200035333536363420200020202020202020200054554C5F4E41564931345F454D3234475F53414D5F4744365F38475F393557323032303130313254554C5C636F6E6669672E68000000902800020241544F4D00C0370461020D03B5016A040000000087170124E8021C92C292000074C80000504349520210407300001800000000037000021100000000414D442041544F4D42494F53009C4BB41D00000000000000000000000000000000000000000000000001000000000000000000000000000000000000001E0666506651665266536655665666570E1FA314008C0E0800B220E88F2C0BC07514A20200665F665E665D665B665A66596658071FCBE8A92DE87B2B32D28D3EC002895516E83C11E8FF10E85612E8AD02E835280BC0740CE83900E88353E8FB10E8D853E8A900B480E8752B8AC766C1E0108AE3B02066A3D08EE8AC02E80E11E8A22D665F665E665D665B665A66596658071FCB2E8B1E0800833E4904007504891E47041E2E8E1E3F049CFA66C706080165F000F0C70640006A04891E4200C706B4016A04891EB601C7067C00B25C891E7E00C7060C01C560891E0E01C706A804E456891EAA042E8E1E47048BC3A3E656A3F656A308579D1FC3504D49446A041647000000A000B000B800C000000000BB0000E8611066C1E810A3EE02BB0B00E854108D3EC00266894518C300E8D02C80FCA07505E83D00EB1180FC4F7505E8BD41EB07E81247EB02B401E8D72CCFE8AE2CE82000EB02B401E8C92CCBE8A02C80FC4F7505E89741EB07E8EC46EB02B401E8B12CCB1E0666506651665266536655665666570E1F3C0475292EA11A0066C1E0102EA118008D36B2018A3C80EF30B3028BEC895E0C89460466C1E810894600E928013C057518E8262AE8F9292EA108008BEC895610894600895E04E90C013C067532E8880F66D1E08BEC894614BB0200E8920F884618E87C0F6689460CBB0900E8820F33C0668946002E8B16EE02895610E9D6003C0B75240ADB7511B98000BB02008BEC895E0C894E14E9BD008AC7E8D000E834010F84A900E9AE003C17751DE831127406E88B0DE80C17E8EE09E8FA0E33C98BC88BEC894E14E98D003C1875450AFF7510E8B8118BEC89460CE83B0A894E10EB75E8FC117568BB001CE82C2B660BC0745D23C97459E8D011BE001CE8200F744EBE001CB040E86F0FE881118BEC89460CEB443C82751A80FB0575150AFF750AE8C5108BEC894614EB2DE892107418EB263C8E751280FF01740880FF02750880C102E8EB10EB108BECC6461902EB0F8BECC6461901EB0732E48BEC886619665F665E665D665B665A66596658071FC3518AC8B80100D3E059C3E84A2BC30C01C35051B0B6E643B033E642B005E642E4618AE00C03E6618AC4B9C800E81627E6615958C3001E560E1F803E0200807605C6060200808A0E0200C1E109FCC60621000033F632E4AC02E0E2FBF6D4FEC4882621005E1FC300570BC0750FE82A0C7425E82400F6C30474F3EB118BC8E8152523C17412E81100F6C304740A5F8D5C28E84C060BF6C35FC350E8DF0BE86724E875240AC974690AED74108ACDB502E81726B1028D9C4801E89429E87602F6C3047408E8F20CE8D82274458D5C28E869005683C608E8A4225E80FD02751151E804185980FB00754D51B508E8E805598ADD33C9E8F5160AC0753BE837028AEB8D5C2880CD02E83B00740380CD04E8C6058D9CA600E894290AC0741A5683C608E85A225E8ADDB98000E8C016E8D804740533C9E8A105E8FC0158C351B94900E8B42559C351E81A007514E8B9013C01750DB92000E82700750580C901EB0233C959C353E84629663D00FFFFFF750E83C304E83829663DFFFFFF0075005BC3505232D2E8272902D002D466C1E81002D002D483C304E2EC0AD25A58C3E8DF0A8D9C4C01E83901E88D01B513F6C308750CE8070C8AEA80FD137502B50366508D9CB8026633C08AC5E843286658A9C80E7455E86201F6C308740FE80F058D5C28E804017504E87200C3B502E82301E84601F6C30474218D5C28E84901E894037405B503E80B01E86804E8210180FD007548B502E80D01C38D9C6801B80055E85111B502E8FD00C3A90200742DB504E8E000E80301F6C3087403E8B0048D9C680156E83A268BF7E868045EE8D725E8D3008D5C28E8F725E81804C3B501E8B200B502E8BF00E8D000F6C30475108D9C6801B80055E8FC10B502E81700C3E8C600B5028D5C28E86E007502B501E80400E8E003C38D9CB402B102E8B727B502E88300C38D9C4C01E83800E88C00F6C30474238D5C28E88F00E8C5258D9C6801060E07B90700E86C2407E86300E8EE0A8D5C28E8B6258D5C28E85425B80200E8BEFEC3B96100E81224C35381C30501E8BF2724063C025BC3E810003D0104750A5383C318E8AA275BA801C35383C312E89F275BC38D9CB40232C9E83827C38D9CB402E88C27C38D9CB402B101E82627C38D9CB402B101E83427C366508D9C4801E86E278AD86658C3555751B90800BD0000BB08002BD9D1E38D584EE85327E8E301E2EE8D5C4BE84827B903008BD0BF520A8555067417668B058D9AF401E891268B45048D9AF801E89F2683C50883C708E2DF8D7C5EB9040033ED8BDFE812270BC07409E85D01E8970083C51C83C712E2E95532EDE86FFF8D5C28E84EFF3D0104751083C314E8E9262470C0E8048AE8E854FF5D8D9CA600E8D7260AC074468D9CA800E8CC263C02753B66C1E8103C0472338D9CA80032E403D88BFBB904008BDFE8AE260BC07415E8F900A98000750DE82E0083C51C555883F870730883C712490BC975DA595F5DC3200358023C000100000400033C0000088002E0013C002000518D1DE86B268D9A6801E8DC258D5D02E85E268D9A6A01E889008D5D05E851268D9A6E01E87C008D5D08E844268BC88ADC66C1C8108AD080E20F8AF0C0EE048AECC0ED068AFCC0EF0480E70380E40FC0E4040AD480E23F80E4C0C0EC020AF48BC38D9A7401E881258D9A72018BC1E878258D9A760133C08AC6E86D258D9A780133C08AC2E862258D5D0CE8E4258D9A7A01E80F008D5D0FE8D7258D9A7E01E8482559C38BC88AD466C1C8108AF080E60F8AE8C0ED048BC1E82F2583C3028BC2E82725C38D5D11E8A8258AE0BA0600C0E807740380CA808AC4C0E80324033C02750380CA403C0375128AC4D0E8A801740380E2FDA802740380E2FB8BC28D9A8001E8E624C33C01743D8BD00FB6C6243F043C8D9AF801E8D1240FB6C283C01FC1E0038D9AF401E8C1240FB6DEC1EB06C1E3022EF7A7B20B2EF7B7B00B8D9AF601E8A72483C508C310000A000400030005000400100009008D9CA600E814250AC0741F8D9CA80051B103E81800590BDB7410E8FE2432C0663D00030C0075030BDBC333DBC3665052E8E8243C02753980FC03723466C1E81032E43C04762A03C38BD083C3043BDA731FE8C7248AE080E4E0C0EC05241F38CC740832E4FEC003D8EBE30BDB5A6658C333DB5A6658C3518D9CA600E89D240AC0741B8D9CA800B112E818007410E88B2466C1E81080E4077504B001EB0232C00AC059C3665052E872243C70752B66C1E81032E483C30503C38BD03BDA731AE85A2438C8740D66C1E81032E483C00303D8EBE80BDB5A6658C333DB5A6658C35766518D9C68018BFB8BDFE83D000BC9740B668BD1E8970F83C71CEBEC66595FC3505351B90700538BDAE8102483F8005B740966C1E3108BDAE86020595B58C35153B90700E86D205B59C366505383C306E8E9235B8BC866C1E1105383C302E8DB238BC85B6658C38D9C480132C9E87023C357B92000E848205FC3E88301668BCA6652E8C406E8AA1C665A7410E83A06B300E89619663BCA7303668BD18D9CD003E899230BC075448D9C540266B8483F0000E8E822B5016681FA78690000722583C30466B878690000E8D122B5026681FAF0D20000720E83C30466B8F0D20000E8BA22B503B103E8CF01EB4566B9080000006633D2538D9C54028BD35BE83D230BC074226625FFFF000066D1E0538BDAE88A225B66C1CA10FEC266C1CA1083C20483C302E2D766C1CA108AEAB103E88801E83806A801743F8D9CAE03E8FE223C007434E8CF058AEBE85C0132EDE86301E8A2058D9CBB02E8E32233C98AC8E82801663BC2740E51E84301FEC5E8440159E2ECEB03B300C38D9CBB02E8BF22FEC88AE8E82E018D9C4003B90000E85222E8C202E8D200E80F016652E8AD05E8931B665A7504B300EB58E8F60080FD017707E8FA000AED7447E81E03E8281180FB00751DE8A705A8017407B10DE83F19EB30B501E89E05E8250FB500E89605EB21E8BF0080FD017607D0EDE8BB00EBBAE87600E8B300E8B600FECDE8B700EBAAB308C38D9C2901E835226633D28AD066B88C0A000066F7E2E83105E8171B753D66508D9C2801E816223C146658722E66508D9CD003E807220BC06658741FB908008D9CD0038BC1D1E003D8E8F1210BC07502E2ED6625FFFF000066D1E0660BC07503B8483F668BD0C38D9C2A01E8CF21240F8AE80AED7502B501C3B5008D9C3101E8BB21A8017402B501C35351E81F0032E48AC5C1E002598D9C540203D8E89E215BC3B102E81D00C3B102E80D00C3B101E81100C3B101E80100C3538D9CB802E820215BC3538D9CB802E82E215BC333C9E87F1E753C66BA37F1FFFF6633C0E8E30433C0E84703741CA9C80E74F6E83CF7F6C3047505F6C31874E9E8300050E82CF858EBDFE81C007508E831008BC1E81CF8C38D5D2866C1E3108D5C28B94900E87B1DC36650E8B5048BC86658C3665266BAFFFFFFFF33D0E88A04665AC3505352E8E0FF750933C0E8E3028BC8EB1083F902740BE82F0880FB01750383E1FD5A5B58C3566633C066BA00F0FFFFE8520766C1E610E8C4020BC07403E81C00E832075EC36652668BD0E8D2158D9C1C03E8AD208AC2E80820665AC35051E871025032C0E80004E8CC01E898008D9C4003E88D2038E8740A8AC5E8E41FB002E8E50358E8CA00E8A800E88C008D9C4C01E86E208BC88BD38D9C0003E863203BC17405B002E8C003E83BFC8D9C0003E84B158D9CD802E8A91FE88AFF66C1CE108BFE66C1CE10E89500E8D100E824038AE98D9CDC0232C9E8CC1FE80D036625FF0F0000595866BAFFFFFFFF33D0E8950633D2C35366508D9CD402E805208AC4E8601F66585BC35366508D9CD402E8F21F8AE0E84D1F66585BC3E87302E82E028ADDE893168AE98D9C3C0332C9E8771F0BDBC383EC088BECE85502E81002E819168D9C4C03E8BB1F8A4600E8151F83C408C38D9CD402E8AA1F32C0E8051FC3E80A008D9CD00232C9E83C1FC3B5008D1DE8901F668BD08D9C0203E8861F0BC0741C518BC88D9C0603E8781F66C1E0108BC159663BC27504B500EB02B502C3E82B028D9C4003B103E8FD1EE8D5F78D9C4003B102E8F11EE8950180FD007514E8A6FDE88E02E888FD668BD0E87702E88E02EB21E84A02E86C02E8730180FD02B504750B81FA74407605B50866D1EAE86E02E85F02E82B00C366525232ED83C102B80600F7E16633C98BC85A51668BC28ACF66F7E166C1E0035966F7F1668BC8665AC3B500E8EA01E8CC177503E811FD8D9C480332C9E8701EC353E85F0166C1E210E84D018D9CB802E8B91E8AE88D9CB402E8B01E8AC8E8BA148AEB5BC3575353E8D6FFE82B015BE81F15746680FD00752953E8DBFC668BD0E808F78ACD51E8E7FC8AFD59E871FF5BE8791E6625FFFF0000663BC8733932DBEB3880FD027516E86F01E8621774288D1FE8581E3D7440761E32DBEB1D80FD03751553E8D300B303E82F145BE83D1E3BC2760432DBEB0380CB015B5FC3538BF0E8141923F074098BC6E8B3178BF30BDB5BC351E815FDE80F0059C35150E8F7188BC858E8020059C35753E828190BC074098B1D83C7023BC375F78B1D83FBFF740B83C70285D974F28BC3EB0233C00BC05B5FC333C0E8C3FF7413E8A0FF8BDEB9FB00E8111A83C608E85C18EBE8BBF016B85AA5E82E1DC35366508D9C4003E8AB1D8AE866585BC38D9C6903E89E1DC38D9C6403E8961D0BC0C35366508D9CD402E8891D8AC866585BC35366508D9CD502E8791D8AC866585BC3538D5C14E86C1D8BD05BC35366508D5C16E85F1D8BD066585BC35366508D9C5003E84F1D668BD066585BC35366508D9C5403E83E1D668BD066585BC35366508D5C10E82E1D8BC866585BC36650538D9C4103E81E1D5B8AD86658C3538D5C08E8111D5BC353508D9C4C03E8061D8AC8585BC353508D9C4D03E8F81C8AC8585BC35366508D5C0CE8EA1C8BD066585BC35366508D9C0003E8DA1C6633D28BD066585BC38D5C04E8CB1CC3518D5C0432C9E8651C59C38D9C5003E8B81C668BC2E8121CC3538D9C4003B101E84B1C5BC38D9C5403668BC2E8FB1BC353518AE8E8C2FF24FD0AE8E8C2FF595BC366508D9CD802E8801C668BD06658C353665051668BC8BB0000E8E11523C20BC1E8E3155966585BC3BB0000E8CF156625CA0E0000C3E85918E8E817E8C6177506E84317E8CA17C3B001C355B301E82D1A5DC3665366BB04000000E8050033C0665BC35566C1E310BB0000E8101A5DC3E81819BB0A00E88E15C3BB0A00E87E15668BC8E80519BB0A00662BC1E87815C3E829000BC97422E814FBE824076651668BC8BB0700E85615662500FE0000660BC1E8531566590C01C332C0C3E86B020BC97506E8C3FAE8710251E8BCFA66C1E61033C0E89AFD7409E8090375F633C8EBF25823C866C1EE10C3A8107563E8E30666C1E61033C0E880FD7435E85DFD50518BC8E8F90185C15958740D50E8AAFE24033C035875E0EB0C50E89DFEA8015874D5E86AFB50E8CD0758B500E892FEEBC6E8CB01E825FDE83401B100E8410766C1EE10E88706A8207542A8407503E80F0EE86E060AC0750732C9B501E8B20EE89D01E8F7FCE830FEE816147514E862020ADB740DE818FBE87C07B500E842FEEB08E85907B501E838FEE8E600C3E8E615C3E81EFDE89F0633C9E89F016633D26633C0E86CFEE85200B1FFE8840033C0E8C8FC740AE8A5FC50E8C50758EBF132C9E8C401E8B0150BC0C3E8E6FCE867066633C066BA00F0FFFFE8330151B101E88C015933C0E893FC740AE870FC50E85B0758EBF1E8A70DE87F16C3B80200E85CFC742EB107E8CA11B80200E86CF0F6C3047512E84618833D00750AE8591583E0FDE85C15C366B802000000E8E4FDE84EF2C3E8DD13742338E176048ACCEB0638C173028AC8BB0200E8B5138AE1E8B913B104E87D110C01C30C01C351E8B313740C8ACCBB0200E897138AC48AE159C3E8F105C3E8FC05C3E826177518E88100E8DBFB80F901750E51E85306B501E832FD59E8DFFFC3E8D7FF51E8B006B500E821FD59C3B80200E8B4FB7403E82411C3E8B0043BC17C3A8BC1E8F004E8BA0E8BC851E82005E8E40459E8AD0E3BC872028BC18D5C04E82D1932C9B50FE8F80CE8EC15FEC138C172F28D5C04E89F190BC0C333C0C3BB001833C08AC2C1E00203D8C353BB0300E8F9126625FF0F00005BC35366506651668BC8BB0300E8E3126623C2660BC1E8E312665966585BC36650BB0500E8CC1225FF0F8BC86658C3E8381423C86650BB0500E8B7122500F00BC1E8B8126658C3665053BB0600E8A312A8107509BBF016E825193D5AA55B6658C3665053BB0600E8891280F101C0E10424EF0AC1E885125B6658C3536650BBF816E8FB188AC1E8561866585BC353BBF816E8EB1883E0015BC3536650BB0700E85112F6C4016658B0067402B0085BC353BB0700E83D1280E4FE80FD06740380CC01E838125BC36650BB0600E825122440C0E8068AD86658C3C3506651E871FA83EC048BEC6633C06689460033D28DBC68018D1DE889180BC074228BDFB000E8120174148BDFE885F4668B4600663BC872068BD766894E0083C71CEBD50BD2740A8D9C4C01E83CF4E988006633C0668946008DBCF40133D28D1DE843180BC074586650E8A7F03C01665874053D400673436652668BD08D5D04E82418E85D008BCA665A742F568D9C4C018BF1E814F45EB000E89F00741D8D1DE804188BD98B470666C1E0108B4702663B460072068BD16689460083C708EB9F0BD27416568D9C4C018BF2E8DCF35E538D9C620133C0E846175B83C4040BD2665958C3575351E805133B5502751866C1CA108BDA66C1CA103B5D0675090AC0740E3A451B740983C71CE2DE33D2EB028BD70BD2595B5FC3516652E8D1123A651A75090AC0740E3A451B740983C71CE2ED33FFEB000BFF665A59C3C366516652535366C1CE108BDE66C1CE10E859175B668BD0E860F33BCA720A663BCA7205E89FF8750232C05B665A6659C35657E8A7FF8BF7E835F35F5EC36650536651525756518BDEB90800E86813598D5C088BC166C1E0108AC2E86F16F6C20375248BC1247FBFF71A803DFF0F840F013A05750D668B450166B900050200E9960083C705EBE3F6C20174258BC1E870010F84EB0033C98ACC8AD00AC075128D5C086625FFFF000066C1E008E81E16EBB28AE18ACA80E10CC0E90280E2F0C0EA048AEA80FC70722A80FC75732580EC708AC432E450E830028BD85838D8720533C0E99C00E82802E883160BC00F849000EB1B32C0E8E6FE0F8485008D5C168B05E8E2158B450666C1E0108B450250E8480B66C1E1108BC8588D1CE8B01566508D5C04668BC1E8A515665866C1E8106681E1FFFF000066F7E166508D5C06E82D168BC8665866D3E066C1E810408D5C14E89315BF571B83F9017411BF5F1B81F901017408BF671B83F90275158D5C0C668B05E859158D5C10668B4504E84F150BDB5E5F5A66595B6658C3004001900101400190010280029001038002900104400190010540019001068002900107D0025E010D400190010E800290010F80025E011080025E01118002E001128002E00113800290012320049001322004B002332004C002628002E001FF050A050505000000050B060505000000081008080800000056E8CF1280E4013B04740983C604E2F733C0EB058B44020BC05EC3575350E8B21283E90AE8E00083F8057603B80500D1E003C8FBA583C602E2FAB8FFFFAB585B5FC36653516652E84100E8770066C1E810660FB7D866B80000000366D3E86633D266F7F3E8F109665A59665BC3536650BB0700E86A0E0AC066585BC3536650BB0700E85B0EA80166585BC35366508D5C06E8D8148AC866585BC351B90800E82A1159C3538D5C08E8C21424035BC38D5C09E8B814C35153B1018AE88D5C08E84F145B59C3538D1CE8A2145BC3538D5C04E899145BC3538D5C16E890145BC353665233C0E8C2FC665A751BE834007416E815004083F805730DE8D11348E80F00668BC2E8C7135BC3BB001EE85F14C3BB081EC1E00303D8C3BB001EB93200E89610C351E8E2FF0BC074128BC8BB081EE83B14663BC2740783C308E2F30BDB59C3C300C300BB20DFE8E333E88DF6B501E8E507C3BB00DFE8D433E87EF6B500E8D607C380F900750AE84A108AC8B502E81D090BF6742EE862F6B50151E8C00759E8C3075633F6B500E82D075EB501E8CEF6E8FB08E8C409E841F68D9C0003E8AC07E8F50766C1CE10B501E80B07E800FFA840750732C0B501E87E0866C1CE10C3E818F6B501E84B07B500E87907E8DC07B10FE8690AE82600C3E85200E80CF6B500E82F07B500E85D07E881F6E8C60F38C1740A80F90B7405B503E89208C3B110E83B0AE8B3F580FD007406B101E8A40AC3E8A60580FD017507B502E8D505EB03E8F301B10DE8160AB103E85400C3E8D5F50BD27405B100E8420AB102E84200E85BF6A8017412E870F580FD00750AB10CE8EB09B002E89104B100E8570AB10DE81F00C3B107E84C0AE89BF50BD2750CE809F6E8EB0B7509E8F20AC3B107E8FC09C3E8F7F5E8D90B752451E8270A5980F90C751A33D25683C608E8020C5E0AC0750CB90A00E8620F4283FA1E75E8C380FB010F84C500E8A50566C1E1108D9C3501E8AB12A801740551E82B0459E868F5B004E89C0566BA50014050E87605E8B80A757E66BA5001504F8D9C2D01E87F1224063C027502B602B005E87405E854058D5C2803D8E8910A75570AFF7509B00AE85E0532DBEB4A5133C98ACFE8350503C8E83A0559B007E8470566BA5001103033DBE8640A740F518AEB8D9C4401B102E8D01159EB61E80B0566C1C9102BC166C1C1103D80000F8276FFB008E81205EB43518AEB8D9C4401B102E8A6115966BA5001103033DBE8200AEB2C8D5C2803D9538AE9B132515FE8AEF48AE9B1A0BA0080E8DA0980FF015B740AB1A2E8CF0980FF017503B000C3B001C351B10CE8D2FE59B001E8BB045683C608E8E20A5E0AC07504B310EB3FB002E8A604E838007411B003E89C04B001E810037529E82700752466BA0C0090438D9C3001E8AB0966BA200090418D9C3401E89E09E8BD03B009E86E0433DBC3E82FF466BA000090478D9C2801E88309C3B10CE866FEB100E89408B101E88F088D9CAC0366B800000000E89C10B001E8B202740AB504E8CB03B308E93F01B108E8F607E8D202B109E8EE07E8C5018D9CB8036633C0E87110E86001B99001E8980DB001E86302B502E88D03E87401E89F03E8E001B503E87F0333C9E80001F6C5017534B502E87003E82001F6C5047408B501E86F03E9CC008AFD80E703E8E80080E30338FB750DE84C017508B502E85303E9B000E86701FEC1E885F338D975BB8D9CAC03E8A2103C037405E8ED00EB9B8D9CB0036633C0E8EF0F8D9C2A01E88810A840740CB113E84F07B003E8DA01EB0AB10AE84307B002E8CE01B504E8F802E8DF00E80A03E84B01B505E8EA0233C9E86B0080FD077505E88600752E51B504E8D50259F6C5017507B503E8D602EB34E878008AD5E8E600E8700038EA750CE8B4007507B502E8BB02EB19FEC1E8F1F238D975BC8D9CAC03E80E103C047505E85900EB9CB000E86001B10BE8CB068D9CAD03E8F40FB3000AC07402B308C38D9CC003E80F008AE8C3538D9CC403E804005B8AD8C351E8D10FC0E102D3E8240F59C38D9CC203E8C10FA801C38D9CB803E8730FC38D9CB803E8530FC333C933D2E8E9FF38D576028AD5FEC1E874F238D972EE33C98AEA8D9C5C03E8310FB10BE8CE06C3E84DF28D9CB803E87D0F66BA03018083E89E07C351538D9CB003E8260FFEC5E8090F80FD067207B502E8F60133C95B59C36633C08D9CB003E8AC0EC332EDE865FF80E30CC0EB02B7032AFBC0E3038AEB80FB18720380CD20E84BFF80E30338FB72028ADF80FB03750380CD040AEBE860FFC3E8DBF18D9CC00366BA02029045E82F07C3E8CAF166BA000190428D9CB403E81E07E8BAF166BA030190458D9CB803E80E07E8EEF1E8D407753BE8A2F166BA0A0190408D9CBF03E8F6068D9C2801E8C50E3C147220E887F166BA1000904F8D9CD003E8DB06E877F166BA150190408D9CCC03E8CB06C3E866F166BA02018050E8BE06C3E848F18BC26633D2B98C0AF7F1C3E84BF166BA00068050E8A306C3E83EF166BA11018050B004E89406C3E82FF166BA000690408D9CC803E883068D9CC803E8520EC3E8BBFF3C06740E3C0A740A3C1474063C1E740233C0E811F18AE380CC8050E8F9F05866BA00018061E8500633C9E884F00BC07402B5108D9CBC03E8B80D8AC5E8D8F066BA07018050E83006E810F1E8F60675498D9C4803E8F70D0AC0740EE8B9F066BA0A018050B001E80F068D9C2801E8DE0D3C1472258D9CD003E8D30D0BC0741AE83CEC32C98D9CCC03E8670D8AC5E887F066BA15018050E8DF05C38D9CB403B90E00E8F409E8A3FEE88FFEE838FF3C01751CE8D2FD741733C9E8A8FD80FD07750DFEC1E861F038D975EFB501EB02B500E80100C38D9CAC03B102E8160DC3518D9CAC0332C9E80B0D59C3518D9CAC03B101E8FF0C59C38D9C3201E8520D24077515B964008D9CAC03E8440D3C027403B99001E8CA09C332E4B10433D2F6E18BC8E8C709C3518D5C14E8240D66C1E010E8A40159C3538D9C4401E8130D5BC35366508D9C4401E8070D8BC1E8620C66585BC353518D9C44018AE8B103E8950C595BC333C9E82D0938C17305B500E88C00B500E88000FEC1E81A0938C172E6B1148AE9E8120938C17405B503E8E301FEC1E8FB08041438C176E7C383EC0C8BEC0BF6741EE802F866C1C810668946008D5C04E89C0C668946048D5C08E8920C88460A894E088CD066C1E0108BC4BB2B00E8D80783C40CC383EC048BECB002884601884E008CD066C1E0108BC4BB2500E8B90783C404C3BB2300E80800C3BB1700E80100C383EC048BEC894E008CD066C1E0108BC4E8940783C404C3BB2200E8E3FFC3BB2700E8DCFFC3BB2C00E8D5FFC3E81E0C66A90000FFFF744083EC188BEC5551B9040083C302E8060C6689460083C50483C304E2F183C304E8F40B66C1C81066894600595D884E148CD066C1E0108BC4BB3100E8330783C418C3E83FEE8D9CD002E8CB0B8AE8BB2100E876FFC38D9C3C03E8BB0B8AF8E801EE8ADD538D9C4203E8AC0B8AE85BE813EEE8B0EEE896047502B30183EC048BEC884E00887E01885E02886E038CD066C1E0108BC4BB2A00E8D70683C404C383EC108BEC663DF0FFFF03760666B8F0FFFF03668BC86633C066894604668946006689460866B8000000D0660BC16689460C8CD066C1E0108BC4BB3500E8930683C410C383EC088BEC894E0066895602895E068CD066C1E0108BC4BB2D00E8720683C408C33DC07F7604B8C07FC383C03F24C0C351E8010B6633D2B90A00F7F18BC8E8F40A03C16625FFFF0000593D10277303B81027C332D2C380FD027525E84EEE66BB00080000E89A00E842EE66BB03080000E88E006633D266BB01080000E88200C380FD0375106633C08AC16633D266BBFF000000EB365133D2E8E5EC8AD566C1E210E81EED8AF28AD1668BC2660D00000080E859ED80FB047606660D00000008E88FEDE8DDEC6633DB8AD95983EC108BEC6689460466895E08668BC26633D266BB6400000066F7E366894600BB0C008CD066C1E0108BC4E896058BECB30183C410C383EC108BEC6689560066895E04BB2E008CD066C1E0108BC4E87305B30183C410C3C353516650B9687480FB03740BB9A08C80FB007503B978696633D28BD16658595BC36652B30066F7C20000FFFF751A80FD13741580FD147410B30180FD0E7409B30380F9037402B302665AC3B51180FA23740780FA227402B500C3B50280FA23740780FA227402B301C332C980FD007508C746000B01B101C35033C0E87301041489460058B101C3C38BDAB72280FE217402B721C30C01C3E8780966C1E8100BC0741C5383C306E869095B3DE001720F5383C318E85C095BA88075030C01C332C0C3B50CC3B502C350E82601B1030AC07404B10802C858C380FA227505C746007869C3E8EF0080FDFF743583EC0C8BEC884E01886E0080F90F7505E82400EB0F80F910750A8D9C4803E807098846028CD066C1E0108BC4BB0400E8500483C40CC3C36653E8A4EB668BC26633D266BB8C0A000066F7F3665B8AE8886E098D9C4003E8CF0888460288660366C1E810884608E866EB66895604C383EC208BEC80F904750A884E0132C0884600EB56E830EBE87F00884600884E01E8A4EB88560A80F901741880F90B753A8D9C5C03E88308884602E824EB66895604EB27E83DEB886E08E815EB66895604E83FEB885E03E8ACEA886E0251E81C008ACDB001D2E0598846098CD066C1E0108BC4BB4C00E89C0383C420C38D9C3C03E8370832ED3C03740C3C0972093C0E77052C088AE8C3B5FFC35232C080EE2180FA1E7410B00280FA207409B00480FA217402B00602C65AC3C383EC088BEC897E00895E02895604894E068CD066C1E0108BC4BB3600E83C038BEC8B5E028A7E0183C408C35633F666F7C200008000750A5033C08AC68BF032F65853BB041FE81907668BC2BB001FE810075B66F7C200001000750233DB8BD366C1E210BA001F83EC088BEC66895600884E048AC5FEC8884607C6460500C64606008CD066C1E0108BC4BB4E00E8CC028BEC8A5E058A7E0683C4080ADB743251B9900180FB20740580FB807513B90A008BC60AC0740AB990013C017403B9E803E8CF03598BC6FEC48BF080FC0676980ADB5EC38D5C04E829078BD0B502E814007411B50180FA13750AE8610080FA137502B502C380FA14C3E8F9FF740380FA0EC380FA05C380FA02740380FA04C380FA01740380FA02C380FA027503B201C380FA047503B203C3C3B508E8D8FF7402B504C38D5C09E8CA068AC80AC9750332C0C3B502E8DA028AC52402D0E8C38D5C08E8AF068AD0B60183EC108BEC8956028CD066C1E0108BC4BB4F00E8EF018BEC8A560483C410C35383C34CE853065BC35383C34CE8A5055BC356E896018B4438837D20005EC352500FBCD832FF80FB017505BB0024EB0CFECBB80004F7E30500208BD8585AC357E85600740A8B5D02E808000BDB5FC333DB5FC352510BDB741B56E8360103DE5E33C98A4F01803FFF74083A07740603D9EBF033DB0BDB595AC35651E8150132C98D7C083B5D04740C83C710FEC13A4C0672F133FF0BFF595EC35651E8F50032C98D7C083B1D740C83C710FEC13A4C0672F233FF0BFF595EC35651E8D60032C98D7C083B450C740C83C710FEC13A4C0672F133FF0BFF595EC35750E8DBFF8AC38B5D02E86EFF585FC35332C9B301E8E8FF74038A4F020AC95BC35332EDB302E8D7FF74038A6F020AED5BC350578BDAE868FF750433DBEB0DB0148B5D08E834FF74F28B5F025F58C366505351578D1C6625FFFF0000E8B5048BD8E83B0023C37431E875FF0BFF742A6650668B45048D5C0CE899046633C08B058D5C04E88E046658E885FFE893FF8D5C086633C08BC1E87B045F595B6658C356E818008B44045EC356E80F008944045EC3C3BFE0028B3D8B7D0CC3BEE0028B348B7430C31E0E1FBFE0028B3D8B7D0E83C7041FC3BEE0028B348B7410C3BFE0028B3D8B7D2683C704C3BEE0028B348B741AC3BEE0028B348B743AC3BFE0028B3D8B7D0A83C704B90700C3E80100CB83EC068BEC8946006633C0C646040089460206528AD38BC5E8CD165A0783C406C3E880FF66F7451001000000C350E873FFB8010009451058C3E868FF884510C3665383EC488BEC66895E0066894E048CD066C1E0108BC4BB0000E8A3FF83C448665BE86A01E8A40183EC1C8BECC64601078CD066C1E0108BC4BB0D00E881FF83C41CE80E00BB0400E88FFD66C1E810E8A7FFC383EC1C8BECC64601088CD066C1E0108BC4BB0D00E856FF83C41CC3E8F3FE668B5D08668B4D0CC356E826FF668B44085EC383EC048BEC894E008CD066C1E0108BC4BB3800E826FF8BEC8A6E0283C404C3C3B006C3B001C3B005C3B008C35366506633C0E80D0383C304E2F866585BC332C0C3FCE89D0366C1CB10E8F60266C1CB106681C304000400E2E9C3FC66ADE8E20283C304E2F6C3FCE8780366AB83C304E2F6C36650B86400E810006658C36650B850C3D1E1E803006658C352F7E18BCAE8690166538BD966C1E3108BD866B804B10300B20066EFB2046633C066EF66B808B10300B20066EFB20466ED33C96603D8730A66ED66A90000008075F666ED663BC3730C66C1E8103BC172048BC8EBED665B5AC3BB42ECE8C7026633D266BB6400000066F7F3C3665053BB0700E857FC2500023500020BC05B6658C36651B301E8C400E802FE6633C98B4C0866C1E00A0BC97503B92000662BC1E8EBFD66894404894C086659C3561E0E1FE8DAFD668B440466C1E00A1F5EC3C3BEE0028B348B741E83C604B91C00C356E8A6FD8A6C335EC356E89DFD5381C30901E875028AE85B5381C30001E86A025B8AC5668944345EC356E87DFD668B44345381C30801B1018AE8E8F1015B5381C30001B1018AECE8E4015B5381C3020166C1E810E8AB015B5EC356E84CFD8BFE83C7045EC356E841FD8A442480FD007405886C330C028844245EC332C0C3665383EC048BEC8CD066C1E0108BC466895E00BB0600E84DFD8BEC668B460083C404665BC366508CC83D00C0750CBAC303EC8AF00AF67402EB0E532E8B1E1400B220E8D6008AF45B32D266ED6658C32E8B1E1400C30BC9751A4B7416433BDA77098BC88BC22BD2F7F391F7F38BDA8BD12BC9C33BCA721A75103BD8770C2BC38BD82BC92BD2B80100C32BC92BDB9387CAC355562BF68BEE03DB13C97211453BCA72F577043BD876EFF813F64D7820D1D9D1DB2BC31BD1F572F003F64D780CD1E9D1DB03C313D173F1EBDF03C313D18BD88BCA8BC633D25E5DC39350920BC07402F7E2910BC07404F7E303C858F7E303D1C3526650B4808AC766C1E0108AE38AC224FCBAF80C66EF66585AC352BAFC0C66ED5AC352BAFC0C66EF5AC3E831FF9CFAE8CEFFE8E5FF9DC3E824FF9CFAE8C1FFE8E0FF9DC35266536650E806006658665B5AC366C1E31066C1EB0EE8D7FEE89301C3665066C1E31066C1EB10E801FE6603D86681CB000000806658C3526653E80400665B5AC36650E8AAFEE8D4FFE863016658C35251665366508ACB80E3FC80E103C0E103E88DFEE8B7FFE82D0166D3C8585066D3C0E83B016658665B595AC3665051C0E103E8530066D3C88AC566D3C0E8A8FF596658C3665051C0E103E83B0066D3C8598AE86658C3E85F00C3E844FE66C1E31066C1EB0EE8DF00C3E835FE66C1E302E8D400C3526653E80400665B5AC3E820FEE84AFFE8C000C35166528AEB8ACB80E103C0E10380E3FCE8D9FF80F9007414668BD083C304E8CBFF83EB046692660FADD08ADD665A59C3526653E89CFF665B5AC3526653E8A1FF665B5AC36650555266508BEC8B560C895608E8C4FDB20066ED6689460A66585A5DC36650555266508BEC8B560C895608E8A6FD2EA12D03B218EFB20066ED6689460A66585A5DC3665055528BECE889FDB200668B460A66EF8B560889560C668B4604668946085A5D66586658C3665052E866FDB21866ED2EA32D035A6658C36681FBFF00000077048AD3EB09668BC3B20066EFB20466EDC36681FBFF00000077048AD3EB0A6693B20066EF6693B20466EFC3C3C3558BEC53518BF0268B5C14268B4C16E828008D66FC595B5DC353518BF0268B5C2433C9E81400595BC3558BEC53518BF0268B5C08268B4C0AEBD5525657C80600008BF0894EFE8CD08EC0268B7C268A450132E4B920002BC8B8FFFF8BD0E306D1EAD1D8E2FA8A4D0332ED8BFAE306D1E0D1D7E2FAF7D0F7D72621441C26217C1E8CD08EC0268B7C268A4D0132EDB820002BC18BC866C746FAFFFFFFFFE308D16EFCD15EFAE2F88A4D0232ED8BC38B56FEE306D1EAD1D8E2FA2346FA2356FC8A4D0332EDE306D1E0D1D2E2FA2609441C2609541EC95F5E5AC3558BEC53515257508BD8268B7F268A450132E4B920002BC8B8FFFF8BD0E306D1EAD1D8E2FA8A4D02884EF6C646F7008BFA8B4EF6E306D1E0D1D7E2FA2609471C26097F1E8D66F85F5AE9F1FE535152578BD88CD08EC0268B77268A4C0132EDB820002BC18BC8BEFFFF8BD6E306D1EAD1DEE2FA268B7F268A4D0232ED8BC6E306D1E0D1D2E2FAF7D0F7D22621471C2621571E5FE9CC0553568BD88CD28EC2268B7726803C007473803C0175588A440132E426837F1E00754C263B471C75468A046BF0038A840490260147268CD08EC0268B7726803C0974178A0432E46BF0038BC3FF940290268B77268A0432E4EBD18B44012629472626FF4726268B471C268B771EEB1A268B77268A0432E46BF0038A84049026014726E980FF33C033F68BD65E5BC3535152568BD88D7735268B54022689571426C7471600008BF0268B472033D226014714261154168CD18EC126F6472F060F850A0526807F34007522268B7716260B7714751026D1670826D1570A26D1670826D1570A8BC3E87911E9E104268A473432E4058000992689471C2689571E8BC3E8FFFEE9C70453568BD88D7735268A440232E4C1E002268B37268B3403F0268B4708268B5F0A26890426895C025E5BC35352568BD88CD08D77358EC0268A540280FA407321268B770232F6C1E202268B740403F2268B5708268B470A26891426894402E97F0080FA417512268B4708268B570A2689471026895712EB6880FA407512268B4708268B570A2689470C2689570EEB5180FA42750A268B470826894722EB4280FA43750A268A470826884733EB3380FA467512268B5708268B470A268957182689471AEB1C80FA47750A268B470826894724EB0D80FA487508268B4708268947205E5A5BC353568BD88D7735268A440232E42689471426C7471600005E5BC353568BD8268B7702268B74028A0432E42689471426C747160000268B5F0226FF47025E5BC353568BD8268B7702268B74028B342689771426C747160000268B5F0226834702025E5BC353568BD8268B7702268B74028B048B74022689471426897716268B5F0226834702045E5BC35352568BD8E870FF8BF3268B4718268B571AD1EAD1D8D1EAD1D826014714261154168BC3E82B10E94AFF538BD8268B5F0226FF47025BC3538BD8268B5F0226834702025BC353568BD8E86BFF8BF3268B572033C026015714261144168CD28EC2268B472E32C080E4063D0002750732E433D25E5BC3268B472E32C080E4063D000474EB26807F340075088BC3E82F0F5E5BC3268A473432E42689471C26C7471E00008BC3E8EAFC5E5BC3538BD8E8E2FE268B4714C1E002268B1F268B1F03D8268B07268B57025BC3E236D736ED363C37F3360B372537303736375351568BD8E8B0FE8CD28EC226837F1600752226837F1440731B268B7702268B5F14C1E302268B440403D8268B07268B5702E97B05268B7714268B471683C6C083D0FF757183FE08776C03F62EFFA47436268B4710268B5712E95405268B470C268B570EE94905268B4722EB4B268A4F3332EDBB010033D2E306D1E3D1D2E2FA8BC3E92B05268A4F3332EDB8010033D2E306D1E0D1D2E2FAF7D0F7D2E91105268B4718268B571AE90605268B4724EB08268B4720EB0233C033D2E9F30453568BD8E8F4FD8BF3268B4718268B571AD1EAD1D8D1EAD1D826014714261154168BC3E8160E5E5BC333C033D2C353568BD8E8EBFD268B7714260377228B048B54025E5BC3538BD826C6472B04E8ABFD268B4714268B57165BC3538BD826C6472B01E8BBFDEBE9538BD826C6472B00E8D2FDEBDC538BD883C335268A5F01C0EB0380E30732FF03DBFF97928F5BC35352568BD8268A472C32E48BF003F08BC3FF94AE8F268947082689570A268A472D32E48BF003F08BC3FF94C68F2689470426895706E917FD5351568BD8268A4F2B32ED8BF18A8CF68FE30A26D16F0626D15F04E2F6268A4F2B32ED8BF1C1E6028B8CD68F8BB4D88F26214F0426217706268A4F2A32ED8BF18A8CFE8FE30A26D1670426D15706E2F6268B4F08268B770A26894F1426897716E9CA0353515256578BD88CD08EC0268A472B32E48BF0C1E602268A472A8BF88A8DFE8F32ED8B84D68F8B94D88FE306D1E0D1D2E2FAF7D0F7D22621471426215716268A472A32E48BF08A8CFE8F32EDE30A26D16F0A26D15F08E2F6268A472B8BF0C1E6028B84D68F8B94D88F262147082621570A268A472A32E48BF08A8CFE8F32EDE30A26D1670826D1570AE2F6268B4714268B5716260947082609570A5F5E5A595BC35351568BD8268A4F2B32ED8BF18A8CF68FE30A26D16F0626D15F04E2F6268A4F2B32ED8BF1C1E6028B8CD68F8BB4D88F26214F0426217706268A4F2A32ED8BF18A8CFE8FE30A26D16F0A26D15F08E2F6268A4F2B32ED8BF1C1E6028B8CD68F8BB4D88F26214F082621770AE9BB025152578BD88CD08EC026807F2B00741A268A472C32E48BF003F08BC3FF94AE8F268947082689570AEB10268A472C32E48BF003F08BC3FF94BA8F268A472D32E48BF003F08BC3FF94C68F26894704268957068CD28EC226807F2B00744A268A472B32E48BF0C1E602268A472A8BF88A8DFE8F32ED8B84D68F8B94D88FE306D1E0D1D2E2FAF7D0F7D2262147082621570A8BC3E8F9FD268B4704268B5706260947082609570AEB10268B5704268B4706268957082689470A268A472C32E48BF003F08BC3FF94A28F5F5A59C353515256578BD8268A472A32E48BF08A8CFE8F32EDE30A26D1670426D15706E2F68CD08EC0268A472B32E48BF0C1E602268A472A8BF88A8DFE8F32ED8B84D68F8B94D88FE306D1E0D1D2E2FAF7D0F7D22609470426095706268B4704268B5706262147082621570AE956FE558BEC5152508BD8268A472C32E48BF003F08BC3FF94AE8F268947082689570A268A472B8846FA8BC3E8DAFC2689470426895706268A4F2D32ED8BF103F18BC3FF94C68F26894714268957168BC3E844FF8A46FA32E48BF08A8CF68FE30A26D16F1626D15F14E2F6268A572B32F68BF2C1E6028B84D68F8B94D88F2621471426215716268A472A32E48BF08A8CFE8F32EDE30A26D1671426D15716E2F6268B4714268B5716260947082609570A268A472C32E48BF003F08BC3FF94A28F8D66FC5A595DC3518BD8E856FC268A4F2B32ED8BF18A8CF68FE30A26D16F0626D15F04E2F68BC3E8AEFE268A4F2C32ED8BF103F18BC3FF94A28F59C38BD8E822FC8BC3E855FC268B4704268B7706260947082609770A268A472C32E48BF003F08BC3FF94A28FC353568BD8E8F5FB8BC3E828FC268B4704268B7706263147082631770A268A472C32E48BF003F08BC3FF94A28F5E5BC35351568BD8E8C5FB8BC3E8F8FB268B4F04E30A26D1670826D1570AE2F68BC3E846FC268A4F2C32ED8BF103F18BC3FF94A28F5E595BC35351568BD8E88FFB8BC3E8C2FB268B4F04E30A26D16F0A26D15F08E2F6EBC8528BD8E872FB8BC3E8A5FB8BF3268B4704268B5706260147082611540A8BC3E8F1FB268A472C32E48BF003F08BC3FF94A28F5AC3528BD8E83EFB8BC3E871FB8BF3268B4704268B5706262947082619540AEBCA51528BF0E81EFB8BC6E855FC268B4408268B540A268B5C04268B4C06E8DDF22689440C2689540E5A59C3528BD0E8F5FA8BC2E82CFC8BC2E85C085AC35152578BF0E8E1FA8BC6E818FC268B4408268B540A268B5C04268B4C06E81CF22689440C2689540E8CD78EC7268B4408268B540A268B5C04268B4C06E8FDF126895C1026894C12E910FD528BD0E899FA8BC2E8D0FB8BC2E8D3075AC351528BD8E886FA8BC3E8BDFB8CD18EC1268B4708268B570A263B5706750E263B4704750826C64730015A59C38BD0268B470A263B47067208750A263B5704730433C0EB03B80200268847305A59C35152578BD8268A472C32E48BF003F08BC3FF94AE8F268947082689570A8CD08EC0268A472B32E48BF0C1E6028BF88A8DF68F32ED8B84D68F8B94D88FE306D1E0D1D2E2FAF7D0F7D2262147082621570AE94DFC558BEC51525783EC068BD8268A472B32E48BF0C1E6028BF88A8DF68F32ED8B84D68F8946F48B84D88F8946F6E308D166F4D156F6E2F88B7EF48B46F68946F8268A472C32E48BF003F08BC3FF94AE8F268947082689570A8BC3E847F926894704268957068BC7F7D08B56F6F7D2262347082623570A268947142689571626217F088B46F62621470A8CD18D77358EC126803C197312268B4F04E30A26D1670826D1570AE2F6EB10268B4F04E30A26D16F0A26D15F08E2F626217F088B46F82621470A268B5714268B4716260957082609470A268A472C32E48BF003F08BC3FF94A28F8D66FA5FE9A3FC528BD8E8FDF88BC3E834FA268B4708268B570A268557067506268547047405B80300EB03B80100268847305AC3535152568BD8268A4F2D32ED8BF103F1FF94C68F2689470426895706268A472B32E48BF08A8CF68FE30A26D16F0626D15F04E2F6268A472B8BF0C1E6028B84D68F8B94D88F2621470426215706E9BDF9528BD8E8AAFF268B4704268B5706268947182689571A5AC351528BD8E891FF8CD08EC0268B7702268B7402813C5A5A745B268B7702268B7402803C6375E1268B770226FF44028BC3E821F8268947082689570A8BC3E8FAF726894714268957168CD18EC1268B5704268B4706263B470A75AD263B570875A7268B7702268B04260347148BDE268947025A59C3268B5F0226834702025A59C352578BD88CD08EC0268B7702268B74028A540184D2750826C747220000EB2F80FAFF7514268B7702268B3F268B34262B750226897722EB16268B07E8E3028BF08AC232E403C003F08B0426894722268B5F0226834702025F5AC38BD82680672FF9268B7702268B74028A440126884734268B5F022683470203C38BD8268B7702268B74028B740126897720EBE3538BD8268A472C32E424032680672FF9C1E0092609472EE94FF58BD8268B7702268B74028A440132E42689470426C7470600008BC3E84004268B5F022683470202C38BD8268B7702268B74028A440132E42689470426C7470600008BC3E80804EBD653568BD8268B7702268B74028A440132E42689470426C7470600008BC3E80604E986F453568BD8268B7702268B74028A440132E42689470426C7470600008BC3E8F003E963F453568BD8268B77028BDE268B5F028B5F0183C30326015C025E5BC351528BD8268B77022683440202268B07E8A0018BC8268B77288A440132E403C08BF103F0833C00744F268B77288A540132F68BC3E8B00126884731268B7702268B348B4404C1E80832E4247FC1E80232E4241F2680672F07C1E00B2609472E268B37268B472EC1E80BC1E00226010426C647320126894F285A59C3538BD826C64732825BC3578BD88CD68EC626807F2C05740A268A472C263A4730751E268B7702268B7402268B7F02268B3D8B740103F7268B5F02268977025FC3268B5F0226834702035FC35356578BD88CD68EC626807F3001740A268A4730263A472C7520268B7702268B7402268B7F02268B3D8B740103F7268B5F02268977025F5E5BC3268B5F022683470203EBF15356578BD88CD08EC026807F300174E5EBC3558BEC535152578BD8268B7702268B74028A0426C6473D008CD18EC126807F3D087320268B7702268A573D32F6268B7C0203FA8BF303F28A152688543526FE473DEBD5268B7F028AD032F68BF2C1E6028A94239026015502268B7F288A550180E2072688572D268B7F288A5501C0EA0380E2072688572B268B7F288A5501C0EA062688572A8A9422902688572C8D66F85F5A595B5DC353568BD8268B77028BC68B744803F08BD88B741E8BC603C383C0045E5BC353568BD8268B77028BC68B744803F08BD88B7420EBE08AC2C31607558BEC5351565783EC408BF88946B8E8D3FF8BD88946E0268B45028B5F2E03D8895EDE8346DE048BC7E89BFF8946E032F68D46B8E8C4FF8AD032F603D28B5EE003DA833F000F8465018846E98066E7F9C646EC00C746D8000066C746D000000000C746F60000C646EA01EB063C010F858C008A56E98AC232E403C08B5EE003D8833F007475268B45028B1F03D88B470432E48BC883C10932ED80E1FE83F9007407D1E933C050E2FD8BC48BD88946BA85C0744183C008268947048AC232E403C08B5EE003D8268B450203078B5EBA2689078B5EBA268B0783C006268947028B5EBA8B76F6268977068B5EBA895EF6C646EA00EB0AC646EA87EB04C646EA838A46EA32E483F8100F8F99008866EA8A46EA32E485C00F8F83008CD08B5EBA8EC0268B5F02895EE08B5EBA268B5F02803F5B754AC646EA108B5EBA268B5F06895EF68B5EBA268B1F8B470432E48BC883C10932ED80E1FE03E18B5EF6895EBA85DB74AC268B1F8B4704C1E80832E4247FC1E802C1E0028B5EB8262907EB918D46B8E8AFFD8AD08D46B8E82E008ADA32FFC1E3028D46B8FF972090E972FF837EF6000F85C9FE807EEA1074058A46EAEB0232C08D66F85F5EE90BFEC353518BD8268A4F0432EDE886E8595BC353518BD8268A4F0432EDE881E8595BC3538BD8268A470432E4E6805BC353518BD8268A4F0432EDE89ED7595BC3538BD866506652665166268B470866268B571066268B4F0466F7F1662689470C66268957106659665A66585BC3538BD866506652665166268B470866268B4F0466F7E1662689470C66268957106659665A66585BC353578BD8268B5F14E838EB8BD066C1E810925F5BC353578BD8268B4714268B57168BD887D366C1E3108BDAC1E302E836EBEBD85352578BD8268B4708268B570A9266C1E0108BC2268B5F14E85AEA5F5A5BC353528BD8268B471C268B571E9266C1E0108BC2268B5F268B5F01E839EA5A5BC35352568BF0268B5C268B5F01E8C2EA8BD066C1E810922689441C2689541E5E5A5BC3535152578BD8268B4708268B570A9266C1E0108BC28BC8268B4714268B57168BD887D366C1E3108BDAC1E3028BC1E816EA5F5A595BC38BD066C1E81092C31E0666506651665266536655665666570E1F0AC07506E80701E9A8003C017506E83701E99E003C027506E85F02E994003C03750BE891038BEC895E0CE985003C047502EB7D3C05750AE80E048BEC895610EB713C067510E88C038BEC895E0C894E14895610EB5D3C077502EB553C08750AE8D0038BEC887E0DEB493C097502EB413C0A7510E865048BEC894E14897E008C461CEB2F3C0B7502EB273C10750AE85A048BEC895E0CEB1B3C117502EB133C15750FE880048BEC895E0CEB07B84F01EB0232C08BEC894618665F665E665D665B665A66596658071FC3501E2E8E1E47048CD8A3E656A3F656A308572E8E1E3F04A3AA041F58CB0030312E303000564553410003000300000100000000000000000302110C0200009C01000034470000B93F008BDF83C704FC6633C0F366AB8BFBBE3A47B92200F3A4061F8C4F088C47108C4F188C4F1C8C4F2083C722897F0E0E1FE8F9D3B04F32E4C3565157B910006633C0F366AB5F598CDB061FC705BB00C6450207C745044000C745064000C6451B06C6451801C6451A01C6451E0166C7453E0084D7178EDBE8CDCC660BC00F84E100061F668945288CC866C1E010B8F34A6689450C81F9FF810F84C20080E503B201538EDBBE801CE8A5D15B061F0F84B10053E821D466894512C7451608108D5C0CE8BAE86689451F668945368D5C10E8ACE8668945236689453A8D5C08E89EE80AC075035BEB7BE8ECD366C1E8103D5802740D3D5E017408770AC6451708EB04C645170E2EA141048945088D5C04E86DE8668BC866C1E910D3E0894510894532B008D2E08845198D5C14E851E85B3D0003772F538BD8B8000333D2F7F35BFEC888451D8845358845348EDB5753BE801CE85DCC5B5F0BC97505061F8325FE32E4EB02B403B04F8EDB5EC30081FBFF8174680AFF75048BC3EB21F6C70875618BCBB201BE201CE8C7D07455E828D30AC0750E66C1E81080E7800AC7E8D502EB3AE8A4CE7406E815CDE864C6BE201CE8D4CB742DE8A500E82C0066BB201C001CE8EBD2BE001CE8EED266C1E8108BD832C0F6C7807402B040E804CCB04F32E4EB04B04FB403C3560633C08EC0BE201CE8E6D28BC866C1E8108BD0C1E90326890E4A04C1EA04FECA268816840426C60651040026C60650040026C60649046226C7064C0400A026C60685041026C7060C01C5608CC826A30E01075EC3010F000A000000000040050FFF000102030405060708090A0B0C0D0E0F01000F00FCBAC403B80001EFB90400B401BE9649AC86E0EF8AE0FEC4E2F6B80003EFB90900BACE0332E4BE9A498AC4EEAC42EE4AFEC4E2F5BADA03ECB91400BAC00332E4BEA3498AC4EEACEEFEC4E2F7C3BE001CE808D266C1E8108BD8E8D8D17505E8C4D17504B84F00C3B84F03C3E8C6D17453BE001C80FB00741880FB017505E804D2EB1D80FB0275108BC1E8B7D1D3E88BC8E8B4CC742EEB0880FB037524E85BD1E8A1D18BD8D3E35033C0BA00033BDA7705BAFFFFEB04F7F38BD0588BC8B84F00C332C0C3B04FB403C3000ADB75078AEFE882CDEB05E867CD8AF8B04F32E4C300E852D1742CBE001CE871D166C1E810F6C440751D0AFF7505E81E00EB0F80FF017514BB1300E8EBE5D1E88BD0B04F32E4C3B04FB403C332C0C35253665081E2FF02D1E28BC24066C1E0108BC2BB1300E81CE5BB1200E816E566585B5AC39C1E0666506651665266536655665666570E1FE834E6E88AFFE853E68BEC895610894618665F665E665D665B665A66596658071F9DCB0E07BFC88E2E8B0EC68EB84F00C3000ADB7506B704B310EB2680FB017514E859CC752153B1010AFF7402B100E86ECB5BEB0D80FB02750DE886CC8AF8C0E702B04F32E4C3B84F03C30080E3010ADB7505BB0201EB0EE822CC750E33C053E80FBB5B7405B04F32E4C3B04FB403C380FC1D7203CD42C31E0666506651665266536655665666570E1F500FB6C4D1E08BF0582EFF94E04B665F665E665D665B665A66596658071FC30E1F500FB6C4D1E08BF0582EFF94E04BC31A4C3085498566850D4D697C9B7C0E7D917D1F7F237F2C82FD828083E7838285E4858D88264FD48CCE4BCE4BCE4BCE4BCE4BCE4BA48DA771FB722E8E1E3F0480268704F3508AE080E47FE8C4013BD3750258C3BACC03ECB2B4B13026F6470901740CB2D4B120A8017549B509EB06A8017441B50B53E870410AFF5B750B80268804F0082E8804EB2B58800E87040880261004CF080E100489166304C70685040800C606840418C7060C01B2588C0E0E01CD42C380261004CF080E10045853500E1F33C98AC8E8FBCA7406E86CC9E8BBC2B208BE401CE8F4CCBE401CE823C8585B0F846EFF2E8E1E3F040E07E819290E1F5366BB401C001CE82FCFBE001CB020E858C85B2E8E1E3F040E07E8222EE82400E82E3DE8D101E88E01E8B43E0E1FBE001CB010E834C8E8FD2DE8F52DC38BECC6461B00C3E82F00E80A00E8BD00E85200E8620AC35383C30A8B166304B91900B81130EF32C0268A27EF43FEC0E2F75B80C20632C0EEC353BAC40383C305B90400B001268A273C01750380CC20EF43FEC0E2F05B268A4709BAC203EEB2C4B80003EFC38BF383C623BADA0326F64709017502B2BAF606890408741D83C610ECB90400B410B2C080FC1174078AC4EE268A04EE46FEC4E2EFC353EC8BDEB9140032E4B2C08AC4EEFEC4268A07EE43E2F48AC4EE32C0EE1E06E84F2D0BED74091F1EB91000F3A446A4071F5BC35383C337B9090032C0BACE03268A27EF43FEC0E2F75BC3BBE4500E078BD30AE47D01C3E80100C333F680FC037F3C4AF6068904107520A08804240F3C027E243C0874203C06741C3C077418B040F6E403D881C30004C3B040D0ECF6E403D881C38004C3B040F6E403D8C380FC077511F606890410750581C30001C381C30005C3BF664EBE874E33C9E84E00C304800005800006C0000D80020EC0020F800310C00311400512800513C005624001538A1E490480FB077F1032FFD1E32E8B87A34EA26504882666045BC32C3028302D3029302A302E301E3F29302E382575072E035D0133F6C383C7033BFE75EDC31E062E8E1E3F04F6068704807549833E4C04007442A04904B900202E8B3E450426F6473301750E26F6470901751B2E8B3E4304EB143C067E0B2E8B3E4104268A6737B5406633C0EB0666B8200720078EC76633FFF366AB802687047F071FC32E8E1E3F0480FB107503E97A0180FB207503E99B0180FB32751FBACC030AC07509EC0C02B2C2EEE9F300FEC80F85F300EC24FDB2C2EEE9E40080FB3575283C807508800E890440E9D300F6068904400F84D0000AC00F84CA00FEC87506E89807E9BA00E9BD0080FB307403E9960050E8303E8AEFBACC03EC8AC8580AC07530B708F6C10175120AED750BA0100424303C307510B702E98B00A0100424303C307502B702802689046F800E890480EB363C017541802689046FB709F6C1017515B70BA0100424303C30741BB7090AED7415B705EB11A0100424303C307508B70B0AED7402B7038A1E880480E3F00ADF881E8804EB293C02752B802689046F800E890410EBB480FB31751B0AC0740B3C01750C800E890408EB0580268904F78BECC6461A12C380FB3375163C00740B3C0175EC80268904FDEBE5800E890402EBDE80FB3475173C00750780268704FEEBCE3C017507800E870401EBC3C380FB367526BB20FF3C017409BB00DF3C007402EBADE80200EBA89CFABAC403B001EE42EC22C70AC3EE9DC3C3B303B700BACC03ECA8017502B701A088048AE0B104D2EC250F0F8BC88BEC895E0E894E16C6461A12C39CFAC706140094768C0E16009DC3281808000809030002632D2728902BA0BF1F00C70607000000009C8E8F141F96B9A3FF0001020304050607101112131415161708000F000000000000100E00FF501808001001030002635F4F50825581BF1F00C70607000000009C8E8F281F96B9A3FF0001020304050607101112131415161708000F000000000000100E00FF281808004009030002632D2728902B80BF1F00C10000000000009C8E8F140096B9A2FF00131517020406071011121314151617010003000000000000300F00FF501808004001010006635F4F50825480BF1F00C10000000000009C8E8F280096B9C2FF00171717171717171717171717171717010001000000000000000D00FF50180E001000030003A65F4F50825581BF1F004D0B0C0000000083855D280D63BAA3FF000808080808080810181818181818180E000F080000000000100A00FF501D1000A0010F000AE35F4F508254800B3E0040000000000000EA8CDF5000E704E3FF000102030405060708090A0B0C0D0E0F01000F00100000000040050FFF0005111C080B14280E182D322024383F0005080B0E1114181C2024282D32383F070C10151A181615131C252F38332E2A2527292A2C2319102325272A2C2B2A29292D32373B3937343233343535312C272F303233343433333235383A3D3C3A39383839393A373431030507090B0B0A09080D11151917151311111213140F0B071010121314131313121416181A191817161717171815141115151617171717171618191A1B1B1A19191919191A181716020304050706060505070A0C0E0D0C0B090A0A0B0B09060409090A0B0B0B0B0B0A0C0D0E0F0F0E0D0D0D0D0D0E0C0B0A0C0C0C0D0D0D0D0D0C0D0E0F0F0F0F0E0E0E0E0E0E0E0D0C00000000000000002818080020090F0006632D2728902B80BF1F00C00000000000009C8E8F140096B9E3FF0001020304050607101112131415161701000F00000000000000050FFF5018080040010F0006635F4F50825480BF1F00C00000000000009C8E8F280096B9E3FF0001020304050607101112131415161701000F00000000000000050FFF0005111C080B252802071B200F14282C0C11252A141E32360F13272C1B203439060B1F2413182C30090D2126151A2E3313172B301F24383D0E182D322024383F0005111C080B14180005111C080B14180E182D322024383F0E182D322024383F0005111C080B14180005111C080B14180E182D322024383F0E182D322024383F50180E0080010F0006A25F4F50825480BF1F004000000000000083855D280F63BAE3FF000800001818000000080000001800000B0005000000000000000505FF50180E0080010F0006A35F4F50825480BF1F004000000000000083855D280F63BAE3FF000102030405140738393A3B3C3D3E3F01000F00000000000000050FFF28180E000809030002A32D2728902BA0BF1F004D0B0C0000000083855D141F63BAA3FF000102030405140738393A3B3C3D3E3F08000F000000000000100E00FF50180E001001030002A35F4F50825581BF1F004D0B0C0000000083855D281F63BAA3FF000102030405140738393A3B3C3D3E3F08000F000000000000100E00FF281810000808030002672D2728902BA0BF1F004F0D0E000000009C8E8F141F96B9A3FF000102030405140738393A3B3C3D3E3F0C000F080000000000100E00FF501810001000030002675F4F50825581BF1F004F0D0E000000009C8E8F281F96B9A3FF000102030405140738393A3B3C3D3E3F0C000F080000000000100E00FF501810001000030002665F4F50825581BF1F004F0D0E000000009C8E8F280F96B9A3FF000808080808080810181818181818180E000F080000000000100A00FF501D1000A0010F0006E35F4F508254800B3E0040000000000000EA8CDF2800E704C3FF003F3F3F3F3F3F3F3F3F3F3F3F3F3F3F01000F000000000000000501FF501D1000A0010F0006E35F4F508254800B3E0040000000000000EA8CDF2800E704E3FF000102030405140738393A3B3C3D3E3F01000F00000000000000050FFF2818080020010F000E635F4F50825480BF1F00410000000000009C8E8F284096B9A3FF000102030405060708090A0B0C0D0E0F41000F00000000000040050FFFE45000C0000000000000000000000000045700C00000000000000000000000001A00A28E00C000000000000000000000000000000000000000001EE810002E8E1E3F04E8FE36E8D536E8761A1FC32E8E1E3F04C706870460F9C6068A040BA089040C112417A28904B401E8731EA0890480261004CF800E100420C7066304D4030E1FE871B8F7C102007503E8F9B7B80300E857F4C31E2E8E1E3F040E07EB001FC3F6068904087401C353BAC803ECB0FFB2C6EEB2C8803E6304B4752FBE6658B9400033DB9CFA8AC3EE8BFBC1EF0383E70303FE2E8A0542EE2E8A4504EE2E8A4508EEFEC34AE2DF9DE98500268A472BF6068904067431B9F800BF64523C087411B94000BFE4533C3874073C3F7403BF245433DB9CFA8AC3EE2E8A0142EEEEEEFEC34AE2F19DEB493C0874253C38742E3C3F742AB9080033DB51E8CBD3B90800F7C31000740383C718E8670059E2EAEB20E8B4D3B9100033DBE85700EB13B9400033DB51E828008AC3E8B72FFEC359E2F25BC3002A002A002A002A153F153F153F153F002A003F002A003F002A003F8BFBC1EF0283E70F2E8AB556588BFBD1EF83E70F2E8AAD56588BFB83E70F2E8A8D5658C39C8AC3FAEE2E8A0542EE472E8A05EE472E8A05EE47FEC34AE2E79DC300000000000000007E81A581BD99817E7CFED6BAC6FE7C00C6EEFEFE7C38100010387CFE7C381000103810EEEE103800387CFEFE6C10380000183C7E3C180000FFE7C381C3E7FFFF00183C66663C1800FFE7C39999C3E7FF1E0E1E3678CCCC787EC3C37E187E18181E1A1E181870F0603E3E3636F6661E0CDB3C66E7663CDB0080C0F0F8F0C0800002061E3E1E060200183C7E187E3C180066666666660066007FDB7B3B1B1B1B003C66386C6C38CC7800000000FEFEFE00183C7E187E3C187E183C7E1818181800181818187E3C180000181CFE1C180000003070FE703000000000C0C0C0FE0000002466FF662400000010387C7CFE000000FE7C7C381000000000000000000000183C3C18180018006C6C6C00000000006C6CFE6CFE6C6C00187EC07C06FC180000C60C183060C600386C3876CCCC760018183000000000001830606060301800603018181830600000EE7CFE7CEE00000018187E181800000000000018183000000000FE000000000000000000383800060C183060C080007CC6CEDEF6E67C001878181818187E007CC60C183066FE007CC6063C06C67C000C1C3C6CFE0C0C00FEC0FC0606C67C007CC6C0FCC6C67C00FEC6060C181818007CC6C67CC6C67C007CC6C67E06C67C00001C1C00001C1C0000181800001818300C18306030180C000000FE0000FE00006030180C183060007CC6060C180018007CC6C6DEDCC07E00386CC6C6FEC6C600FC66667C6666FC003C66C0C0C0663C00F86C6666666CF800FEC2C0F8C0C2FE00FE62607C6060F0007CC6C0C0DEC67C00C6C6C6FEC6C6C6003C18181818183C003C181818D8D87000C6CCD8F0D8CCC600F06060606062FE00C6EEFED6D6C6C600C6E6E6F6DECEC6007CC6C6C6C6C67C00FC66667C6060F0007CC6C6C6C6D67C06FCC6C6FCD8CCC6007CC6C07C06C67C007E5A181818183C00C6C6C6C6C6C67C00C6C6C6C66C381000C6C6D6D6FEEEC600C66C3838386CC6006666663C18183C00FE860C183062FE007C60606060607C00C06030180C0602007C0C0C0C0C0C7C0010386CC60000000000000000000000FF30301800000000000000780C7CCC7E00E0607C666666FC0000007CC6C0C67C001C0C7CCCCCCC7E0000007CC6FEC07C001C3630FC30307800000076CEC67E067CE0607C666666E6001800381818183C000C001C0C0C0CCC78E060666C786CE6001818181818181C0000006CFED6D6C6000000DC666666660000007CC6C6C67C000000DC66667C60F0000076CCCC7C0C1E0000DC666060F00000007CC07C067C003030FC3030361C000000CCCCCCCC76000000C6C66C3810000000C6C6D6FE6C000000C66C386CC6000000C6C6CE76067C0000FC983064FC000E18187018180E0018181800181818007018180E1818700076DC000000000000001038386C6CFE003C66C0663C18CC7800C600C6C6CE76000E007CC6FEC07C007CC6780C7CCC7E00C600780C7CCC7E00E000780C7CCC7E003838780C7CCC7E0000007CC07C186C387CC67CC6FEC07C00C6007CC6FEC07C00E0007CC6FEC07C006600381818183C007CC6381818183C000000381818183C00C6386CC6FEC6C6003838007CC6FEC6000E00FEC0F8C0FE0000006C9A7ED86E007ED8D8FED8D8DE007CC6007CC6C67C0000C6007CC6C67C0000E0007CC6C67C007CC600C6C6CE760000E000C6C6CE760018003C1818183C00C6386CC6C66C3800C600C6C6C6C67C0000187ED8D87E1800386C60F066F66C00C3663C7E183C18003E63380E633E001C003E613C867C001C0E00780C7CCC7E001C00381818183C00000E007CC6C67C00000E00CCCCDC760000FC00BC6666E600FE00C6E6F6CEC6003E003E6067633D003E0076CEC67E067C1800183060663C000000007C606000000000007C0C0C0000C0CCD8307C360C3EC0CCD8306C3C7E0C180018183C3C180000366CD86C36000000D86C366CD80000228822882288228855AA55AA55AA55AADD77DD77DD77DD77181818181818181818181818F81818181818F818F818181836363636F636363600000000FE3636360000F818F81818183636F606F636363636363636363636360000FE06F63636363636F606FE00000036363636FE0000001818F818F800000000000000F8181818181818181F00000018181818FF00000000000000FF181818181818181F18181800000000FF00000018181818FF18181818181F181F1818183636363637363636363637303F00000000003F30373636363636F700FF0000000000FF00F736363636363730373636360000FF00FF0000003636F700F73636361818FF00FF00000036363636FF0000000000FF00FF18181800000000FF363636363636363F00000018181F181F00000000001F181F181818000000003F36363636363636FF3636361818FF18FF18181818181818F8000000000000001F181818FFFFFFFFFFFFFFFF00000000FFFFFFFFF0F0F0F0F0F0F0F00F0F0F0F0F0F0F0FFFFFFFFF00000000000066DCD8DC66000078CCF8CCC6CC0000FE62606060E00000FE6C6C6C6C6C00FEC6603060C6FE00007ED8CCCCD8700000666666667CC0000076DC1818183800FE386CC66C38FE00386CC6FEC66C3800386CC6C66C6CEE003E603866C6CC780000007EDBDB7E0000067CDEF6E67CC0003860C0F8C06038007CC6C6C6C6C6C60000FE00FE00FE000018187E1818007E0030180C1830007E000C1830180C007E000C1E1818181818181818181818783000000018007E0018000076DC0076DC00007CC6C67C00000000000000181800000000000000180000001F181818F8381800D86C6C6C0000000070D830F80000000000007C7C7C7C000000000000000000001D000000002466FF66240000000000000010000000000000000000000000000000000000007E81A58181BD9981817E0000000000007CFEFED6FEFEBAC6FE7C000000000000006CEEFEFEFEFE7C38100000000000000010387CFE7C3810000000000000000000103838106CEE6C103800000000000010387C7CFEFEFE6C1038000000000000000000183C3C3C18000000000000FFFFFFFFFFE7C3C3C3E7FFFFFFFFFFFF00000000183C6666663C180000000000FFFFFFFFE7C3999999C3E7FFFFFFFFFF00001E0E1E3678CCCCCCCC780000000000003C6666663C187E1818180000000000001E1A1E1818181878F8700000000000003E363E363676F6660E1E0C000000000018DB7E3C66663C7EDB180000000000000080E0F0FCFEFCF0E08000000000000000020E3E7EFE7E3E0E02000000000000183C7E181818187E3C18000000000000666666666666660066660000000000007FDBDBDBDB7B1B1B1B1B0000000000007CC6C6607CF6DE7C0CC6C67C00000000000000000000FEFEFEFE000000000000183C7E1818187E3C187E000000000000183C7E18181818181818000000000000181818181818187E3C180000000000000000000C0EFF0E0C00000000000000000000003070FE7030000000000000000000000000C0C0C0FE00000000000000000000002466FF6624000000000000000000103838387C7CFEFE0000000000000000FEFE7C7C7C3838100000000000000000000000000000000000000000000000183C3C3C3C1818001818000000000036363636140000000000000000000000006C6C6CFE6C6CFE6C6C6C00000000000018187CC6C0783C06C67C18180000000000000062660C183066C6000000000000386C3830767ECCCCCC7600000000000C0C0C18000000000000000000000000000C18303030303030180C00000000000030180C0C0C0C0C0C18300000000000000000006C38FE386C000000000000000000000018187E18180000000000000000000000000000000C0C0C1800000000000000000000FE0000000000000000000000000000000000001818000000000000000002060C183060C0800000000000007CC6C6CEDEF6E6C6C67C0000000000001878181818181818187E0000000000007CC6C6060C183060C6FE0000000000007CC606063C060606C67C0000000000000C1C3C6CCCCCFE0C0C1E000000000000FEC0C0C0FC060606C67C0000000000007CC6C0C0FCC6C6C6C67C000000000000FEC6060C1830303030300000000000007CC6C6C67CC6C6C6C67C0000000000007CC6C6C6C67E0606C67C0000000000000000000C0C00000C0C000000000000000000000C0C00000C0C0C180000000000000C183060C06030180C00000000000000000000FE00FE000000000000000000006030180C060C1830600000000000007CC6C60C1818180018180000000000007CC6C6C6DEDEDEDCC07E000000000000386CC6C6C6FEC6C6C6C6000000000000FC6666667C66666666FC0000000000003C66C2C0C0C0C0C2663C000000000000F86C6666666666666CF8000000000000FE6660647C64606066FE000000000000FE6660647C64606060F00000000000007CC6C6C0C0C0CEC6C67C000000000000C6C6C6C6FEC6C6C6C6C60000000000003C18181818181818183C0000000000003C181818181818D8D870000000000000C6C6CCD8F0F0D8CCC6C6000000000000F06060606060606266FE000000000000C6C6EEEEFED6D6D6C6C6000000000000C6C6E6E6F6DECECEC6C60000000000007CC6C6C6C6C6C6C6C67C000000000000FC666666667C606060F00000000000007CC6C6C6C6C6C6D6D67C060000000000FC6666667C786C6666E60000000000007CC6C0C0701C0606C67C0000000000007E5A181818181818183C000000000000C6C6C6C6C6C6C6C6C67C000000000000C6C6C6C6C6C6C66C3810000000000000C6C6C6D6D6D6FEEEC6C6000000000000C6C6C66C38386CC6C6C600000000000066666666663C1818183C000000000000FEC6860C183060C2C6FE0000000000007C60606060606060607C000000000000000080C06030180C06020000000000007C0C0C0C0C0C0C0C0C7C000000000010386CC6000000000000000000000000000000000000000000000000FF0000001818180C00000000000000000000000000000000780C7CCCCCDC76000000000000E060607C6666666666FC0000000000000000007CC6C0C0C0C67C0000000000001C0C0C7CCCCCCCCCCC7E0000000000000000007CC6C6FEC0C67C0000000000001C363030FC303030307800000000000000000076CEC6C6CE7606C67C00000000E060607C6666666666E60000000000001818003818181818183C0000000000000C0C001C0C0C0C0C0CCCCC7800000000E0606066666C786C66E60000000000001818181818181818181C0000000000000000006CFED6D6C6C6C6000000000000000000DC6666666666660000000000000000007CC6C6C6C6C67C000000000000000000DC666666667C6060F00000000000000076CCCCCCCC7C0C0C1E00000000000000DC6660606060F00000000000000000007CC6C07C06C67C000000000000303030FC30303030361C000000000000000000CCCCCCCCCCCC76000000000000000000C6C6C6C66C3810000000000000000000C6C6D6D6D6FE6C000000000000000000C6C66C386CC6C6000000000000000000C6C6C6C6CE7606C67C00000000000000FE860C183062FE0000000000000E18181870181818180E00000000000018181818001818181818000000000000701818180E181818187000000000000076DC00000000000000000000000000000000001038386C6CFE000000000000003C66C0C0C0C6663C180CCC3800000000C60000C6C6C6C6C6CE7600000000000C1830007CC6C6FEC0C67C00000000003078CC00780C7CCCCCDC76000000000000CC0000780C7CCCCCDC76000000000060301800780C7CCCCCDC760000000000386C3800780C7CCCCCDC7600000000000000007CC6C0C0C67C180C6C380000003078CC007CC6C6FEC0C67C000000000000CC00007CC6C6FEC0C67C000000000030180C007CC6C6FEC0C67C0000000000006600003818181818183C0000000000183C66003818181818183C0000000000000000003818181818183C0000000000C600386CC6C6C6FEC6C6C600000000386C3800386CC6C6FEC6C6C6000000000C183000FE60607C606060FE000000000000000066DB1B7FD8D8DF760000000000007ED8D8D8D8FED8D8D8DE00000000003078CC007CC6C6C6C6C67C000000000000C600007CC6C6C6C6C67C000000000030180C007CC6C6C6C6C67C00000000003078CC00C6C6C6C6C6CE76000000000060301800C6C6C6C6C6CE76000000000018003C181818181818183C0000000000C6007CC6C6C6C6C6C6C67C0000000000C600C6C6C6C6C6C6C6C67C00000000000018187CC6C0C0C67C18180000000000386C6060F060606066F66C0000000000666666663C187E183C18180000000000003E6363301C0663633E001C00000000000000003E63380E633E001C000000000C183000780C7CCCCCDC7600000000000C1830003818181818183C00000000000C1830007CC6C6C6C6C67C000000000018306000CCCCCCCCCCDC7600000000000076DC00BC6666666666E6000000000076DC00C6C6E6F6DECEC6C60000000000211E001E3360606763331D0000000000423C003B6666663E06663C00000000000030300030303060C6C67C00000000000000000000007E6060600000000000000000000000007E060606000000000000606062666C183060DC360C183E000000606062666C18366EDE367E06060000000018180018183C3C3C3C18000000000000000000366CD86C360000000000000000000000D86C366CD800000000000011441144114411441144114411441144AA55AA55AA55AA55AA55AA55AA55AA55DD77DD77DD77DD77DD77DD77DD77DD771818181818181818181818181818181818181818181818F818181818181818181818181818F818F8181818181818181836363636363636F6363636363636363600000000000000FE36363636363636360000000000F818F818181818181818183636363636F606F63636363636363636363636363636363636363636363636360000000000FE06F636363636363636363636363636F606FE000000000000000036363636363636FE00000000000000001818181818F818F8000000000000000000000000000000F81818181818181818181818181818181F000000000000000018181818181818FF000000000000000000000000000000FF1818181818181818181818181818181F181818181818181800000000000000FF000000000000000018181818181818FF181818181818181818181818181F181F181818181818181836363636363636373636363636363636363636363637303F000000000000000000000000003F303736363636363636363636363636F700FF00000000000000000000000000FF00F73636363636363636363636363637303736363636363636360000000000FF00FF00000000000000003636363636F700F736363636363636361818181818FF00FF000000000000000036363636363636FF00000000000000000000000000FF00FF181818181818181800000000000000FF3636363636363636363636363636363F000000000000000018181818181F181F000000000000000000000000001F181F1818181818181818000000000000003F363636363636363636363636363636FF36363636363636361818181818FF18FF181818181818181818181818181818F80000000000000000000000000000001F1818181818181818FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFFF0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0FFFFFFFFFFFFFFFFF00000000000000000000000076DCD8D8D8D8DC7600000000000078CCCCD8FCC6C6C6C6CC000000000000FE666260606060606060000000000000000000FE6C6C6C6C6C6C000000000000FEC6623018183062C6FE0000000000000000007ED8CCCCCCD870000000000000000066666666667C60C080000000000000000076DC1818181818000000000000FE38386CC6C66C3838FE00000000000000386CC6C6FEC6C66C38000000000000386CC6C6C6C66C6C6CEE0000000000003E60603C66C6C6C6CC780000000000000000007EDBDBDB7E000000000000000002067CCEDEF6F67C60C0000000000000001C3060607C6060301C0000000000007CC6C6C6C6C6C6C6C6C60000000000000000FE0000FE0000FE00000000000000000018187E181800007E00000000000030180C060C183000007E0000000000000C18306030180C00007E00000000000000000C1E1A18181818181818181818181818181818181818587830000000000000001818007E001818000000000000000000000076DC0076DC0000000000000078CCCC7800000000000000000000000000000000001818000000000000000000000000000000180000000000000000001F1818181818D8D87838180000000000D86C6C6C6C6C0000000000000000000070D8183060F8000000000000000000000000007E7E7E7E7E7E0000000000000000000000000000000000000000001D00000000002466FF66240000000000002F0000000103060C183060C080000000003000007EC3C3C3DBDBC3C3C37E000000004D0000C3C3E7FFFFDBDBC3C3C300000000540000FF99181818181818183C00000000560000C3C3C3C3C3C3C3663C1800000000570000C3C3C3C3DBDBDBDBFF6600000000580000C3C3C3663C3C66C3C3C300000000590000C3C3C3C3663C1818183C000000005C00000080C06030180C060301000000006D000000000066FFDBDBDBC3C300000000760000000000C3C3C3C3663C1800000000770000000000C3C3DBDBDBFF66000000000000C560C30BDB7403E946015732C0B94000F3AA5FBB928E26891D268C4D022E8E1E3F0457BE4904B91E0083C704FC8A042688054647E2F75FA08404FEC026884522A185042689452357E8D91B5F26885D2526887D268A1E4904E8FC05740580FB137F1D32FFD1E32E8A876A8E32E40AC0740140268945272E8A876B8E26884529A185048A168404FEC2F6E2B2003DC8007E15B2013D5E017E0EB2023D90017E07B2033DE0017E002688552A8A2687048AC42401C0E00480E402D0E40AE080F410A08904240A0AE0E89408B2C0B030EE42EC2408C0E0020AC40C012688452DB00326884531E877081E0632D2C41EA8048CC18CCE3BCE743426C577048CD90BF1740380CA1026C5770C8CD90BF1740380CA0826C577088CD90BF1740380CA0426C577108CD90BF1740380CA01071F26885532B003BAC403E8E4048AE0C0EC028AD48AF2D0EE81E204042503030BC22689452B8BECC6461A1BC30AC0740FFEC87436FEC874568BECC6461A00C3B82000F6C101740383C060F6C102740383C03AF6C104740305030383C03FC1E8068BEC89460EC6461A1CC38BFB83C720F6C1017403E88500F6C1027403E8EF00F6C1047403E8F8018BECC6461A1CC3F6C1017406E81615E82501F6C1027403E88501F6C1047403E81202EBDC8AC4EE42ECAAFEC44AE2F5C3E86B04BDC003B9150032E4EC87EA8AC4EE42ECAAFEC44A87EAE2F0EC87EAB020EEC3268A0588044746E2F7C3268A25EF47FEC0E2F7C3B2C08AC4EE268A0547FEC4EEE2F4C39CFA51578BC72BC32689078BF7E80A04EC2688440126895441B2CEEC26884402B2CCEC26884409B2CAEC26884404B2C4EC26880483C705B90400B401E870FF268A04EE8BFE83C70A268B544132E4B91900E85BFF268A4401EEE85FFFB2CE32E4B90900E849FF268A4402EE5F5983C7609DC39CFA8BC72BC32689470251572E8E1E3F04A010042430AABE4904B91E00F3A4BE8404B107F3A4BEA804B104F3A4BE1400B104F3A4BE7400B104F3A4BE7C00B104F3A4BE0C01B104F3A45F5983C73A9DC39CFA268B3F03FB8BF7518BFE83C705BAC403B80001EFB001B90400E807FF47B2C2268A4409EEB2C4B80003EF268A04EE268B5441B81100EFB11932C0E8E6FE268A4401EE80C206268A4404EEECB11532E4E8DBFEB020EEB10932C0B2CEE8C5FE268A4402EE599DC39CFA268B7F0203FB06512E8E1E3F04268A0580261004CF0806100447BE4904B91E00E88EFEBE8404B107E886FEBEA804B104E87EFEBE1400B104E876FEBE7400B104E86EFEBE7C00B104E866FEBE0C01B104E85EFE59079DC39CFA8BC72BC326894704E8A605B2C0B034EE42EC268805BAC803EC26884501504A4AEC2688450283C703B900034232C0EE4242ECAAE2FC584AEE9DC39CFA268B770403F3E86C05B2C0B034EE268A04EEBAC603268A4402EE56424283C60332C0EE42B90003268A04EE46E2F95EFECA268A4401EE9DC3BACC03EC24FE0AC4B2C2EEC3E8A812B2C086C4EEEB00EB0086C4EEEB00EB00B020EEC3508AE080E480802687047F08268704247F8AE03C077E1E26F647330175173C2374133C32740F3C33740BB40326F64709017502B40788264904BAB403800E87040226F64709017407B2D480268704FD89166304C7064E040000C606620400B90800BF5004FC061E0733C0F3AB07268A0732E4A34A04268A4701A28404268A4702A38504268B4703A34C04268B471486C4A3600458C35232E433D2B00DCD17F6C429750832E433D2B00ACD175AC3061E602E8E1E3F042E830E490400756E803E0005017467C6060005018A1E620432FFD1E38BFB8B8550048A3E62045032F68A0E840432ED41518B0E4A0432D2E8A6FFF6C429753D515289955004B408E8B0D40AC07502B02033D232E4CD17F6C429751F5AFEC259E2DEFEC659E2CAE877FF32C0A200055889855004E8AF03611F07CF5A5959B0FFEBEA522AF538C67D0232C02E8E0641045AC3A08504F6E38AF78BD88BCABAC403B8020FEFB402E86D008BD132ED8AE68AC6F3AA03FD8ACA4B75F732E4E85700C3538A1E62040BC075040ADB7403E835035B8BF82BD181C201018AC332E4C38AC632F62BEA0ADB742A2AC3F62685048BC852B401E82000B2C4B8020FEF5A1E061F8BC18BCAF3A403F503FD4875F51FE881FFC38AD8EBF8BACE03B005EE42EC24FC0AC4EE4AC39CFAEE42EB00EC4A9DC31E2E8E1E3F048B16630480C2061FC31E2E8E1E3F048B1663041FC350BACC03ECB2D4A8017502B2B458C3E8EEFF80C206C31E2E8E1E3F04803E4904037413803E490402740C803E4904017405803E4904001FC3502E8E064304A0100424303C3074052E8E064504580BC07403E8E10103064E0481C201012BD132ED8B2E4A048BF88BF08BC5F6E3D1E0D1E50ADB75028ADE38F37E028ADEC3FC8AD88BC1E8B3FF03F03A164A047406061FE81B00C3061FE84000C3FC8AD88AC18AE6E895FFF7DD2BF0061FE80100C3538ACE2ACB32ED32F62BEA2BEAE30E8AE18BCAF3A503F503FDFECC75F458B0208ACAF3AB03FDFECB75F6C3538AC62AC37406F6E28BC8F3A5588BC8F6E291B020F3ABC38BD8E82E002E8E1E45048AC322DFD3E3A8807403301CC3F6D78A3422F70ADE881CC38AFCE80C002E8E1E45048A04D2E822C7C3B028F6E2F6C201740305D81F8BF1C1EE0280FF057F0C03F0F6D180E103D0E1B703C3D1EE03F0F6D180E107B701C3FC8AD82E8E0645048BC1E8860075028ADE03F0E82400C3FC8AD82E8E0645048AC18AE6E86D0075028ADEF7DD81C6F00081C7F0002BF0E80100C38ACE2ACBE32C518ACA5657D1E9F3A513C9F3A48ACA2BF12BF981C6002081C70020D1E9F3A513C9F3A45F5E03F503FD59E2D48AC78AE78ACA57D1E9F3AB13C9F3AA8ACA2BF981C70020D1E9F3AB13C9F3AA5F03FDFECB75DEC3E8B00081C201012BD138F3760232DB51B102D2E6D2E35932EDBD5000803E4904067404D0E2D1E0061F8BF88BF0B050F6E30ADBC352538ADF32FFD1E38B875004E80E0050D1EBA14C04F7E35B03C35B5AC3528BD0A04A04F6E432F603C2D1E05AC38BE883E50F2E8AA6427A8BE8C1ED0483E50F2E8A86427AC300030C0F30333C3FC0C3CCCFF0F3FCFF268B0486E0BA0080F6C4C074020AD6D0EEC1E00275F288560045C38B1663048AC586E0EF8AE1FEC0EFC3528BD08AC4F6264A04C1E00232F603C25AC3538ADF32FFD1E38B875004D1EBE802005BC3528BD032F6528AC4F6268504F7264A045A03C20ADB740803064C04FECB75F85AC3528BD0A04A04F6E432F603C2D1E003064E04D1F88BC8B40EE891FF5AC38BC2F7264A048BF9C1EF0303F80AFF740A8AC732E4F7264C0403F880E107B480D2ECC3E8F0FCECC3E8F8FFB2C0B020EEC3E8EFFFB2C032C0EEC3C43EA80426C47D048CC50BEFC353B00EE895FC8AE0B00FE88EFC8BD8B80EAAEFB80F55EFB00EE87FFC3CAA740DB00FE876FC3C55740432C05BC3B00E8AE7EFFEC08AE3EFB0010AC05BC38AEE8A368504061F0ADB74258AC52AC3F6E68BC85232F6C1E2028BC2D1E22BD5518BC8F3A52BFA2BF259E2F45AE80500C38ADDEBF88AC6F6E38BC88AC78AE032F6C1E2028BDAD1E28BF12BD58BCBF3AB2BFA4E75F7C32E8E1E3F04890E60048AC52460A8207406B9001EE99400F6068704010F858B00803E4904077406E819FC7401C3F6068704087403CD42C38A3685048AD6FECA38CD7E1F0AC974648AE98ACEFEC9EB5C38D174588ACE80FD037C048AE9D0EDFEC9EB4980F9037E448AE12AE50AE4750A38CA7438FECA38CA74328AC50AC138F07E0A80FC027E1280FD027FC880FC037DBF8AD6FECA38D174138ACEFEC9FEC98AE92AEC80FE087F04FEC1FEC5B40AE805FEC32E8E1E3F04A2620432E48BF0F7264C04A34E048BC8E87AFB7407803E4904077702D1F9B40CE8DCFDD1E68B845004E827FEC32E8E1E3F048A264904E8359F7407C70650040000C3E848FB740B80FC0774067708E877FCC3E89FFBC380FC137C03741FC3E84EFA8AD88BC1E885FA8B2E4A0452F6268504F7E58BF703F05AE890FAC3E830FA8AD88BC1E867FAC1E703528B2E4A04C1E503F7268504F7E58BF703F05AE855FEC32E8E1E3F048A264904E8E1FA740C80FC077407774080FC037F04E853FBC3E81EFCC3E8EAF98AD88AC18AE6FEC4E81DFA2B3E4A04C1E70352F7268504F7264A04C1E0038BF72BF05A8B2E4A04C1E503F7DDE800FEC380FC137C0374C6C3E8AFF98AD88AC18AE6FEC4E8E2F9528B2E4A04F7268504F7E52BFD8BF72BF05AF7DDE8E9F9C32E8E1E3F042E8E064504E85DFA7411803E4904077C182E8E0643047403E9B100E849FC8BD8268B078BEC89461AC3A15004E8B7FC8BF0BB08002BE38BEC803E490406751FB90400268A0488460045268A8400208846004583C650E2EBB80002B280EB17D1E6B90400E856FC81C60020E84FFC81EEB01FE2F0EBE22BEBC43E0C0132F680FB0E750926837DFE107502B680161F8BF58BCBF6C6807401475657F3A65F5E7423FEC003FBF6C680740147FECA75E2FECC740F2E8E1E3F04C43E7C00B080B280EBCB32C08BE503E38BEC89461AC3803E4904137C057502EB5AC32E8E064104E818FC8BF08B1E85042BE38BECB80508B90500BACE03803E49040F721AF6068704607513B40AF7C601007502B405B007EFB80518B90501EF518BCB268A04F6D08846004503364A04E2F158EFB8000132D2E944FF2E8E064104A150048BD032F6528AC432E4F7264A04F72685045A03C28BF08B1E85042BE38BEC538B3E4A044FC1E703C1E603B9080032E4268A04D0E40AC0740380CC0146E2F18866004503F74B75E35BB8000132D2E9ECFE33EDEB03BD01002E8E1E3F042E8E0645048A264904E8C4F8740F2E8E06430480FC0774057C3DE90B028AE38BF08ADF32FFD1E38B8750048BD0A04A04F6E432F603C28BF8D1E70ADB740BD0EBA14C0403F8FECB75FA8BC60BED7503F3ABC3AA47E2FCC3502E8E064504A15004E8EEFA8BF8A050048A264A048BE858A8807408247FC5367C00EB04C5360C018AFC32E4C1E00303F080FF067469D1E78AF3B05580E303F6E38AD88AF88BC550B204F6C6807527ACE855FA23C3ABACE84EFA23C3268985FE1F83C74EFECA75E783EE0881EF3E0158E87200E2D2C3ACE82EFA23C3263105ACE825FA23C3263185002083C750FECA75E583EE0881EF3E0158E84900E2A9C38BC550B204F6C380741FAC263005AC263085002083C750FECA7FEF83EE0881EF3F0158E82000E2DAC3ACAAAC268885FF1F83C74FFECA7FF183EE0881EF3F0158E80300E2BDC3FEC038E0720632C081C7F000C38A168504F6E28BF032F68BEA660FB6065104F6E2660FB7164A0483FA647503BA680083FA5A7503BA600081FAAF007503BAB00052F7E2660FB7F8660FB60650046603F866C1CF1003FA66C1C70381CF00FF66C1C7105A8AE24AC1E203A0500450C5060C0103F02E8E064104585751509CFC8BCDE83B00B508AC8AE08AC7D0E473028AC32688056647FECD75EF6603FAE2E29D58595F83C708FEC038E0720E5132C08BCD4903FA83C708E2F9592BF5E2BCC3065233C08EC066C1C7108BC766C1C710E8A49A741638E074120FB6D0E88BC98AE066C1C7108BF866C1C7105A07C380FC137C0B0F8418FF80FC620F8411FFE80100C380FC11750680E38080CB0F50538ADF32FFD1E38B9750045B2E8E064104E807F98BF88B2E85045832F6528B364A04568A268504C5360C0180FC0E7509837CFE107503B41046F6E403F0B603F6C380756DB2C4B8020FEF5A5850524A8AE0575151578BCD32C0AA03FAE2FB5F47FEC438D4760A32E48BCD4903FA47E2FB59E2E0595FBAC403B0028AE3EF5B4B5A51578BCDAC268A25AA03FBE2F75F472BF5423BD3760A33D28BCD4903FB47E2FB59E2DDBACE03B80300EFB2C4B8020FEFC3B2CEB80318EFEBBC2E8E1E3F04803E6304B4740BBACC03ECA8017504CD42C3C3E8D1F80AFF751C8AE380E41F80266604E008266604E82D008A1E660480E320B105D2EBE891F57419A0660424DF80E30174020C20A2660424100C020AD8E85300C3E87EF8C3535080E30F8AFBD0E381E310070ADFE860F5740EB4008AC3E82CF30BED740326881D8AC3E80B000BED740426885D10585BC38AE01E2E8E1E3F04803E4904331F7F088AC4B411E8FEF2C3E830F8C39CFAE89F05B2C0B90300B4018AC4EE8AC3EE0BED74044726881DFEC480C302E2EBB020EE9DC32E8E1E3F048A264904E8F2F4740A80FC0777067403E8C0F5C380FC137C03744CC38AD8E8BBF7BACE03B008EF2E8E1E4104F6C380751CB2C4B802FFEF8A25C605008AE3EF8A25B4FF8825EFB2CEB808FFEFC3B80318EFB2C4B0028AE3EF8A25B4FF8825EFB2CEB80300EFEBE1502E8E064104A14A04C1E003F7E203C18BF858268805C32E8E1E3F048A264904E86FF4740F80FC07770B7408E85FF58BEC89461AC380FC137C037429C3E835F78ACC2E8E1E4104BACE0332FFB80403EFD0E78A1D22D9740380CF01FECC7DF08BEC887E1AC3A14A04C1E003F7E203C18BF82E8E1E41048A058BEC88461AC32E8E1E3F048A3E62048ACFD0E132EDBE500403F18B148A0E49043C0D764A2E8E064504E8EEF375338A1E4A048AF88AC6F6E38ACA03C8D1E1030E4E048BF98AC7AAD1E941FEC238DA735989148B166304B00E8AE5EF8AE1FEC0EFC32E8E06430480F90774C3E98300750432D2EB0F3C0A751D3A3684047503E99300FEC68914E892F3750580F9077F058BC2E84CF6C33C077504E8C581C33C0875830AD274DEFECAEBDA32FF32D22BCB3A3684047406FEC603CBEB9589148B166304B00E8AE5EF8AE1FEC0EF2BFB2BFB268A6502508B3E4E048BF3D1E603F7A08404F6E38BC8061FF3A58BCB58B020F3ABC3B90100B40AE8BCC6FEC23A164A0474038914C332FF32D289143A368404742EFEC6EBED89142E8E064504E8FCF2740E2E8E06430480F907740432FFEB108BC2E8ADF58BF9D1E74F8B1E4A04EB9133C98A3684048A164A04FECAB001E970F72E8E1E3F04F6068704087403CD42C3E876F68BECC6461B00C32E8E1E3F048ADF32FFD1E389975004D0EB381E620475058BC2E85CF5C32E8E1E3F048ADF32FFD1E38B9750048B0E60048BEC894E16895612C32E8E1E3F04A0870424800A0649048A264A04F606870408752DE85DF27407803E4904077F21518ACC8A2E8404BEDB8581FEE48574102E3B0C740583C603EBF024802E0A4402598A3E62048BEC89461A895E0E894E16895612C3841823842B33842A322E8E1E3F043C047F1B5052BACC03ECA8015A587408803E6304D47408C3803E6304B475F83C1C73F432E48BE8D1E52EFFA617864F866F868186B686008600860086DB86F386F78600860086008600860086008625870086298744870086838700869187AC87B387BF87E387803E4904137415E8BFF48BC386E0E870EF0BED74078AC732FF268801E893F4C3E8A6F48AC7E844FC0BED74F026887D11EBEA803E49041374E306E88CF41F0BED74078BF2B91100F3A48BF2E8DE0132E4B91000B2C09CFA8AC4EEACEE9DFEC4E2F4ACE807FCEBB580FB0177B0E843F4B2C0B030E8FBF024F780266504DF80FB0074070C08800E650420EEEB90E89D018AC3B2C0E8DBF08BC8EEB020EE8BEC884E0FE978FFB311EBE48BFAE805F4B9100032E4B2C08AC49CFAEE42EC268805FEC44AEE9D47E2EE9CFAB011EE42EC9D268805E8E3F3EB5AE8CE00C38BFA518BC3268A35268A6D01268A4D02E8CA0083C7034359E2E8C30ADB751AE8B6F3B2C0B030E86EF0247FF6C70174020C80B430E870EEEB1DFECB751CE898F3B2C0B030E850F0EEA8807503C0E702B4348AC7E851EEE87FF3C38AC3E8D1008BEC894E16887613C38BFA518BC3E8C30026883526886D0126884D0283C7034359E2E8C3BAC6038AC3EEC3BAC603EC32E48BEC89460EC3E83FF3B2C0B034E8F7EF8AF8EEB030E8EFEFB301A8807505B300C0EF028BEC895E0EEB9C518BC3E87300E82A008AC3E852004359E2EEC3F6068904027403E816008AC3E83900C3F6068904027403E806008AC3E82E00C350B01EF6E650B03BF6E550B00BF6E15903C15903C1B164F6F180FC327C02FEC08AF08AE88AC858C352E839005A538BDABAC8039CFAEE428AC7EE8AC5EE8AC1EE9D5BC3E81F00539CFABAC703EE4242EC8AF8EB00EB00EC8AE8EB00EB00EC8AC88AF79D5BC35051E881F2B9FF7FECA8087502E2F95958C32E8E1E3F048BF8240F81E7F000C1EF0383FF067F182EFFA5A788AF88C4886289BE893C0374083C047F03E8CF01C3BAC403B0038AE3EFC33C0477F2505350528B166304B007E8EBEE8AE0D0EC80E401A840740380CC02B012E8D8EE40A38504B009E8CFEEA8807404D12E8504A185048BD03DF401731BBAE0013DC2017313BA90013D7C01730BBA5E013D4A017303BAC800891685045A58C6068404FFE85D015B588ADF32FF0AC0740EB30E3C017408B3083C027402B3108ACB8AE981E9010280F9087E0481E90101871E850453E85BF25BE88502C30AC07411FEC8741AFEC87438FEC8743CFEC87440C3892E7C008C067E00C38CC88EC0FECA0ADB740732FF2E8A97A289890E850488168404892E0C018C060E01C3000D182AE80903B90E00EBD6BDB258B90800EBCABDC560B91000EBC20AC075BD8B0E85048A16840480FF07773580FF0177100AFF7506C42E7C00EB26C42E0C01EB2080FF02750B8CCD8EC52E8B2EA471EB100E078ADF32FF80EB02D1E32E8BAF158A8BC58BEC894E1689561289460A8C461EC3C560B258B25CB260C560C57053068A264904E8C7C3268A4702268A6733F6C4017422BDC5603C107D0EE871028C060E013C0E7D07BDB2588C0E0E01892E0C01E81001EB2DB4843C107D13B4813C0E740D7F15B4023C08740580CC80EB0A26F6470501740380E47F86C432DBE80600E8C901075BC38BF88BF2BACE03ECB80500EFB80604EFB2C4ECB80204EFB80407EF8BD68BC750247F0AC074220E0733D2B900013C047507B710BDC560EB10FEC87507B70EE8E801EB05B708BDB258E82D0058A8807400BAC403B80203EFB80402EFB2CCECA801B8060E7502B40AB2CE50EC58EFB004EE32C0EEB80510EFC3FC0BC97501C380FF0E750A26837EFE10750380CD801E061F2E8E0641048BFAC1E705B0405380E303F6E35BF6C3047402042086E08BD003FA8BF5E32832C086FB32FF51F6C5807401468BCBF3A483FB207407B920002BCBF3AA59F6C580740146FEC975DE1FC38A264904500657C43EA80426C47D0C8CC50BEF74308BEF83C707268A053CFF742438E0740347EBF28BFD268A05FEC8A28404268B4501A3850426C47D03893E0C018C060E015F0758C326F64733017401C3C41EA80426C45F088CC00BC3741FBF0B00268A013CFF7415473806490475F2268A0732E4870685048BD8E80100C38B1663048A268504FECC80E41F9CFA80FAD4740BB014EE42EC24E00AC4EE4AB009EE42EC24E00AC4EE9D8AC88BC38A168504F6F2803E8404FF7507A28404FE0E8404F6E2F6C1807402D1E0488AE0B0128B166304EFA04A048A268404FEC4F6E4D1E0050001A34C04C38A264904500657C43EA80426C47D088CC50BEF744A8BEF83C70B268A053CFF743E38E0740347EBF28BFD268A3D268A5D01268B4D02268B5504268A450A3CFF7402FEC850A08404FEC0F6268504A3850458A2840426C47D068BEF32C0E8DBFD5F0758C3505351522EA149040BC074092E8B2EA4710E07EB08B83011B702E8C7BE5A595B58C33C047C01C3E3FD532E8E1E3F0486FB32FFD1E38BFB81C750048B355B8915568BF05153268A4600453C0D7F1F750432D2EB403C0A74323C077505E83179EB623C0875080AD2745AFECAEB27F7C602007405268A5E0045B90100B409E864BEFEC23A164A04720C32D289153A3684047306FEC68915EB2B50E8ADEA7508B80008E840BEEB09803E49040774F132E4863E6204538AFC55E825005D5B863E6204588B155B59E2155AF7C60100750289158B053A3E62047503E834EDC3E964FF33C98A3684048A164A04FECAB80106E8F3BDC32E8E1E3F040AC0750DE818008BEC895E0EC6461A1AC33C017509E841008BECC6461A1AC3A08A04BFA28E2E3A057204BBFFFFC332E4D1E003F82E8B5D040ADB74050AFF7504C386FBC3A0100424303C307406F6C30175EFC3F6C30174E9C3BFA28E2E8A0D32C083C7042E3B1D741286FB2E3B1D740B83C702FEC038C87EEBB0FFA28A04C3BB0800F606890402740EBB0700BACC03ECA8017418BB0800BAB403E8DFEC7421B701E88CE980FAD4741786FBC3BAD403E8CAEC740CB702E877E980FAB4740286FBC30F080F080F080F08030103010101000801010101010101010F010F080F0400020F0201010F01FF01FFE00F00000000070208FF0E00003F00100108000000000100020201000404010005020500060106050600080108000702070607CA003400900096000000000000005F57C390506652E8F4FFFFFF81EF100000002E8B0766BAF80CEF66BAFC0CED32C0668BF8665A58C366B84F03665266565357500AFF7544E8C8FFFFFF6633F666BB5300E848000000C1E810F6C440752B6681E2FF0266D1E2668BC26640C1E010668BC266BB1300E83000000066BB1200E827000000665832E46650585F5B665E665AC39066B84F03C39066B84F03C3906652E811000000ED665AC3906652E805000000EF665AC390668BD75033C0668BC36603C6C1E002EF6683C20458C3AA379D379D379D378837883788378837CA3341346B34AC35AB35AB35F1355636863643376C376C37E335D635D635D635D635D635F1355636863643377137B7376C376C37FFFFFFFFFFFF0000FFFF0000FFFF0000FF000000FF000000FF000000FF000000000008100008101800081018CE3101CE3102DC4503BC4503F33203A73203CF3104E83104F83104CE3103000000007B3900027B3901027B3902027B3903027B3904027B390502753B0002753B0102753B0202753B0302753B0402753B0502AA3B0002AA3B0102AA3B0202AA3B0302AA3B0402AA3B0502E53D0002E53D0102E53D0202E53D0302E53D0402E53D0502E53D0002E53D0102E53D0202E53D0302E53D0402E53D0502AC3C0002AC3C0102AC3C0202AC3C0302AC3C0402AC3C0502E83C0002E83C0102E83C0202E83C0302E83C0402E83C0502593C0002593C0102593C0202593C0302593C0402593C05028D3C00028D3C01028D3C02028D3C03028D3C04028D3C05023D40000070400100704002005D4000004B3F0002443D0002443D0102443D0202443D0302443D0402443D0502633F0002B8410500B8410100B8410000B8410200F9410000F94102003E420000CE3E0002CE3E0102CE3E0202CE3E0302CE3E0402CE3E05028A400000B240000033410000AE410000923D0002923D0102923D0202923D0302923D0402923D0502AD410001AD410001B13A0002B13A0102B13A0202B13A0302B13A0402B13A0502D2400000AE410000AE410000AE410000E33F0000D53B0002D53B0102D53B0202D53B0302D53B0402D53B0502043C0002043C0102043C0202043C0302043C0402043C05023A3C00023A3C01023A3C02023A3C03023A3C04023A3C0502F540000018410000D63C0102D63C0202323D0102323D0202A60002010C930000000000000CAB00003293000000004294000000000C95449900000000000000000000000028A07E93EC93D0981494000020C3000000000000000000000000E4A056A1CAA100000EA2000054C20000DEA2B4A474A5D2A614A7BABF0000000028A70000DEBC00000ABFEEA80000C6AA0000000000006CC13ABE0000000000000000000000000000000000000000000000000000000020AE2CAF62BA82BC00004A000201000000004CD144C314D20CC440C448C668DD92C800009CC456CAA8C43AC8C2CA00001CC548DD000034DD000030C50AC678DC0000000010C680D2000000000000C8DC000000002500020100083700004BE50004491900020502060000005215523D5218521A0D655300025B004B000101000037000042210063001F006301390063033F00630245005A5A5B030540000005042D1940001505400201020C00400200000D005B020000E30D5B020000E70D5B020000E80D5B006E0002010C083700003D2500004422003D250006445D003D2500044458005538005B01050000616001003CE5010080492A000105000062600100010101000156004003A940000105000061600100010201004002E500015B02E500015B01050000616001003CE50100804965005B280002010000370000010500006CA80100020000010002010100010500006DA8010002000201005B2E0002010000370000521603014100150541100102600F41030140001B0540100102620F400105F30FE10A602D5BCA0002010404370000660C030C4100002D0A41422D0D4204003D240006004431002D0D4208003E0A42414519005520005B5600430324430500030446000033054601000000010200004603000001000D020100442D054602000000010200004603244304004BE5000149AA0007020100452D05460100000001020000464A02010044449000032943000EA200444398000329430008A2004533054603000000010200004601020100005B0D020100440104000000003DA5000144C400070201004543C9000D020100445BC303010710083700003D2501FF44A1033D250119469D033D250102479D033D25011445A1033D05000000000044FD01661B5600023DA501024941005608404353003DA50103494E00560840435300030C4018003E0D400000446200030A02404366000EE501804BE5010249740002A9020255280203010000030546A86100003DA50100448D0003054650C300005CA50F5EF3085528013E0500404B4C0047A7001B05000143BC002C6501013E0500A025260048BC001505000143A700142D01044BE5018049EB00210502800000007C0240007E0240467C0540100000007E0540350C00000302024043EE00560002270200462105410000010027024046030A42403E054100000000491601030D40010056080143400103024046030201410302034127024041030240033E054100000000491E0127020103030A014027024603030A0301030A0140038A0142270200463305401000000015054005038A034066FF2D0D42AB035600400321400133254014152540012D0A4240030C4800004A25065E044423025600404BE50130449B014A25F15D0144DC0143A3014A25F15D0149DC010300400B5E090D40F0FF3E1A400349DC013C02075E0149DC013C0A0A5E0349DC010300400C5E092540703E29400149DC013C02085E0244E0010EE501013A00004BE501014475034BE5010249FD013D25020446FD0155280252233A000002010302020502000003040221020132250214524D020102033D050000000000449D033DA50100444E0202010302020502000F030002210201322502144BE501304448020EE50201524D0201020366FF2D0D42AB035600400321400133254014152540012D0A4240030C480000030540000038003E0500C0C62D0047A0025EA540CF203E0500E067350047A0025EA540CF103E050000093D0047A00209A540CF5CB20F5EC34003054020001C243DA5010044BB0203054010000C125C9A105E0300405C1A0B5E0F00035CA20B5E8F40560040032940010F2540014BE5018049E5020F6540015C0A0C5E8BFE40078D0D5E0FE03E8D010000490A033E0D030000490A0307E50E5EFE430F030DE50E5E014AE50E5E014927034A650C5E0149270307E50E5EEF432C030DE50E5E100102075E010102085E027C050200EC04007E0240462705400A0000000102095E40010A0A5E033A00003DA50100449D0303010002020502000103040221020132250214524D020202003A00003D250204469D030225030202E103020261030102B9030108A503040EB1030202010200522E3A00005B0225010B4375037A18000000D800B001880260033804000000010002000300040005007300020100003700003D65000144720056004003214000212540DC030A48400105B63A000100005C052D3BCFFFFFFF200000005C05403BCFFFFFFF200000005600400321400021254080030A48405C050150FFFCFFFF0003000056004003214000150540195C025050FFFFFFF1403A00005B5B00E4060201080437000042290063071302630817005A5A5B0D25C839025C253447FC010125320100010542350000000001054035000000000105463500000000010544350000000001054A3500000000010548350000000001054E350000000001054C3500000000010552350000000001055035000000000105613500000000010563350000000001056535000000000105673500000000010569350000000001057235010000000105DF39021000000105B33A000000000105B13A001B5D050105063B350013000105073B361100000105083B41E601000105093B0000000001050A3B0000082C01050C3B0204000001051F3B5E4E010001050A3B0000082C01050D3BA401000001050F3BA40100000105143B000200000105153B49D200000105183B200000000105193B240D000001051C3B0000000001051D3B000000000105ED3A000092060105EE3AAA0800E00105C939FE0100000105CA391E0500000105CB39BA0400000105CC39240400000105CD39A20800000105CE39FE0100000105CF391E0500000105D039BA0400000105D139240400000105D239A20800000105D339FE0100000105D4391E0500000105D539BA0400000105D639240400000105D739A20800000105D839FE0100000105D9391E0500000105DA39BA0400000105DB39240400000105DC39A20800000D25C839020D25DA4101012533470001253147000125324700012545480001658B4FF05B01051F35FFFFFFFF010520351F00000001053B016402120001053001A0861100010531013C000108018D8338640001258238010125320100010542350000000001054035000000000105463500000000010544350000000001054A3500000000010548350000000001054E350000000001054C3500000000010552350000000001055035000000000105613500000000010563350000000001056535000000000105673500000000010569350000000001057235010000000105DF39021000000105B33A0000000001058F3B1000000001056B3C200000000105473D300000000105233E40000000550001200D01DC00030A48400105B13A001B5D050105063B350013000105073B361100000105083B41E601000105093B0000000001050A3B0000082C01050C3B0204000001051F3B5E4E010001050A3B0000082C01050D3BA401000001050F3BA40100000105143B000200000105153B49D200000105183B200000000105193B240D000001051C3B0000000001051D3B000000000105ED3A000092060105EE3AAA0800E02C0501010000003D0D01050045FE025608480105C939FE0100000105CA391E0500000105CB39BA0400000105CC39240400000105CD39A20800000105CE39FE0100000105CF391E0500000105D039BA0400000105D139240400000105D239A20800000105D339FE0100000105D4391E0500000105D539BA0400000105D639240400000105D739A20800000105D839FE0100000105D9391E0500000105DA39BA0400000105DB39240400000105DC39A20800000D25C8390255000166FF2D0D42DA06030C4800000D25DA4101200D011B00030A4840012133470101213147010121324701200D010400030A48400121454801200D011000030A4840030D4000F00F614001016A8B4F402C0D0101002D0D4202003D25010545600456084855000152172C2501013D25010545BE040205010502000052296608030C410C003E0D41000044020501A5150103010513011027000001011401010D251501014A6515010244FA040101420101010146010101014A010101014E01010101520101550001524E5C05DD5D00F0FFFFAA0A00005C056353FFFFFF00000000305C056553FFFFFF00000000305C056753FFFFFF00000000305C056953FFFFFF00000000305C056B53FFFFFF00000000305C056D53FFFFFF00000000305C053155EEFFC0FF110001005C053156EEFFC0FF110001005C053157EEFFC0FF110001005C053159EEFFC0FF110001005C05315AEEFFC0FF1100010001059A550100000001059A560100000001059A570100000001059A590100000001059A5A0100000002250107523302050100070000550002524D2C2501013D25010645E805661603A40006002D0D420800030A00423EA50000447906030A4200030C0104003E0D0121214425063E0D012122496D06030C40080066162D0A424003244000003E2540FF446D063E25401449650603044002004C054000010000446D063E0D01212244620601A5596101436D06436D062D0C4201004330062D0D00100033A500014305066616030C4104004C0D410200448D060DA54C0002521601015339020101543903010555390000000003014101150541180102C40041030141011B0541080102C900410300415539010259394103014003330140022D02404101025A39405B7A0A0000006B01D60241040B29BC000201000466FF5608472D0D42740003214700092547F042224763005B00636056006320360063904E0063A03E0063B046005A5A5B2D0D423000435B002D0D422400435B002D0D423C00435B002D0D421800435B002D0D420C0003214700092547072D0A42472D0A4247030C4800005B7ABC000000800000018001000280020000000100020003000400050000DC00B801940270034C0400006B01D60241040B29762A0000D800B00188026003380400005A00B4000E016801C20172000101000037000056004003214000210D406B01030248400125AC41013D650002494C00010DBD4101005400BB410D25AE41010105AD411100000007A5AC41FE0105AF4111011101436E000105B141000000010105B541000000010105AF41110111015400AD41010DBD4100013A00005B7300010100003700005214030041C041331A4141038A4041030041C141331A4141030A40413E0540000000004936000305407008000F0E2500B052143D650000446D000102164D400105174D000000000105184D000000000105194D000000005C05144D8FFF0FFF310000005B0725144DFE5B0043000101000037000052143D650001443A000D65015003542001504AA5015001491B0054200F5056004020250001030A484007E5E8397F433F000D250150013A00005B00CF000201000037000042290063001B0063011B006302AA005A5A5B66FF5608402D0D42C30003214000152540012D0A4240030C4800003D6500004472000D25CC00013A0000018DC000000251020105C600000010000105C80000005000010DC30002005420CA000105C20000010000431A000725CC00FE3A00000D25CA00010125C2000107A5C100FE0D25D500010D65D500014A65D500014493005408D5005400C6005400C800431A005C65D400FC0201A1C000002BA5C000010DA5C100015B7A0C00000002002C002D002E002F0000D501030104003700006608030546102700003DA50002491E00020200465B0305400C0000002121400066FF2D0D4281012D0A4240030440000003044104000304000800010200004003884001000318400100098D40FF013E8D40000049990001020000410300400100090540FF0100003E0D4000004982000305460071020043BC00210240460300410100090541001E00001B05410943B4007C0240467E054000000100030041010009054100F000001B05410C75024041030246403DA5000149C800020200465B3DE50000490B0156004003294000210D400A00030241002D024041010200004003004101000905410000F0071B05411402E200413DE50000490B01020500102700005B5600400339400055380066FF2D0D4259013E0C400200472C012D0D420800431C01330C400400210C4006002D0C40000003094200550000020A00407C054640420F007E014000020200405B7A7C00FFFF070000000000C8003F000800190040065F0040003200800C7E006000640000327F007F006400116C0100006C01004C6C01000D6E0100006E0100486E01000D70010000700100487001000D6E0100006E0100486E01000D7E0100007E0100487E01000E72010000720100497201000EB0010000B0010049B0010000BF0002030400370000560046560000032100005520003D650003442C003D65000D46B40002290000322500080E25006052145C222855F80002220000030D41010066FF2D0D42BB002D0A424103240000003DE2000048A0003E250004446F000322460033254601152546040F254601333900003E250001448C003E250002448500032546210365002F439000036500130379460033654601152D46030F65460152140102014D460152004D005400054D5400FF4C3A00005B7A040003020104005E01010404083700003D6502014927014BA50203492A0052250205000000000002050100050200432F005528025225033800C400034800C9000E2502905214082502070D05B43A111101005C25B33A0B0103214102152541040D22B33A410D65B63A015C25DB3AFD01030241001B054108010ACB3A41010ACF3A41150500180102CA3A000102CE3A004BA5020349A0002B05CA3A000010002B05CE3A00005000010DA73A8000010DB13A0003010D0C3B010301050A3B0000082801050B3B0000080001E5EF3A0801E5EE3AE05400A93A0119AA3A000189AA3A000119AE3A000189AE3A00070DA53AFFF866FF2D0D424F01030C4000003E0D40FFFF440E013D8C010000440E012D0D42030043F1000124A53A02000109C73A010725B33AFE0725DB3AFE3A00005B0E25029052143D650200493C010D25B33A014348013D6502104448010109C73A013A00005B7A0F00010001010103010502020008FFFF0842000101000037000052143D65000144210054204B504A654B5001491600433E005C4D1B50FEFF00014AA5015001443E000D254B50014A654B50014436003A00005B1300010300003700000E2500A052143A00005B00C6010101001856004003214005210D408000030A4840370000010D47500D003D8D010D00462C000119475001018D48504001010D49502C01030941002D194100038A41412D8D4101001B1D4102011A485041330D410100010AEA4F415408EC4F0199EC4F02031941003309410256184103B14104331A4141018AEB4F4103194100330941022D1A41412D0941004B2504104498002D094100010AEB4F4103214104092541021B2541010122ED4F41030941012D194101330D410100010AEF4F415408F74F0199F74F03031941013309410356184103B94104331A4141018AF64F4103194101330941032D1A41412D0941014B25042044FC002D094101010AF64F4103214104092541041B2541020122F84F413D65050044210107650150EF4326010D65015010030046EB4F020002F64F56004003214005210D400100030A4840560040030940023D650500495301330D4002001505400F5600413D8D020D00486B01030D410D00331941020F0240410FE540800102E8394056004003214005210D406B01030A48400109C341000189C341010109C441000189C441010102C041460101C141025400BE410131BE410401B1BE41045400BF410139BF410401B9BF41043A00005BD80101010000370000560041033941010925410F3E254107491C005B560040036240410102585340030A464266FF2D0D42C001152541022D0A4241030C4800000705905D00000100030C48020003054050C300005600410321410027024041150540100325400201026253400105635340000030030A42465608480D255A530154005953560041037141010FE5418001027253410369410003A5410101027253414B25010144D5000371410003A5410201027253410379410003A541030102725341030540003101002DA9400101026E5340430801037141010F65410103A5410201027253410305400011010001026E53400305400130000003A9400101026F53405CA55853CF100D2558530102650002560040032940012D254004210540C80000005600410321410027024041030A4140330D4101003E0D41000044AC0151644A255B53044432014A655B533149AC01026500014B25010149AC0101057253010003803D65010149730102A800725343AC0156004103194100560040030A40413B02400328407253036840725303A840725303E8407253040200402DA541042D0D4104003EA94101457A010D255A530201255853025101540058535B7A18000000000004000200080004000C0006001000080014000A004600020200043700005530003225000120250008560848032248400DA5D5530102A000D45308A500034A25D45302443C005C0DD553FFFE01004342000D0DD55301013A00005B1403010500003700000E25006052140825000F422900630F530063110902631266026301CC026300F5026308D8016309B901630AC0016313C8016314D001630BE001630CBC02630DE801631001025A5A43B50154009A55010D2B551F003DA500004472003DA5000244A2013DA5000549A2015400C9553D250200498100022502023225020101E1C955024A25CC550149B5017B0501008000007E05408C0A000056004603294602270240460765D055FE0105D155008000000102D255400DE5D355100D65285504510107652855FB5101032140021525400501E2CA55405420CE5502A0022855030A464808A5020756004003314002210D408000038A4640030A4840038840EA4F030840EF4F2D054001000100039841EB4F031841F64F030A484601020C564001020D5641031A4846030040EB4F331A4040330840BE41330840BE41030041F64F331A4141330841BF41330841BF41030A4846010A0F5641018A0F5640031A4846030040EC4F338A4040030041F74F338A41414A25ED4F014485010FE540804A25F84F014491010FE54180030A4846011A0E5641019A0E564043B50107E528552F0D65285504510107652855FB51013A00005B5420D85543B5010125D8550143B5010125D8550243B5010125D8550343B5010725C855EF43B5010D25C8551043B5010D65D05501510A0725CD55FE510A010DCC55010251C843B5010D25DE551043B50101696F55023DA500034925024A2535551049250201A56F5502432A0201B16F55003D250200443F0232250201142502045CE16F558F023DA50005444D023DA50000495E0202A5000003394000332540010122CB554002E002705543B50102E00270554BE5020144B50102B0006F553DA50000448C023DA50005448C0202E5000443950202E000CB552CE500013DA5000244A3023DA5000349AC0254007055500243B50102A50000033143004A626F554444B5015408CC5551C80D25CD5501513243B5010D257055013DA5000044E102010DA1550F0143B501033943000302404433254001010AA1554043B5015400A15507257055FE070D6F55FF8007253555EF5420C8555420D85543B5010C01010604003700004229006307EA00630125006300C000630BED006304F2005A5A43050102650010524D3D65000044E6000265001152044BE5020149E6003DA50000495700030100000265000F553800524D020200000265000A550802524D3DA500004970000265000B524D4379000265000E524D43AD0020050164000000020501141E00022C2101000301000002020040520C26050064000000020201400202000002650001550802524D5105026500015204510A02650009524D43E6000265001252044BE5020144E60002650008524D0265000052043DA5000049E60002650000524D3A00005B43E600524D43E6006606022900000268004E00028C00200052335B0229000052335B350B020208003700003D25000344220B66FF2D0D42290B56004003214000152540012D0A4240030C4800003D650010497400026500013D25000445220B4AA5F95D0144220B026500004AA5155E0249220B0D25165E010705155EFFFFFBFF3DE50004456D004AA5155E0144220B0265000143220B3D2500044885000305000101010143C5004AA5F95D01447B004AA5155E0249220B0D25165E010705155EFFFFFBFF030500010100003DE5000144C500030500010100003DE5000244C500030500010101014229006307EF00630ADD0463014D056300DA0663097C086308EC09630B9F0A630E4D0A630F0E015A5A5B0105FD5D000000000105EE5D004000005C05F05DFFFF0FFF0000400043220B4AA5F95D0149220B4A25005E014942013C25F95D004942013C71F95D0049420108E50001030040F15D092540013E39400044220B5420F95D074DF15DDFFE4A65F15D40494C010D05035E010101010D25005E010DA5005E200D25005E010D05035E0101010103394000092540015C22F15DFE405C65005EC1060D25025E080DE5005EA05C05065EBBBBFFFF333300005C05035EF7F7F7F70202020266072D0C420A005600402025000C2D0A4240032440090003624040038A40405C02045EF8F8F8F8400321430003A246443DA500004415020305400400000066072D0C42040003044100003E054100000000444C024CA4460600490D022D0D420C0043EE010324400700434C020305400500000066072D0C42080003044100003E054100000000444C024CA44604004942022D0D4244004323022D0D42080003244005001505400E5C02005EFF3FFEFF400765005EFE3DA500004900035C050B5EFFFF8FFF000020000D050C5E010100005C050B5E0F00FFFF401600000D050E5E000000010105075E0500666601050A5E020000000105095EF32001000105085EF3DF000001050D5E000000005C050B5EFFFFF8FF000000005C050C5E8FFFFFFF200000000D050E5E0000001007050C5EFBFFFFFF01050F5E3E0008000105105E3E0018240105115E3E0000000105125E3E0034004390035C050B5EFFFF8FFF000010000D050C5E010100005C050B5E0F00FFFF600A00000D050E5E000000010105075E010052F854000A5E0105095EE90900000105085E5C0F000001050D5E000000005C050B5EFFFFF8FF0000040007050C5E8FFFFFFF0D050E5E000000100D050C5E0400000001050F5E3E000C000105105E3E0080880105115E3E0000000105125E3E0034000DA5065E080D25F35D010D65F15D204A65F15D40499F030DA5F15D010725005EFE0705035EFEFEFEFE4AE5005E1044B90366072D0C420C0003044000003E0540FFFFFFFF44EB030104F45D00000104F55D04002D0D42080043C8030105F45D382000000105F55D0C0000005600014A05035E2020202044240451022D0501010000003E0501A086010049FE030125F95D0343220B0D05005E00010000030040045E0905400700000021054003000000030541212000002D0241400102F45D41030041F55D0105F45D840000000102F55D41030541222000002D0241400102F45D41030041F55D0105F45D850000000102F55D413D25000445C004030040005E09054000C001001B05400A0105F45D21000000030041F55D0925410F0F2241400F2541800105F45D210000000102F55D415600413DA5000044CF04030D4101015CA20B5EF8410D65005E0143220B030A464866072D0C420A005600402025000C2D0A424020250002030A484001042E5D000007E52D5DFC030A4846030540010101013D250004452F054AA5F95D01442F054AA5065E01492F05090540FFFFFEFE0D02035E40510503024000690540FFFFFFFF0702035E4051C851C843220B4A25FC5D0149220B3C25F95D0049220B4C250001446C050D05065E040000004C650001447B050D05065E400000004CA50001448A050D05065E000400004CE500014499050D05065E0040000003024000150540040D02035E405600014A25FC5D0149220B0302400015054005030041035E09024140090540202020203E02414044EB0551022D0501010000003E0501A086010049A9050125F95D0443220B0302400015054004690540FFFFFFFF0702035E405600014A25FC5D0149220B0302400015054005030041035E090241403E05410000000044400651022D0501010000003E0501A08601004902060125F95D0543220B5600014A25FC5D0149220B4A250C5E80496E0651022D0501010000003E0501A08601004943060125F95D0643220B030A414856004003214000030A48400D25600101510A030A48410D25E85D034A25E85D04448D060D65F15D124A65F15D04449A064C25000144AE060D65F05D104C65000144BA060D65F05D204CA5000144C6060D65F05D404CE5000144D2060D65F05D800171F95D0043220B4A05065E4444000044220B0765F15DFD0725E85DFD030A414856004003214000030A484007256001FE030A48414C2500014416070705065EFBFFFFFF4C6500014425070705065EBFFFFFFF4CA500014434070705065EFFFBFFFF4CE500014443070705065EFFBFFFFF07650C5EFE5400085E5400095E030040065E4C2500014467075E0540FCFFFFFF030000004C6500014479075E0540CFFFFFFF300000004CA50001448B075E0540FFFCFFFF000300004CE50001449D075E0540FFCFFFFF003000003C02065E404451080102065E4003024000150540040D02035E405600014A25FC5D0149FC070302400015054005030041035E09024140090540202020203E02414044FC0751022D0501010000003E0501A086010049BA070125F95D0743220B0302400015054004690540FFFFFFFF0702035E405600014A25FC5D014951080302400015054005030041035E090241403E05410000000044510851022D0501010000003E0501A08601004913080125F95D0843220B0302400015054002690540FFFFFFFF0702035E400302400015054001090540020202020D02035E4043220B4A25FC5D0149220B56004020250002030A4148030248400DE52E5D10030A48413DA5000044A8080D65F05DF00DA5F05D010DA5E95D013DA5000044C4084A05065E3333000044D5090302400015054001690540FFFFFFFF0702035E400302400015054002090540040404040D02035E40030040065E4C25000144FF08090540FCFFFFFF4C650001440D09090540CFFFFFFF4CA50001441B09090540FFFCFFFF4CE50001442909090540FFCFFFFF0102065E4003024000150540040D02035E405600014A25FC5D0149220B0302400015054005030041035E09024140090540202020203E02414044800951022D0501010000003E0501A0860100493E090125F95D0943220B0302400015054004690540FFFFFFFF0702035E405600014A25FC5D0149220B0302400015054005030041035E090241403E05410000000044D50951022D0501010000003E0501A08601004997090125F95D0A43220B0302400015054003090540080808080D02035E4043220B0302400015054003690540FFFFFFFF0702035E4007A5F05DFE4C25000144110A0765F05DEF4C650001441D0A0765F05DDF4CA5000144290A0765F05DBF4CE5000144350A0765F05D7F07A5E95DFE56004020250002030A484007E52E5DEF43220B0321430003A2464466072D0C4204003DA5000344710A66072D0C4206003DA5000249220B03044100003E05410000000044220B3D020141468F0A4CA446060049970A2D0D420C0043710A030441080043FE0A08A5001B66072D0C4208000321430003A2464403044100003E05410000000044220B3D02014146D00A4CA446040049D80A2D0D42440043B20A2D0D4208003DA400000044F90A03244100003E25411844F90A2D0D42060043DD0A03044101005C020F5E0000FCFF415C02105E0000FCFF415C02115E0000FCFF415C02125E0000FCFF413A00005B7A0C000000D800B001880260033804001F02010200003700003D0D00000044CE01560041032141010925410F150D4102030A404266FF2D0D4207022D0A4241030C4802000DA5905D015408905D030C48000003F94101153D41045CBA10548F41030A42404A251054014981000D0D105401010D251054104A2510542044670007251054EF4A251054204974000D25135440560041030941003B0241033B41001B25410401A211544103694101152D4104012A1154415600400FE54080037340000102165440560040036B40000102165440036340000102165440037B40000965400F01021654403E254104471001332541042D054604000000036340000102165440036B40000102165440037340000102165440037B4000010216544043D7000D251354020D25115401032940012125400A2D2540644A251454014942015114332540013E2540004926010265010143CA014A051454F08FFF004454010265010243CA0101051654010000800300401654026A014002B801145408A5011F3DA50100467C010265010343CA0132A501013D8D00000044CA013DA5010044CA0103314101031940005618403B02400328401654036840165403A840165403E8401654040200403E25410447CA01332541042D054604000000439D013A00005B66FF2D0D420702030C480000018D18543200010519547A1C020001051A5410113D102D0D4204002C2500013D25000649D5015608485B7A1800000000001C0004003800080054000C00700010008C001400005C00010200040225010403314100090D410F00150D410166FF2D0D4250002D0A4241030C48000007A5905DFE010D905D111150024A0D935D0100494100022501135408905D5400925D3A00005B7A0C000000040008000C00100014005B01020104043700004221006307290063034E006302600063048400630C1201630D1B015A5A435A01010D455D9F0F66060124475D3000014C475D31000324463B003E254600445A015420475D5B0DE5475D015C05435DFFFFFFFD110003005B0DE5475D014A25445D024472000DA5435D010DA5435D025C05435DEFFFFFFD010000005B4A055300000200004494000D254B5D013D8D00000044110103054680F0FA0256004103194100210541FF0F0000270246403E05410000000044C4002D0D400100018A455D4056004103194100210240412702464001A54A5D0C010A4A5D4015054004560041032941002D0D410100210240411B054008010A485D400DE5485DC007254B5DFE4A654B5D014909015B0105435D000003005B0DE5475D014A05435D010000004441014A05435D10000000494E014A05445D010000004936015C05435DFFFFFEFF000002005B5C05435DEFFFFDFD010000005B00D00002010000010500C2000000E001053E26430000005C057E1238FFFFFF430000005C057E18F8FFFFFF030000005C057F12F8FFFFFF030000005C057F18F8FFFFFF03000000010517742D0B150003004026743E0540F900000049700001050BF000001200010525CE3021210343CF003E0540F6000000498D0001050BF000002100010525CE2301102343CF003E0540F000000049AA0001050BF000003300010525CE3120312043CF003E05400F00000049C70001050BF00000CC00010525CE2031203143CF00010525CE203120135BAF0003020C003700000301000003010101030102025216030146001B0546080202000002020101020202023D6502004936002C2202463DE502004941002CA202463D65020249480003014003090540000000FC3E0540000000D0496E00010563C000000040550000552002437200540063C0010164C00056004003214002010265C040010166C00103314002010267C0400101E8C0033D65020144A6003DE5020144A60051024AE5A0218049A6005B00B201020200003700003D250101448D003D250102448E003D2501034433003D2501004993013D050000000000495E003A00005B523C03004024013EF94000445A004AA524011044410003F9400001022401404AA52401104452005538005B5420A453523C03004024013E3940004489004AA52401084470000339400001022401404AA52401084481005538005B5B66FF2D0D429A0156004103394101152541022D0A42413D65010B49010120050064000000030C48020003004140010F254110090D41DFFF030C4800004A0501500100000044EA00030C4802003C0241014049EA003C02400141449301030C48020007254001EF0102410140010A400141439301560040038D400C003D650118442401038D403E003D65011944240103A9400133A540140331400109254003152540040F0D4001015600410329410133254114030C4800004A05015001000000447101030C4802004A254001104971013C22430141497101031A48403C0A000140449301031A484007250001FE030C4802000122430141070D4001EFFF031A4840010A0001403A00005B7A180000000000800004000001080080010C000002100080021400E700010808000301000002050005000100522920050064000000030246400202000003010000553800030540003200003D05000000000044640003024046270140003E05409C180000475300030540003200003E0540C8000000466400030540C800000066FF2D0D42C7003E0C400200477B002D0D420800436B00330C400000030C0106003E0D011900499A00270D403200210D400200439F00270C4006002D0C40040002E20040330C400400210C4006002D0C40000027024640020A004002B200405B7A2000C8004006080019004006800C40003200800C381860006400003200327F00640000CB00010100003700003D65000144610056004020250010030A484007258F4FFD4A258F4F04492000521407254650FE4A65465001492F0003214000210D40DC00030A48400725B43AFE56004003214000210D406B01030A484007258541EF43C70056004020250010030A48400D258F4F024A258F4F0444710052140D254650014A6546500144800056004003214000210D40DC00030A48400D25B43A0156004003214000210D406B01030A48400D2585411056004003214000210D405A00030A48400D254C4D013A00005B00240001010000370000030041E30D330541010000001B05410B01020600410D251F0E035BC8000201D6098002A000E0012D00100060000A0002000000000008080600123CA00F2003000158021C00280080000100040000000000000000006A3C6419000440010003260018008800030006000000000000000600553C302A00050802C003280060007000010003000000000000000000E93C302A0005980100042A0030007000010003000000000000000000EA3C8F2F7805D0011A04270058009000030004000000000000000200EB3C483F40063002B00432004000C000010003000000000000000000EC3C3400020100000000002A002A00002A2A2A00002A002A2A15002A2A2A15151515153F153F15153F3F3F15153F153F3F3F153F3F3F5C00020100000000000000000000000000000000000000000000000006000000C8320000000034210000B80B000000007D0000010000000000FFFF0000000000000000000000000000000000000000000000000000000000000000000C00020100000000800000007400010110010612110116121301066A1401166A1601065517011655190106EA1A0116EA650116E966010AE921010A1222010A6A23010A5524010AEA450116EB46010AEB750116EC76010AECD2011670D4010A70D8011671D9010A71E2011672E4010A72E8011673E9010A73F5011674F6010A74140002010200080080000002000400084000FFFFDA0001048A0E05001331580021220000B70000000800000014326B001E210000BE0000000200000013337E001E220000C5000000000200001334910020210000CC000000000400001335A40021210000D300000000080000010491000204020003040200230602000000FF010492000204030003040200230602000000FF010493000204040003040200230602000000FF010494000204050003040200230602000000FF010490000204010003040200230602000000FF14060F000000FF14060F000000FF14060F000000FF14060F000000FF14060F000000FF050001010000380004030400000024F40000102788130000000000000000C2014E0C01010000550000001027000000020501000606000000000000000000F20105030E00360046005A01A201307500000C003F053A400000409C00000C003F053E000000FFFFFF000C003F05F380000000000000FFFFFF000C003F053E00000000000000483F00003F004400001600000004011F00000004022C00000004033E00000004081B500000040925600000040A35900000041021B0000004112FF0000004182A40010004786900003F004400001600000004011F00000004022C00000004033E00000004081B500000040925600000040A35900000041021B0000004112FF0000004182A40010004F0D200003F004400001E00000004012600000004023000000004033E00000004082240000004092C600000040A37700000041027900000041132C0000004182E00010004683C01003F004400001E00000004012600000004023000000004033E00000004082240000004092C600000040A37700000041027900000041132C0000004182E0001000400000000000102030203000100070500000102030203000100070500000102030203000100070500000102030203000100070500000102030203000100070500000102030203000100070500083000009B0000000730000046250000083100009B0000000731000046250000083200009B0000000732000046250000083300009B00000007330000462500005600000005000000FFFFFFFF0000000058000205010A01000C02040264C0000065C0000066C0000067C00000E8C00000A021000042EC0000102700000C04000000000000000000000000000000000000000000000000000000000000000000000000000000000000C401020500000000000000000000000000000000245053505B4809DF160000000000000000000000400400000000030000000000010000000060000000300400000000000400000000E0000000000000000000000500000000010000000A0300000000000700000040040000400B0300000000000900000008000000E4C90000000000001100000000100100001005000000000012000000005000000020060000000000140000000030000000100300000000002100000010000000000B030000000000230000000050000000000200000000002D00000000F0000000400300000000002E0000000080000000900400000000003500000038000000ECC900000000000036000000004000000070060000000000370000000010000000B0060000000000380000004004000000050300000000003A0000000062000000C00600000000003B0000000003000000220700000000003D00000000400000002507000000000003000000006000000065070000000000420000000008000000C5070000000000010000000000000004010000000000000000000001012C0000C540736900550069000000900100007C99050000000000000000000000000000000000000000006C000201B55D000000000100B55D000008080200B55D000010100300B55D000018140400B55D00001A180500B55D00001C1C0600915D000008089000955D000008089100995D0000080892009D5D000008089300A15D000008089400A55D000008089500A95D0000080897008A060C0001E2011D0900007E3A00007D00080000001B000000000000000000007100000000000000000000000000010000000A0000006C070000F30400003E040000F3040000F30400006B030000F304000004050000040500002A0300000000000000000000000000000000000000000000000000002C010000300100003001000030010000300100006400000030010000340100002C0100002C010000000000000000000000000000000000000000000000000000800000000E0000001E00000001010101010101010100010101010000000000000000000000000000000000009808000098080000980800007E040000980800007E040000980800007E040000A203000014000000AC0D0000AC0D00006400000069000000020000000000000001000000010000000100000064000000640000006400000064000000640000006400000064000000640000006400000064000000000000000000000000000000200300002003000020030000BC02000020030000BC02000020030000BC02000071020000320000002003000020030000190000003200000000000000000000000000000000000000000000001900000023000000190000002300000019000000230000001900000023000000190000002300000000000000000000000000000008000000FBEFFFA7230600005F000000000000000000000000000000790000000000000000000000000000000F000000660000006E006900690073007300730073000000000000000000000000000000FC700000FF0100004B004B000000000000000000A50AA50AF00AF00AF8116810800000000000020000000000000000000DE04D3EFCDEA6BD7498273F000002000000803F000000000CE5243E8CDB083EE145073F010104000000803F000000000CE5243E8CDB083EE145073F010002002289923FBD35B03CF77520BE2731803F1D38E73D01000200331B643FC8EF0D3E000000004A7B033FDAACBA3E01000200BADA5A3F9CE1463E764FAE3FE86A03C03199C23F010002007BA05D3FBB0F003E3945C73D780BA43E0000C03E0200020000000000000000000000000000000000000000000200020000000000000000000000000000000000000000002C016C07E803E803E803E803E803E803E803E803E803E803E803E803E803E8033001F304E803E803E803E803E803E80330013E04B004B004B004B004B004B0043001F304E803E803E803E803E803E8036400F40171026B033001F304E803E803E803E803E803E80334010405E803E803E803E803E803E8032C010405E803E803E803E803E803E8032C012A03200320032003200320032003D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D001D0016C07F3046B033E04F304F304040504052A03D001000303033001FB01F00AF00A280A480D480D480D8813181518151815F401F401F40100000000D0010000010200005B00000800000003040451006B02000000000000000032003C0000009001900190019001900190019001900190011E00DC05800CAC0D5500DC0501000102000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EC4CA13C6EC0E73C81785D3D73637A3D583934BC1361C33C000000000000000000000000000000000000000000000000000000000000000000000000000000000C010C0101010000000000000C010C0100020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000001E0046000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CB00000000000000000000000000000000000000190019006F060000C5060000350700006F060000C5060000350700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C8000405000000000000000000000100000000000000000000010200000000000000000000020301000000000000000000030401000000000000000000040504000000000000000000050604000000000000000000060704000000000000000000070000E718E7180002010300000000960000002A000000160000001B000000FF0005000500FF00FFFFFF0001201F0001201F00011421000000000090010000008001000000000000000000000000000000000000000000000000000000000000000000000000006C0003030000021130750000CC55010000200000312C00004C000000200352034605BC0200000000800000000000000000000000000000000000000000000000DC05000084038403460584030000000000000000000000000000000000000000000000000000000000000000F70902044B0057003F061F072B090000000000000100080400200000FF00000000000000000000000000000033000070080472008108000000040400C00000004B345A4146333235424D0000000000FFFFFF00000000001C000000514C01005F4C01005E4C0100604C0100614C01008140010082400100834001008440010085400100864001008740010088400100894001008A4001008C4001008D4001008E400100904001009140010094400100954001009640010097400100A3400100A440010098400100A1400100A8610000000000002501000000000000BA08000040000000090905030D0005000202000208000000050303000500000011040500000001010100010100111800DB0100000A0A00001E0000001E00000043512A020F0000000C000A0A080300011F2A0C001E00000009F1130F1E0000000000000050C30000000000002D04000000000000BA080000400000000A0F0905170008000202000208000000050404000800000011040500000001010100010100121800B60300000A0A00003C0000003C000000455136021E0000000C000A0A090300011F2A0C003C000000C9F1130F3C00000000000000F82401000000000045080000000000003A090000400000000D170D0723000C00040400020C000000050505000C00000021060500000001010100010100151800910500000A0A00005A0000005A000000485146022D0000000C000A0A0C0300011F2A0C005A00000089F2130F5A00000000000000CC55010000000000550A0000000000004A090000400000000F1B0F0929000E000404000210000000050606000E000000218805000000010101000101001718007F0600000A0A0000690000006900000049515002350000000C000A0A0E0300011F2A0C00690000000AF3130F6900000000000000A0860100000000005D0C0000000000005A09000040000000101E0F092D000F0004040002100000000506060010000000210806000000010101000101001818006C0700000A0A000078000000780000004A5156023C0000000C000A0A0F0300011F2A0C00780000004AF3130F780000000000000048E80100000000007E00000000000000EA090000400200001426130D3900130006060002140000000607070014000000318A06000000010101000101001B1800470900000D0D000096000000960000004D5166024B0000000C000A0D130400011F2A0C00960000000AF4130F960000000000000040130200000000000704000000000000FA09000040030000152D170F4400170006060002180000000708080018000000310C07000000010101000101001B1800180A00000F0F0000B4000000B40000004F5178025A0000000C000A0F140500011F2A0C00B4000000CBF4130FB400000000000000785D0200000000000F04000000000000FA09000040030000162D170F4400170006060002180000000708080018000000310C07000000010101000101001C1800810B00000F0F0000B4000000B40000004F5178025A0000000C000A0F150500011F2A0C00B4000000CBF4130FB40000000000000020BF0200000000001F080000000000008A0900004003000018341B114E001A000808000220000000070909001C000000318E07000000010101000101001E18005C0D000012120000D2000000D200000052518602690000000C000A12170500011F2A0C00D20000008BF5130FD200000000000000B024030000000000280B0000000000009A090000400300001A3C1F135A001E000808000220000000080A0A001F000000311008000000010101000101001F18004A0F000014140000F0000000F000000054519802780000000C000A14190600011F2A0C00F00000004CF6130FF000000000000000143E030000000000300B000000000000AA090000400300001B412315610021000808000220000000080B0B001F00000031920800000001010100010100201800C60F000016160000FF000000FF00000056519C02800000000C000A161A0600011F2A0C00FF000000CCF6130FFF00000000000000E86E030000000000400B000000000000AA090000400300001D442515660022000A0A000224000000080C0C001F00000031920800000001010100010100221800B3100000171700000E0100000E0100005751A802870000000C000A171C0600011F2A0C000E0100000CF7130F0E01000000000000000000000A000000554C01007CFE000180FE000184FE000188FE0001A0FE0001A4FE0001091C0003C91A0003091B0003FFFFFF0000280000A8498840000004B08002000000000401C0C0C0C0C0C0C0C0C00000008000000080000000FFFFFF0100280000A8498840000004B08002000000000401C0C0C0C0C0C0C0C0D00000008000000090000000FFFFFF0200280000A8498840000004B08002000000000401C0C0C0C0C0C0C0C0D00000008000000090000000FFFFFF0300280000A8498840000004B08002000000000401C0C0C0C0C0C0C0C0C0000000800000008000000000000000400000004F4C0100504C0100514C0100524C0100534C0100544C0100564C0100574C0100584C01005E4C0100604C010000FE000104FE000108FE00010CFE000110FE000114FE000118FE00011CFE000120FE000124FE000128FE00012CFE000130FE000134FE000138FE00013CFE000140FE000144FE000148FE00014CFE000150FE000154FE000158FE000178FE00018CFE000190FE000198FE00019CFE0001A8FE0001B4FE0001B8FE0001BCFE000184FF000188FF00018CFF000190FF000194FF000198FF00019CFF0001A0FF0001A4FF0001A8FF0001ACFF0001ECFF0001F0FF0001F4FF0001F8FF0001021D0003031D00038C1C0003A10400051804000555020005FFFFFF001AA720000500000000002A000000060600040000F425E50F0000000000000000000000000000000000000000060003000000030400000305000000009C000408480448040000080000000800171000000F300000220A4C56500501000F0FDE00204004001042000000000000040000000000000038383043080810696600001B2A8C480000000000C0E03886000000000300000000142F2F22222B2B000000000000000000000000000000001C038E03AA028E03E300AA02E3007100E3007100550171001C0355011C038E03CF0030FFFF0C00F30080019000088001050000000E1000403FFF3F0F2B0000002200000010000000120000000000000016000000000000001800000024400100254001002640010024480100254801002648010024400500254005002640050024480500254805002648050024400900254009002640090024480900254809002648090024400D0025400D0026400D0024480D0025480D0026480D00FFFFFF00100000006754130220314576100000001023754664573201100000001023754664573201100000006754130220314576010000001023754664573201010000006754130220314576010000006754130220314576010000001023754664573201000000000050000303000000000010050000020100000000007D00E40C0008700010270000CC55010024F4000050C3000010270000000000006B0000008000000000000000000000000000000000000000000000006C00040205030E002106400000000000FF0005070C000E0000000000000001030E002106400000000000FF0001070C000E0002020000000004030E001006440000000000FF0004070C000E0000030000000002030E001006440000000000FF0002070C000E0000010000000014000202000000000000000000001000000000002000020114001A00000000000800000004000000000000000000000000000000F4000304010B0000D0074E0C00004E0C10270000FF000500FF000001FF00000060CC050070C600001873010070C60000B0CC0000CCF100000ED40000A4000000E8DF0500203005000000000000000000020000000000F00070110100D084000000000000333381017D1A09963014C902600060004788730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55AA5700F10E00000B0064860100000000000000000058001C000000504349520210407300001800000000035700000003800000474F5020414D44205245563A20782E782E782E782E780078787878007878787800000000B3AC0000A02301002698876FBF7D624A5B78E666660E000701444AA5B25C68A698516B03176CE2731798B82923534B48C262944841CE2952D60E02E7338E6CDB555DABBB5555B6D5BB3B54982AB002802AA88CB14D32ECEDBC1C2A5AA156A33FBFBFFCE6705A6DDEF7DB77DDEF7F6EFBE2F77EEF7C3EFDEFB3DFBDFE09FBBBB592471B6E7BB32BFF5FA115FFFFD3EE4A2B41A963F859F18AC3B48F5F1A53DF9CA2A86514B395C18535F7F8368AFDFCBF385EB8987CBF78B8A8FFFA00E4FFE2EF85C628A978D5757E8C7735C54BAFFFF703E2CFA3AA3C3DE8BE750677BF3FE237AA39E8B174FA0CF9F9F5013106DA2BEFF0E0328AC962EA94C3B18C0B0E5861D5F7FD30F51474B4D4451053116DA2BEFF2C3E43CF529B1FCFDEE3CEFEFEEB15F790FCFDF27CDFEFEEEBD053DF95F9FBA1FF1EE4D5F761E7FF6F67FF8F7EB6E94F7ACFCFD9FFE3DE8B6EAF266E152CF57DEAD5F7ADE77BB857DD2EE55C3ABEE415D3F1DCEF7B4571F0BFEBDFFE35F76AFBB6FCF6F884FC3ED5FA57E3F4A299C987C971FA249BED7C0A65D745A0BE5FD1528309F8B43C3DB2B429E2D0D15BAA4CB611684BAB74C62E8EC3F234969BB5682F8B4572D457AD4582D458AD4592F85711737168AE5A8AF5A8B05A8B15A8B25ED7791737168AE5A8AF5A8B05A8B15A8B25F75BF8B9B8B4572D457AD4582D458AD47FF79BD37BB1737168AE5A8AF5A8B05A8B15A8B25EDB7D1737168AE5A8AF5A8B05A8B15A8B25F8EDEC5CDC5A2B96A2BD6A2C16A2C56A2037AD9BBA5B3774B66EE96CDDD2D9BBA5B36E3DF8A44B54AD15CB515E550AD7B3375176390DFFE54572D457AD4582D458AD4592F76B68B60A956322A2D15CB51296A2BCABC5ACEF16B397E045B37BEF45D3E2D15CB515EB5160B5162B5164BFCA585BB8BF1956DB612D46A961BEA961BEA961BEA961BEA961BEA961BE29C95F9F214BB88B1C6F11638DE22C71BC458E3788B1C6F11638D2BFD01FFF5A3791799CA7EB1C1BF58E0DFAC706FD63837EB1C1BF58E0EF16CDDE2D9BBC5B3778B66EF16CDDE2D9BD65CC5CDC5A2B96A2BD6A2C16A2C56A3CD1965D6A374B1C6DD2C71BE82C6CBE82C6CBCC630D750E8BBFD149AFF3293D7A49361E63CF5DE4A2EB8C1FD183C0AE93A9EAAA702BDC54E7AA702C35B49ADA4C0B0A1A9A6A9C12EEAE5BAB96C12E6D2CD83CBB96772CA68FF1771C28980CFFA593EF7D8ECFCAEFB6BD2E77AFFF389C0AE47E0C9ECBE3D0E9F2360D70BDD27A27FC7E26F653638729EDAE41FD5E37C9F3FB4D95A6EDD789E927C4C5EE7BBFD9A2CA29A3F98AFB3556573EE3BF1AF3396549BDDFFE7DFCB7AF39191F6B7395F4364F627551DF66E28B4741F658712472F59EEA7C3CCFF0D7D1C5D5EC0BFECCAFC5BFA7FF17ED3FC5F95F9DFFD78353DE6E5D4F79AC32B7125FD9A2C661F70C07BB927598A0CF3A3735932BE8D9FEEE0DFDF993C6E7B2485252E80ADC48F372E36F3A4E13A292E8F996FE4FDBF07A7D363F5597ADACBCE076F9CAAD77E5D4FF957CFEAB9ECEFA72D4997F1BA8477FDDE6B9385E0FEDC96B3E1C436CAF8BF6F79C1B87BD776F7B8E90E85EEF7966798EA05C52F3EF3D4EC24F57B2EAFCBBC37F57A7E94D77F57DDEA7C1D1F631BD6F737329FA66CAF32DE92A1B95EC7D8EE168BD177FAEF3D8FD1D6CFAFF2319ED5E1D51F6D839FDB87FAF377CC63F7DA1EF2D753E347CD64FCDD53A939E8CADB5F5719E64BCEFB5CFCF7A361211BD261BCBEEA2677BCEDFDF4E9F31AFF810F566713BA95E8D84D4F6797FAD95D65D76BEF95846F45E6E33A0CE76DE206DFD6A9B7FA7825597F57DD52BEE855F6E15F730AFB9757D94AFBE360556F7D5F76CAFB84AFBF4D5F7E3ABEDEABEE9D5F742AFB9F57DB857DCCABEDA2BEE4D5F652BEF8CAB99FC257DDC2BEED95F7095F7E9ABEFC757DBD57DE895F79B57D9CAFB6CAFB9857DCBABECA57DA7F9B9C8D0AC511D4774565CAEC0A30A76144D12EF2B2654F958C2B3D14BFC95F1BCEAF35CEAF8EE757C7F3ABF56B577654E859F375FEC15DE5515C29CF05894B63FB00B1A057173EB5BD1AB55DFF4FFF90CFFFCFFFFDD3FF1D4CC01B4D0B3CA1598013DA159B0E2BC707BCC80C34A1F73E55487968183A82A90AD2053A856F748562C3A5F161C978E0F3324A3D613C8D3A00C0D3936BC693ECC93E8E1F1E54E060F181E71E5365392F4717A5DA15920E7BA02B3414680A3C37DA80F346568399D1FF961E74AA62BB90DAC42DBFC5F60E7324F78926F3A00DE7FAD11FDF88CE3C1FDC85C9855106A3481DF62008FE9DA6EE69EA29BB9A4A9A3D034348F70A9F9D68F499FA5A4D034779FD1E850CFE868E2DBB9D1E81A533C6993A4A552CB3347534751A40CE4C4D4CF4DF857C6CDF4D7F8F9EA3D052135B9DCCCEB47351514D50AE9F414744854521FDDB4EC2929A973E7D25368E2EFF4400C85876D4B46D3B0A3A8A956E67EA298FA6A2A6A58BA266B279A9FE6EA0EA767BF0AE676D4D507D180F34B51479FD0776D2A4FCF92BE5E98F5A9914BF49DCD1B4A640F8A33E5E99A7739FA7A7A4D1E856AE02D53D368EA541DCCA2A2A3A9A9686D1E8E909A08E9F93A6434717B4483834A2D1071F2B7F7FC064EC7A6A540371C9A14B4BCDAF3B4D5150853800B9840F1E370DCE990A80DAA2E5FB10E2CA3683C0B474421D9B47A4A4A2A3BF1C4407CC88D2AE3F2483C794750D3354D4CD283B9CFABB60DBE7F40D15BBA0A4EF28CAEBF4752853D3D32DC1F17BFE7F3F519FEE68CFA38BD5EEE98331CCE5FEC73F51A30E2469407E7C3AA2FC9062DBFFB6FF16FD413F279FA4A542A28F996E6D1D2D1F36E22DBF5FA3EE3474DA5D1B4CA52F774FA2123F409D1054CE331B358EC7F57D6369B33253A6B9C9E43461CB21DC350194FD03045C95F42852683F42867F32DAABA9C4CCE396F18DAA1FAB50FCBEC50DD4D1CF022D8BA3E3741D52BE31DA068D0694E0F85363CD8E4E46383E87BEFE25FC3977697C34073EBC70725EF9D37238BE444885D6C014D3BEC8E885CA040F74FA8B8C51D05961C2EDDC191C5726244748CEA6163AC258B2F7EF4963C20B1DFFD91221D0707C8E412C6E8E4997D61A244D64F8402A7B91DBFD010144F9B0B5E085A8667DC531C98639CCD5B9C96DD4C4C3963A12ACC73D871C742559697A73EDA38CE59EE370E04319976965684E4B259B391C1EA89A71AD5C0699EA88288C8E982C8E45969C7D00B48C8E70289913C1F1C45B48714FB40D66032B85E5DF1057A0504C90BD1CF66F3602646A80EF4E1707226B56801BF483A741912EF46CB3AD4E391C2FDA385470BF707A89AC3970F1C8EB019FE1FD77F98F9BE0108646FAF49B27BCA6B33E3A34176D4E8B98DA4C88BDB81D6999C8D2B5937619E97EC3B13334755DE3D2072CB6E0EF3399AE21C972CE4AECC81F5BA6FB43E54E6F7079674256099BDBB601C64EE6F13FB03167F68ED291FD2141D4DF5CCD030E83AB6BAD160DF43D0869D5EB72D37B13F12725E192EDDC1AC6A318EDD256E9D873E1C6D39B43D9BA4BE1BBFDA212EC16D97C85C247EEA6001591017F602C450075307239A6AD07A3E64064D808D696EE26B0611700585EADE0E8A3D5B0683E97696DD5E220C6B99AB0392B6893F32186392BA2F571838949D868EB6E8EE6FCD1EC22EB3D7270722350D4A47C60E6BABEED8F1E486EBC31B32EB8C9785D7FA8514F26D7175B56292AABC8339F9D7599434A179D91CE92F74C2EB8D8F00A734CD8CF37F74F2DE399BEDBA83D985B667A83986F1EF78C18D44A3C366FB662E0BD75EC2185DE59BC6265648D6F20CD06464E7D67D01957CA16F910E89C85CB38C2EBB34D5C175CEDAE493EDA6D4E3D261F14ED265F783F713C1D63D50688E25EFF13930CC95189E355C7C9ADD4C3CFE1C161CC5EA5D0F36B9980E53D080DAED2DD93959A13A130BED7BC3CBBF0BB2CDF8DDA385F4BDE1CAD9BB83E5357A4EC8CE3474977130E92F90CCEE7BB52131A5B4391CD81303897EBC4980CEBCCEC0CEC5435775316AE2C07B30E467E11C97D2E66AF5DC170D0D469D9BB469C4B3B0D743AFDDBB83D4EE3EA1EDEDD3A4B7D17B86D0E4B92ED2E169F04742958BD68DF845D6D2B21EF6D590104EEF9EE713EA18B74DEFB4DCF86B765EF2833BB26AA1ADA8319DEE2C4EF870D24CF707A35DCDE3ECC20531F98392C2FA9BF104F624D7CD2B60311603522EB3E61C9F5BDF975BC41203AFF1C23AC190819530C66F410E4E92BE4FC007770C4B769E50192FBBDA024735E385AF1492A7D2EF09D0002B9F2D086D87278AB535FE31D30DD85AE97E974DF82874C01C46FFB0711B1438A40D44EB5600EF5E90E46A599C956357E52A046E4D7FECA64E739D93B59D9718FAD6B3A0A59625277005AA291EE4A7E9758A0A90704086D10C6DFAC8B9E4FB50E15BBC03113BE7DD090CE3DE00A93892C24A5688362736A7E3F582501F297ABF5811ED3572381E9A496D0E4A316A458E9DAA0C206DE7F52913529B7D2A1E50E8BFB722BAC20647521D4A6CDFB326387905372E3F5609D2DC175C90DA27EAF431796653B60E13AA5EC2A591895A43909AB74FBD095D98988589E8F9E3B4975D606A3EC8D145F092E18DED0BAD18DC15EC0825F56389F24419721D071A9F5B8521FC5D18404CD47C9D683F1C9BA915854C5894182395F915F366365A5C0094B6C1F895DA57A6B6F664828E93B72EBB287D6BE1CF9E701B3A7B1C210B6F4CDC35FD529D69E36B0501F5D983D37DD61398CF961CA905C8D205E9DEE3C07A6639F3433E5EB9F0EB8E98720EABB522A21BF1AA3C510A66FD91C71EED365A550980868BA7949AB94D29028A8395629FC63A56452F089ABE902D12489C2588DC18DF708350D089D37D01A8938EA1E066AE47A51D933D189D2E3C9D2FC911427CD81E484B861E2AF0BEE0B0AF184469EA2847A3811E318F1270C61B00E94F4D79ED5E396FBF3F0D5E251E9E7A849C087961D6CBEA235E1A8CFB435FE6DB407C546A9C02CCBD75B269F62B7386C83AA0ED9C53B93362C8A200C40AA3628ECDB9DD25C464A15934312DC27FCC098D42A7AB8F5B56783AB257DFD4A1D3DA4A90C874F831A90C393540E7CD2606F8D6C440BA120741CD35A70271C4CD072410B6C096CFC13721701F1E3BC4E2992136ED58A62AF5F095FAF4058BFC36F46EE4627CC45E7726F08BCEE8FE82318CA31865EBA47E2F944CF2D0C2E7B74FE46E02A1ADB1F850883C8519C950508308CD02A27E5E2C9CA6ED2BAD34D859E806CFA5C62D660B9465ADB912A2CB330DABFCD4DAB53F3ABB51C44FEDD17AE6567BC13D8E09859B6AFD96B888B4B5392CEB5AA16158CCF19DA99DA0A7EFB4B3E6B0BE7227B597227F413F2D26B813C95DBA4B8C725C576970CE9BC2E87782B4EE090BB723950A800227870E323A6E999975BB521617D484D0F4FEED3E191239EF3A4B708F963C8C9D81110BBB4F41A48B709D7864AEFC62775700335A4AACB246FC41A26A8525284BA9A40F6A29A123E5891043CA9D07C013A081BD6DE590E7A58E9B5C7CADF591D5762268F39E30DAD47143BCCE6FB73FA005FD9FC8B8E8F54A210D4A63A43FECBBA7512CDDB7E0D43F540FC28EBD1D7EC2F1C952833AA91ED67CE128BCE8B44FB4684E3AB3538DC5646D0E7DDE34016BE0392E51EE1EEBD324C119706A35A3B4B51C2179BA6ADCC83D72E2319D54725960401B2BBB811DB282BC0F4AF057816EAA881F627ECDD957FEDEE46F47D1E2A53F6EE078E89DF5E77149DF495E730996D196DC99953607F7FB063F9BB00303D077628DECB66CEADB73E38315DA062A24F80D2CA809B0EDC6A3EC4D1A9A6E74197101DB3DFEE4560CD5FCC0D4101133B9BF5264799AB2B80084B503CE537A8AC258FA24EE780418D265C50D6CD47D4AC202060346998660147950C5B3757056BBB1BBD54C92AF8040EA0E7A601B37EAE1907BCF4316E7295ACC3B0E8968A7013B47D79953D0E3CC82E4D022C703A0C4B635FF4C744B174DF6BA5FA434F982313DB93E5047FDD907F0CACC11A8DF2C4978C81F61ADBD7124A2F5394126E9DEE8C9CDA975BB7230D3DC499759B151B83E88813C7CF035691447F778B1447768F712E18D38FE94313F66E87211EEE093A569B8BCCEBB005B4CC431871ADBB8D31ECC515FD01153CCAC3743AF4EC98660E83DC0353F239353BEF3DC5547F1E9068B68C5EAF50A1024C08BC3DBDDF6E9517BB806787141EA60D47B92A1F6A0271FD908947D010229A2EBA74F9B2193902EC9FE017585DFFDC2E951CC5693308103AA1057AB8BEB43AAECC4E41C4E571391B515F7C2D0F6744D3A95AE6C4D6284888F21A828D41812EE8A5CE1695D19F93FC1A899ABD7497267A0EB47A6DCC07B244239E538F6D71B03E53672D349D39A978043E2D710FFDD41CB9E5D72E32B6C4F6065F6D1540D9CFB8AB904DD25C13607CE1942F52D45D1B0023441DBCE02C2B3EC12019BA9932EB6908417400E75EE9C3FA9A74F2D6E2CC7CD0B324180984317AF097BEAB17A5DA8A3F017E75E510ABAE0E896EE1FE34E8964737DD0137A33A043541305D7658F0735D39FC58EB552D118CADB043041CD5C0DC29D644378A2981EF7B6DC2BDEEABD3523984C9DEDA21F42E941E3DE829F29ABD388A1ED3B3B49DA75C015F757FD1E7CA386D53DD1F1E3D2BD3B05143C0024D938A9030978DC36DECC40083A51EE8F7BF98A0B6D22BF06AA950EADB0EEE426AF62EC30E301AB3381C0A6FC12F57EC109C184F259821805A81843323578A3DDD7DB713BA9D97177FFF9898C0A5F4032D3E9C34D5E4D36A439ECFD38F3B9FA510F079C1428943F410169BA938FC68697EC6DC427C1CD7F32146004CB047F9840030E990E6150286B7D1077B05CD39F1AE207CE8D70DC197DB554ABCD9C50FDB509FDE2BD1AE22035EFDCB8BD491EAC9BAE1412975BD9079489A9985EBBE12103C4DBA3AA14691D45BD3A0CAF883C089B5058C3C7D66BC5FA6475439AB42979C92945C2E60AD27963F22F788E6D7B881C135B7EC22B5E8E7A0F6A7B96D45F79E703C40C150FF20AA2F0C4A77C72F5DBD44DF0589939F09F828A8E883839202214FAEF6C4C0E83E156D93302BDF5981CA3AFC0E52A3CB06AEA6157D67449E86D0741CC0254B402857225F1DA40FC4329BDB0F683B17F2A47DBFE44289E093D11332A74103F53A600788BBEFF620CE3DB89066A9B28157ABFCA2907866F4F1C6A3FB09C9F02F0504D422821AA71036A282EA7FC18B9BF5459ED64D45C224CBC5B7241DE7704C993928D0D77A9FE5CC4590368410145BF274D81219ECEB6467665FCEE993851F155C81B6B61649D45767357BF5EFC922B52F7C129EFABC5BE9290709EB8999E4813C5562C1B3D7CA3811E128E04658F4FBCC51455658203B7A7998FE6BD68756C413F67DAC51DE26C913370C0E94104E35E74399A74609876FC420846222812F6ED945CEAC5DF1C25DB693BDD150D8DA4EE9977E0BAB3607903DC0E71B726A56EEE0EA08937ACE01E625BCABFE220256DC9ED00AE4EA80F16312DDF708B07DE254C4AC6C5366D4B3271C54C362E5B9D547E04CBEB2755760246AE6737B516B356166E92B01806EE66AE5CC0DB1ADBC12157E39DC1ABB621875738C756D91F1CE916665A38C62E87809E464DCBF9FC6197D62AE906CE22427EDEFD43A3B8A08B01D87B2C143CCB6D6A24F1C3392CAB39E0299042BFD2EE0E49A0708D57C9122092A290249D8A410509E0C41115F9855166BE75A11548802F7B260436FC89FC472F430D89C8E4E846D1DC1FD2A33363099A6AE41999267FE217E542F879D21140E173983DD81D75B5A6A459D75C625EF45C4FB218935B7EF901394C04D585DF9EAE64E471FD429BE97595A47E0756D7D3536916B46DA26B1E9190AF2896A30413584832B3B8635FEC54A6C2764AD353F0851606A3FBF9240EB53C6212E80768E927C0433A6AC1E2358D7C10B57F58D7C20F5067E301D83F59AFEA143AF4F402F86F944D38D47B5D12722117D2BE385995B84E8C27CB27A6C4866753B61820C2C6B22487D585F238408F29BEA7C20F47F76009B3878E0E7337E515095B3C7DCACCA1CFBC3018579274C2D5D30F78BAE66F1BC71F7810C5BA73E583CCC1F38EA098BDE24CC70C859CF25B99E0C76242280F7E1D713C96D473112C071487D61AD5205A8C45AED01D5574FACE4E7A6F1486A947A0EFBAEFC9E83DA84003475326476836A29C9DD279160B72CEE93CD11E78DA9FDB9B37FBE10BDB99F2F5FE90D0E8AA648E83FA468FB1189E5C0E2EBC6698A7E575C286CDC990823450748DC17AEDE043F53732C4F98366FD6F149A160CBAEAC251BEB178622176F7951951BF033278E513724C4DACD9C991ADF72A17CEECD4766480D076107ABF7E7722EBA0B77DC3393A5FB860D204185DD042404EC82A876D8A3B4197B9843A8F71661301C8C4FDCD9909005A9DB63A26EE2B575F7A8C254D5C83D58F48FABA8C2999AD5C9FDD891AFD84982C4C5CCBFDD7A46099394C028CD6E27FD514375D2138BD466D3D78C1E0361AF5C4C26E93C03353932983930900A5E2A359FDA40D4C78C03181E2C713D7EB9227AFD3224F5A9900F503C58D1F3FA59C68ED5B39727AFD72C1E9F845DB35FE69ACC1AFC1BB64FB9EC8901EACCBAEF7BF84627EF015B27F4B92480FF1ACC91D7A7FE20E290838C28FFB317FF4D47F5C9914E4457725234D6641842FFC4B32661E0D816EF7204268C8F5CA68BCFFC42A685323837366AC8210CB06237C120D31A3864B2E0860F0DAF982435D963D4E1AE946D5DCDFAC4B543009F9A30AFC13A4116AC638C9317D7B650E68BAE3B46730B67496D4D6DD31F1A744B035B750CD0E406D6B97013FBB01FA1C817B303B95C310BE25819009B25E01E61A8F4C280B145409EC7F9287B1E4A87B169A914332EB4AC25FAE21F3F903BD64B3007A2A5AC4B63AC7852A082951A82C982C7197B3620FB0D0FDA0414B480E056F4F82D1D47FFC2430849F3748E719BA07075D2352ABBA757782BC3B4505F6066C457820EF1C165B6F8E244B435AE1D8078C42E15EA4C181C9354008E81AB4788923F332F694C2E3580E01B4228196D0AD926037E1265997A0A5FCE92FCE84113586FF324BF9F0BFF0D4BFA06237F9B0A3DB0EDF44C83C540D1A98C845331E2734182482C900C739834AD79638ED11AFE95ACD0828D86FE9C2FE8FE3130BE38DED501DAFAA744162E1976A3B2D635174B9887B7C3CB2E917D3EA5ECF85ECD5BBC0E682264917D4F1098E183FAC42567BD0C1E40306E1FA89721F7E113133BAC0FBE605F753F19257CEB42962C94BD5A1884B1B00B1980B132D275FC8078F1E443C7A7241E216082FAE0285B4A98FFB8BA0E95E127392A3AEFEF235275DC9782A57E788C9F7EB1E5804393C47BDFB93D8CB129A2C13DD6045B5EDA9F186C03A421B03606E5C0238D2DA3C6F6A7E0EFAC411740450C5E246B1681A6209C3C99A166E810D2C2DE01BB8C3BF9DFB43D621FCE84A5437700E096581C339378DF7C7F3F3CC2C32A91BB4983B1562F119474C372F12950500EF90E3BC47A62F5D96FB4BD74EF2CD7FDC6B1F70CB896D693BE0B0B1E1B306164087A8BF547DB6B585583346B9EA396F0C4129CB13F08B01F02B18F9846A5F6A87CB0F0809891DDCE6009D7F0FDD159427DFFA841801BD6B64FA5C10263F523C22AB766F12270C56FCE4977FE53568BB9B23A2A66464767320DBF3A061AAF3182FD01E644DD84B4A4AF9CA2129E77E7F6AF12ECD7C2FBA20B789F6B318D3BC186C1E30BA3A0D4310571707493867B8C4929DBA408FCE310A9F5E921F49F3A080E3CD4686423F94188F8EA2509A2845EF0CE8E674BB8474E56B577F57C41A5FB5CD8DB087F1FE1300C426702C590C26D12DFC78253FAC1986F8E04134D7CC06398E5CF0313D5A7D2E585633C00E7ACEB5C60A5B26A0F5F18389991BFC6862665826BF2C44BF675AE39E1ADC1A3DD24704A7B6B32084887200ACDB3B1E160814AFC605FEF62D3A918AB2EC081BA639BFC47B53606AB8241E2DB5EBC8C606D8E24BEF06671A3C5E3357F332FCC17026D7679494D728EAFE6E256DCA0C8177D0E65ECE77E84A3DEF17443F8C34A3094B08F6717929303E34BAEC92F3985C43E18B36204F62D40926FD8373FE6C56E7C260191B53085B009A36559B25216C3EF3C8DD98F2DE72FE5778C06B6849A9E32BA20B800B79535C01961019A75B25146FEF8C91855472DC2052718BD58C3164B280D2078048D4D075449B188AB2020209602F94516E3335B36B4CD0A1167EA4E2E8692B39E736757AC9989BF2C74119B7F667977A4D557029166F3D307B0145F370D68B343DFD5A6CC0630452430A0EDF0E554810D0B5C402358B6B8A6A5A49880C4341F006DDFB18F3A2599CDC971525930D0F84315A3D7E6C19DD11C0FAD0BAE249842B288EA65DD2340050957783A5C2BA1818E972ABF59BEEA3400DC5550948676169CD51335DAC28E7612CF7B27AA56EF9E04E09D30D1D18C4FFD8091971832BA21B7A59E833B09D41CB5C4D5C811FE6F43D757CB815050FA41E33FDA0A802E05401FC83C683E50F147F607879EF878D0A21E29FF6878EE8545151B5150F5E0783F001E10B90F1A4C8078D2E5812A89FED0F1779B0F1C5DA87887781E2F3001E3E6B90F1F3E403C7D19657BB2B6C0B7F1C45A4D628DD425D8B38ADE5033A83DB954301FC55827741C039F7A049E4C099652797BEF924CE5161C2AF37D66691658354E5884E7D42131DABCB26C59A18CDEEC7AE238BAD7C528FCB509D379566806D8A6B0EDBD9A1DC1CFB624024993701C9FFE5AF1DEBC0F6859A8C0050166C626B2840400847ED8822C254455016484162024144E5859581A2415B08D60CC5EDF63AD5D0D7E36C052B2A39599C9304AA82577E450F4DF5E4C42288DC4F00E4B78F1162D45B312ABC57B23DE2BE12E0BD2222BA11AEC613D231CEEDAC90D68C84BD8295A5C6B33230624C6E186BC7426017C0D720D49084C5829AA49ACC0260613256CE56138294A32C44321B04E623579F7339667F5008E9C099036E2DDE1B372B587E02FAC5EF2B0151F405804F78AC5E8C718DF6E8337302CC166C8F3E73EB262E9F5DAE42C80C2A63FAC0732EBB9535735FD671C20B77D39619B2A9E724061C743EADE56F7ACCF98856C13531E56CEB33F0A2DB0756133B3D362831F4D99F225D750334B6DC8DE275F9623FA69F4720A4FDA6F688592879910D56688B10539161AE76F91043BDD55FC83344DE04CE2669E748AF9BA9AB7878E795B9E667E284F1DF61839E3A01D0764A682C6A3057AE18AF1DD3B15374372CA498BF59581821BA7B9CC820630106EC497144AFA80753AA07544D0015F1E43980556F00FE881638BCF95525AF5905E58A719E9AE3D83EF93EF78959C3C00648F8FBF4C05FA5FC0C8E9C" diff --git a/resources/amfi_detect.py b/opencore_legacy_patcher/detections/amfi_detect.py similarity index 96% rename from resources/amfi_detect.py rename to opencore_legacy_patcher/detections/amfi_detect.py index d57d593fbe..127df25405 100644 --- a/resources/amfi_detect.py +++ b/opencore_legacy_patcher/detections/amfi_detect.py @@ -1,9 +1,11 @@ -# Determine AppleMobileFileIntegrity's OS configuration -# Copyright (C) 2022-2023, Mykola Grymalyuk +""" +amfi_detect.py: Determine AppleMobileFileIntegrity's OS configuration +""" import enum -from resources import utilities -from data import amfi_data + +from ..utilities import utilities +from ..datasets import amfi_data class AmfiConfigDetectLevel(enum.IntEnum): diff --git a/resources/device_probe.py b/opencore_legacy_patcher/detections/device_probe.py similarity index 99% rename from resources/device_probe.py rename to opencore_legacy_patcher/detections/device_probe.py index d045d3bd90..3ed75288ec 100644 --- a/resources/device_probe.py +++ b/opencore_legacy_patcher/detections/device_probe.py @@ -1,18 +1,24 @@ -# Hardware probing -# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk +""" +device_probe.py: Hardware probing +""" -import binascii import enum import itertools import subprocess import plistlib import hashlib + from pathlib import Path from dataclasses import dataclass, field from typing import Any, ClassVar, Optional, Type, Union -from resources import utilities, ioreg -from data import pci_data, usb_data +from ..utilities import utilities +from ..detections import ioreg + +from ..datasets import ( + pci_data, + usb_data +) def class_code_to_bytes(class_code: int) -> bytes: diff --git a/resources/ioreg.py b/opencore_legacy_patcher/detections/ioreg.py similarity index 99% rename from resources/ioreg.py rename to opencore_legacy_patcher/detections/ioreg.py index fbdc420938..a149533a71 100644 --- a/resources/ioreg.py +++ b/opencore_legacy_patcher/detections/ioreg.py @@ -1,5 +1,6 @@ -# PyObjc Handling for IOKit -# Copyright (C) 2020-2022, Dhinak G +""" +ioreg.py: PyObjc Handling for IOKit +""" from typing import NewType, Union import objc diff --git a/resources/os_probe.py b/opencore_legacy_patcher/detections/os_probe.py similarity index 98% rename from resources/os_probe.py rename to opencore_legacy_patcher/detections/os_probe.py index c2cf30b777..5cd7530375 100644 --- a/resources/os_probe.py +++ b/opencore_legacy_patcher/detections/os_probe.py @@ -1,8 +1,10 @@ -# Probe for OS data +""" +os_probe.py: OS Host information +""" import platform -import subprocess import plistlib +import subprocess class OSProbe: diff --git a/resources/build/bluetooth.py b/opencore_legacy_patcher/efi_builder/bluetooth.py similarity index 94% rename from resources/build/bluetooth.py rename to opencore_legacy_patcher/efi_builder/bluetooth.py index e0dc5a9ee2..41c92a360d 100644 --- a/resources/build/bluetooth.py +++ b/opencore_legacy_patcher/efi_builder/bluetooth.py @@ -1,12 +1,20 @@ -# Class for handling Bluetooth Patches, invocation from build.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +bluetooth.py: Class for handling Bluetooth Patches, invocation from build.py +""" import logging import binascii -from resources import constants, device_probe -from resources.build import support -from data import smbios_data, bluetooth_data +from . import support + +from .. import constants + +from ..detections import device_probe + +from ..datasets import ( + smbios_data, + bluetooth_data +) class BuildBluetooth: diff --git a/resources/build/build.py b/opencore_legacy_patcher/efi_builder/build.py similarity index 94% rename from resources/build/build.py rename to opencore_legacy_patcher/efi_builder/build.py index df8011a2a0..06772c5573 100644 --- a/resources/build/build.py +++ b/opencore_legacy_patcher/efi_builder/build.py @@ -1,19 +1,35 @@ -# Class for generating OpenCore Configurations tailored for Macs -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +build.py: Class for generating OpenCore Configurations tailored for Macs +""" import copy import pickle -import plistlib import shutil -import zipfile import logging +import zipfile +import plistlib from pathlib import Path from datetime import date -from resources import constants, utilities -from resources.build import bluetooth, firmware, graphics_audio, support, storage, smbios, security, misc -from resources.build.networking import wired, wireless +from .. import constants + +from ..utilities import utilities + +from .networking import ( + wired, + wireless +) +from . import ( + bluetooth, + firmware, + graphics_audio, + support, + storage, + smbios, + security, + misc +) def rmtree_handler(func, path, exc_info) -> None: diff --git a/resources/build/firmware.py b/opencore_legacy_patcher/efi_builder/firmware.py similarity index 98% rename from resources/build/firmware.py rename to opencore_legacy_patcher/efi_builder/firmware.py index 866ec2c102..1819979594 100644 --- a/resources/build/firmware.py +++ b/opencore_legacy_patcher/efi_builder/firmware.py @@ -1,5 +1,6 @@ -# Class for handling CPU and Firmware Patches, invocation from build.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +firmware.py: Class for handling CPU and Firmware Patches, invocation from build.py +""" import shutil import logging @@ -7,9 +8,18 @@ from pathlib import Path -from resources import constants, generate_smbios, device_probe -from resources.build import support -from data import smbios_data, cpu_data, os_data +from . import support + +from .. import constants + +from ..utilities import generate_smbios +from ..detections import device_probe + +from ..datasets import ( + smbios_data, + cpu_data, + os_data +) class BuildFirmware: diff --git a/resources/build/graphics_audio.py b/opencore_legacy_patcher/efi_builder/graphics_audio.py similarity index 99% rename from resources/build/graphics_audio.py rename to opencore_legacy_patcher/efi_builder/graphics_audio.py index 756f0deaf1..214753b162 100644 --- a/resources/build/graphics_audio.py +++ b/opencore_legacy_patcher/efi_builder/graphics_audio.py @@ -1,5 +1,6 @@ -# Class for handling Graphics and Audio Patches, invocation from build.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +graphics_audio.py: Class for handling Graphics and Audio Patches, invocation from build.py +""" import shutil import logging @@ -7,9 +8,20 @@ from pathlib import Path -from resources import constants, device_probe, utilities -from resources.build import support -from data import smbios_data, model_array, os_data, cpu_data, video_bios_data +from . import support + +from .. import constants + +from ..utilities import utilities +from ..detections import device_probe + +from ..datasets import ( + smbios_data, + model_array, + os_data, + cpu_data, + video_bios_data +) class BuildGraphicsAudio: diff --git a/resources/build/misc.py b/opencore_legacy_patcher/efi_builder/misc.py similarity index 98% rename from resources/build/misc.py rename to opencore_legacy_patcher/efi_builder/misc.py index 8c2cd29741..76b0cecdb6 100644 --- a/resources/build/misc.py +++ b/opencore_legacy_patcher/efi_builder/misc.py @@ -1,5 +1,6 @@ -# Class for handling Misc Patches, invocation from build.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +misc.py: Class for handling Misc Patches, invocation from build.py +""" import shutil import logging @@ -7,15 +8,24 @@ from pathlib import Path -from resources import constants, device_probe, generate_smbios, utilities -from resources.build import support -from data import model_array, smbios_data, cpu_data +from . import support + +from .. import constants + +from ..utilities import generate_smbios +from ..detections import device_probe + +from ..datasets import ( + model_array, + smbios_data, + cpu_data +) class BuildMiscellaneous: """ Build Library for Miscellaneous Hardware and Software Support - +xw Invoke from build.py """ diff --git a/resources/build/networking/wired.py b/opencore_legacy_patcher/efi_builder/networking/wired.py similarity index 96% rename from resources/build/networking/wired.py rename to opencore_legacy_patcher/efi_builder/networking/wired.py index 9b31fec6ee..b0360db0bd 100644 --- a/resources/build/networking/wired.py +++ b/opencore_legacy_patcher/efi_builder/networking/wired.py @@ -1,9 +1,17 @@ -# Class for handling Wired Networking Patches, invocation from build.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +wired.py: Class for handling Wired Networking Patches, invocation from build.py +""" -from resources import constants, device_probe -from resources.build import support -from data import smbios_data, cpu_data +from .. import support + +from ... import constants + +from ...detections import device_probe + +from ...datasets import ( + smbios_data, + cpu_data +) class BuildWiredNetworking: diff --git a/resources/build/networking/wireless.py b/opencore_legacy_patcher/efi_builder/networking/wireless.py similarity index 98% rename from resources/build/networking/wireless.py rename to opencore_legacy_patcher/efi_builder/networking/wireless.py index 0ef2af82ed..a912ff4285 100644 --- a/resources/build/networking/wireless.py +++ b/opencore_legacy_patcher/efi_builder/networking/wireless.py @@ -1,11 +1,17 @@ -# Class for handling Wireless Networking Patches, invocation from build.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +wireless.py: Class for handling Wireless Networking Patches, invocation from build.py +""" import logging -from resources import constants, device_probe, utilities -from resources.build import support -from data import smbios_data +from .. import support + +from ... import constants + +from ...datasets import smbios_data +from ...utilities import utilities +from ...detections import device_probe + class BuildWirelessNetworking: diff --git a/resources/build/security.py b/opencore_legacy_patcher/efi_builder/security.py similarity index 95% rename from resources/build/security.py rename to opencore_legacy_patcher/efi_builder/security.py index 6783c1e822..f50f1c047b 100644 --- a/resources/build/security.py +++ b/opencore_legacy_patcher/efi_builder/security.py @@ -1,11 +1,16 @@ -# Class for handling macOS Security Patches, invocation from build.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +security.py: Class for handling macOS Security Patches, invocation from build.py +""" import logging import binascii -from resources import constants, utilities, device_probe -from resources.build import support +from . import support + +from .. import constants + +from ..utilities import utilities +from ..detections import device_probe class BuildSecurity: diff --git a/resources/build/smbios.py b/opencore_legacy_patcher/efi_builder/smbios.py similarity index 98% rename from resources/build/smbios.py rename to opencore_legacy_patcher/efi_builder/smbios.py index ce527505d4..b5f49e1ec5 100644 --- a/resources/build/smbios.py +++ b/opencore_legacy_patcher/efi_builder/smbios.py @@ -1,5 +1,6 @@ -# Class for handling SMBIOS Patches, invocation from build.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +smbios.py: Class for handling SMBIOS Patches, invocation from build.py +""" import ast import uuid @@ -10,9 +11,19 @@ from pathlib import Path -from resources import constants, utilities, generate_smbios -from resources.build import support -from data import smbios_data, cpu_data, model_array +from . import support + +from .. import constants + +from ..utilities import ( + utilities, + generate_smbios +) +from ..datasets import ( + smbios_data, + cpu_data, + model_array +) class BuildSMBIOS: diff --git a/resources/build/storage.py b/opencore_legacy_patcher/efi_builder/storage.py similarity index 97% rename from resources/build/storage.py rename to opencore_legacy_patcher/efi_builder/storage.py index 62d61f5a10..77a4d66072 100644 --- a/resources/build/storage.py +++ b/opencore_legacy_patcher/efi_builder/storage.py @@ -1,11 +1,21 @@ -# Class for handling Storage Controller Patches, invocation from build.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +storage.py: Class for handling Storage Controller Patches, invocation from build.py +""" import logging -from resources import constants, device_probe, utilities -from resources.build import support -from data import model_array, smbios_data, cpu_data +from . import support + +from .. import constants + +from ..utilities import utilities +from ..detections import device_probe + +from ..datasets import ( + model_array, + smbios_data, + cpu_data +) class BuildStorage: diff --git a/resources/build/support.py b/opencore_legacy_patcher/efi_builder/support.py similarity index 98% rename from resources/build/support.py rename to opencore_legacy_patcher/efi_builder/support.py index 8b24490880..732ee76362 100644 --- a/resources/build/support.py +++ b/opencore_legacy_patcher/efi_builder/support.py @@ -1,5 +1,6 @@ -# Utility class for build functions -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +support.py: Utility class for build functions +""" import shutil import typing @@ -10,7 +11,7 @@ from pathlib import Path -from resources import constants, utilities +from .. import constants class BuildSupport: diff --git a/resources/sys_patch/sys_patch.py b/opencore_legacy_patcher/sys_patch/sys_patch.py similarity index 95% rename from resources/sys_patch/sys_patch.py rename to opencore_legacy_patcher/sys_patch/sys_patch.py index d91e867992..cd1d6d9360 100644 --- a/resources/sys_patch/sys_patch.py +++ b/opencore_legacy_patcher/sys_patch/sys_patch.py @@ -1,36 +1,39 @@ -# Framework for mounting and patching macOS root volume -# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk - -# System based off of Apple's Kernel Debug Kit (KDK) -# - https://developer.apple.com/download/all/ - -# The system relies on mounting the APFS volume as a live read/write volume -# We perform our required edits, then create a new snapshot for the system boot - -# The manual process is as follows: -# 1. Find the Root Volume -# 'diskutil info / | grep "Device Node:"' -# 2. Convert Snapshot Device Node to Root Volume Device Node -# /dev/disk3s1s1 -> /dev/disk3s1 (strip last 's1') -# 3. Mount the APFS volume as a read/write volume -# 'sudo mount -o nobrowse -t apfs /dev/disk5s5 /System/Volumes/Update/mnt1' -# 4. Perform edits to the system (ie. create new KernelCollection) -# 'sudo kmutil install --volume-root /System/Volumes/Update/mnt1/ --update-all' -# 5. Create a new snapshot for the system boot -# 'sudo bless --folder /System/Volumes/Update/mnt1/System/Library/CoreServices --bootefi --create-snapshot' - -# Additionally Apple's APFS snapshot system supports system rollbacks: -# 'sudo bless --mount /System/Volumes/Update/mnt1 --bootefi --last-sealed-snapshot' -# Note: root volume rollbacks are unstable in Big Sur due to quickly discarding the original snapshot -# - Generally within 2~ boots, the original snapshot is discarded -# - Monterey always preserves the original snapshot allowing for reliable rollbacks - -# Alternative to mounting via 'mount', Apple's update system uses 'mount_apfs' directly -# '/sbin/mount_apfs -R /dev/disk5s5 /System/Volumes/Update/mnt1' - -# With macOS Ventura, you will also need to install the KDK onto root if you plan to use kmutil -# This is because Apple removed on-disk binaries (ref: https://github.com/dortania/OpenCore-Legacy-Patcher/issues/998) -# 'sudo ditto /Library/Developer/KDKs//System /System/Volumes/Update/mnt1/System' +""" +sys_patch.py: Framework for mounting and patching macOS root volume +""" + +""" +System based off of Apple's Kernel Debug Kit (KDK) +- https://developer.apple.com/download/all/ + +The system relies on mounting the APFS volume as a live read/write volume +We perform our required edits, then create a new snapshot for the system boot + +The manual process is as follows: + 1. Find the Root Volume + 'diskutil info / | grep "Device Node:"' + 2. Convert Snapshot Device Node to Root Volume Device Node + /dev/disk3s1s1 -> /dev/disk3s1 (strip last 's1') + 3. Mount the APFS volume as a read/write volume + 'sudo mount -o nobrowse -t apfs /dev/disk5s5 /System/Volumes/Update/mnt1' + 4. Perform edits to the system (ie. create new KernelCollection) + 'sudo kmutil install --volume-root /System/Volumes/Update/mnt1/ --update-all' + 5. Create a new snapshot for the system boot + 'sudo bless --folder /System/Volumes/Update/mnt1/System/Library/CoreServices --bootefi --create-snapshot' + +Additionally Apple's APFS snapshot system supports system rollbacks: + 'sudo bless --mount /System/Volumes/Update/mnt1 --bootefi --last-sealed-snapshot' +Note: root volume rollbacks are unstable in Big Sur due to quickly discarding the original snapshot +- Generally within 2~ boots, the original snapshot is discarded +- Monterey always preserves the original snapshot allowing for reliable rollbacks + +Alternative to mounting via 'mount', Apple's update system uses 'mount_apfs' directly + '/sbin/mount_apfs -R /dev/disk5s5 /System/Volumes/Update/mnt1' + +With macOS Ventura, you will also need to install the KDK onto root if you plan to use kmutil +This is because Apple removed on-disk binaries (ref: https://github.com/dortania/OpenCore-Legacy-Patcher/issues/998) + 'sudo ditto /Library/Developer/KDKs//System /System/Volumes/Update/mnt1/System' +""" import logging import plistlib @@ -40,10 +43,11 @@ from pathlib import Path from datetime import datetime -from resources import constants, utilities, kdk_handler -from resources.sys_patch import sys_patch_detect, sys_patch_auto, sys_patch_helpers, sys_patch_generate +from .. import constants +from ..utilities import utilities, kdk_handler +from ..sys_patch import sys_patch_detect, sys_patch_auto, sys_patch_helpers, sys_patch_generate -from data import os_data +from ..datasets import os_data class PatchSysVolume: diff --git a/resources/sys_patch/sys_patch_auto.py b/opencore_legacy_patcher/sys_patch/sys_patch_auto.py similarity index 98% rename from resources/sys_patch/sys_patch_auto.py rename to opencore_legacy_patcher/sys_patch/sys_patch_auto.py index a4367696c1..ece222a26a 100644 --- a/resources/sys_patch/sys_patch_auto.py +++ b/opencore_legacy_patcher/sys_patch/sys_patch_auto.py @@ -1,23 +1,35 @@ -# Copyright (C) 2022, Mykola Grymalyuk -# Copyright (c) 2023 Jazzzny +""" +sys_patch_auto.py: Library of functions for launch services, including automatic patching +""" import wx import wx.html2 -import requests -import markdown2 + +import hashlib import logging import plistlib +import requests +import markdown2 import subprocess import webbrowser -import hashlib from pathlib import Path - -from resources import utilities, updates, global_settings, network_handler, constants -from resources.sys_patch import sys_patch_detect -from resources.wx_gui import gui_entry, gui_support -from data import css_data +from .. import constants + +from ..datasets import css_data +from ..sys_patch import sys_patch_detect + +from ..wx_gui import ( + gui_entry, + gui_support +) +from ..utilities import ( + utilities, + updates, + global_settings, + network_handler +) class AutomaticSysPatch: diff --git a/resources/sys_patch/sys_patch_detect.py b/opencore_legacy_patcher/sys_patch/sys_patch_detect.py similarity index 98% rename from resources/sys_patch/sys_patch_detect.py rename to opencore_legacy_patcher/sys_patch/sys_patch_detect.py index 5e05d03df0..3557a9506a 100644 --- a/resources/sys_patch/sys_patch_detect.py +++ b/opencore_legacy_patcher/sys_patch/sys_patch_detect.py @@ -1,18 +1,32 @@ -# Hardware Detection Logic for Root Patching -# Returns a dictionary of patches with boolean values -# Used when supplying data to sys_patch.py -# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk +""" +sys_patch_detect.py: Hardware Detection Logic for Root Patching +""" import logging import plistlib -from pathlib import Path - -import packaging.version import py_sip_xnu +import packaging.version + +from pathlib import Path -from data import cpu_data, model_array, os_data, sip_data, smbios_data -from resources import (amfi_detect, constants, device_probe, kdk_handler, - network_handler, utilities) +from .. import constants + +from ..detections import ( + amfi_detect, + device_probe +) +from ..utilities import ( + kdk_handler, + network_handler, + utilities +) +from ..datasets import ( + cpu_data, + model_array, + os_data, + sip_data, + smbios_data +) class DetectRootPatch: diff --git a/resources/sys_patch/sys_patch_generate.py b/opencore_legacy_patcher/sys_patch/sys_patch_generate.py similarity index 98% rename from resources/sys_patch/sys_patch_generate.py rename to opencore_legacy_patcher/sys_patch/sys_patch_generate.py index ea80107711..1a628b1e60 100644 --- a/resources/sys_patch/sys_patch_generate.py +++ b/opencore_legacy_patcher/sys_patch/sys_patch_generate.py @@ -1,8 +1,15 @@ -# Generate patch set for use in sys_patch.py +""" +sys_patch_generate.py: Class for generating patch sets for the current host +""" + import logging -from resources import constants, utilities, device_probe -from data import sys_patch_dict +from .. import constants + +from ..datasets import sys_patch_dict +from ..utilities import utilities +from ..detections import device_probe + class GenerateRootPatchSets: """ diff --git a/resources/sys_patch/sys_patch_helpers.py b/opencore_legacy_patcher/sys_patch/sys_patch_helpers.py similarity index 98% rename from resources/sys_patch/sys_patch_helpers.py rename to opencore_legacy_patcher/sys_patch/sys_patch_helpers.py index eeccbe9127..7fe8c85ab2 100644 --- a/resources/sys_patch/sys_patch_helpers.py +++ b/opencore_legacy_patcher/sys_patch/sys_patch_helpers.py @@ -1,17 +1,25 @@ -# Additional support functions for sys_patch.py -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +sys_patch_helpers.py: Additional support functions for sys_patch.py +""" -import plistlib import os import logging +import plistlib import subprocess from typing import Union from pathlib import Path from datetime import datetime -from data import os_data -from resources import bplist, constants, generate_smbios, utilities +from .. import constants + +from ..datasets import os_data + +from ..utilities import ( + bplist, + generate_smbios, + utilities +) class SysPatchHelpers: diff --git a/resources/analytics_handler.py b/opencore_legacy_patcher/utilities/analytics_handler.py similarity index 96% rename from resources/analytics_handler.py rename to opencore_legacy_patcher/utilities/analytics_handler.py index fbdac3e2fd..1d07b0da66 100644 --- a/resources/analytics_handler.py +++ b/opencore_legacy_patcher/utilities/analytics_handler.py @@ -1,9 +1,19 @@ +""" +analytics_handler.py: Analytics and Crash Reporting Handler +""" + +import json import datetime import plistlib + from pathlib import Path -import json -from resources import network_handler, constants, global_settings +from .. import constants + +from ..utilities import ( + network_handler, + global_settings +) DATE_FORMAT: str = "%Y-%m-%d %H-%M-%S" diff --git a/resources/arguments.py b/opencore_legacy_patcher/utilities/arguments.py similarity index 96% rename from resources/arguments.py rename to opencore_legacy_patcher/utilities/arguments.py index e22888296e..55e962f8a2 100644 --- a/resources/arguments.py +++ b/opencore_legacy_patcher/utilities/arguments.py @@ -1,3 +1,7 @@ +""" +arguments.py: CLI argument handling +""" + import sys import time import logging @@ -7,11 +11,25 @@ from pathlib import Path -from data import model_array, os_data -from resources.build import build -from resources.sys_patch import sys_patch, sys_patch_auto -from resources import defaults, utilities, validation, constants -from resources.wx_gui import gui_entry +from .. import constants + +from ..wx_gui import gui_entry +from ..efi_builder import build + +from ..datasets import ( + model_array, + os_data +) +from ..sys_patch import ( + sys_patch, + sys_patch_auto +) +from ..utilities import ( + utilities, + defaults, + validation +) + # Generic building args diff --git a/resources/bplist.py b/opencore_legacy_patcher/utilities/bplist.py similarity index 100% rename from resources/bplist.py rename to opencore_legacy_patcher/utilities/bplist.py diff --git a/resources/commit_info.py b/opencore_legacy_patcher/utilities/commit_info.py similarity index 95% rename from resources/commit_info.py rename to opencore_legacy_patcher/utilities/commit_info.py index af64465fe9..0f7b218920 100644 --- a/resources/commit_info.py +++ b/opencore_legacy_patcher/utilities/commit_info.py @@ -1,8 +1,12 @@ -# Parse Commit Info from binary's info.plist +""" +commit_info.py: Parse Commit Info from binary's info.plist +""" -from pathlib import Path import plistlib +from pathlib import Path + + class ParseCommitInfo: def __init__(self, binary_path: str) -> None: diff --git a/resources/defaults.py b/opencore_legacy_patcher/utilities/defaults.py similarity index 96% rename from resources/defaults.py rename to opencore_legacy_patcher/utilities/defaults.py index abbcbaf55d..0b8387a9cc 100644 --- a/resources/defaults.py +++ b/opencore_legacy_patcher/utilities/defaults.py @@ -1,14 +1,19 @@ -# Generate Default Data +""" +defaults.py: Generate default data for host/target +""" + import subprocess -from resources import ( +from .. import constants + +from ..detections import device_probe + +from ..utilities import ( utilities, - device_probe, generate_smbios, - global_settings, - constants + global_settings ) -from data import ( +from ..datasets import ( smbios_data, cpu_data, os_data @@ -25,16 +30,16 @@ def __init__(self, model: str, host_is_target: bool, global_constants: constants self.host_is_target: bool = host_is_target # Reset Variables - self.constants.sip_status: bool = True - self.constants.secure_status: bool = False - self.constants.disable_cs_lv: bool = False - self.constants.disable_amfi: bool = False - self.constants.fu_status: bool = True + self.constants.sip_status = True + self.constants.secure_status = False + self.constants.disable_cs_lv = False + self.constants.disable_amfi = False + self.constants.fu_status = True - self.constants.fu_arguments: str = None + self.constants.fu_arguments = None - self.constants.custom_serial_number: str = "" - self.constants.custom_board_serial_number: str = "" + self.constants.custom_serial_number = "" + self.constants.custom_board_serial_number = "" if self.host_is_target is True: for gpu in self.constants.computer.gpus: diff --git a/resources/generate_smbios.py b/opencore_legacy_patcher/utilities/generate_smbios.py similarity index 97% rename from resources/generate_smbios.py rename to opencore_legacy_patcher/utilities/generate_smbios.py index ad541b9cf5..9926415443 100644 --- a/resources/generate_smbios.py +++ b/opencore_legacy_patcher/utilities/generate_smbios.py @@ -1,8 +1,18 @@ -from data import smbios_data, os_data, cpu_data -from resources import utilities +""" +generate_smbios.py: SMBIOS generation for OpenCore Legacy Patcher +""" import logging +from ..utilities import utilities + +from ..datasets import ( + smbios_data, + os_data, + cpu_data +) + + def set_smbios_model_spoof(model): try: smbios_data.smbios_dictionary[model]["Screen Size"] diff --git a/resources/global_settings.py b/opencore_legacy_patcher/utilities/global_settings.py similarity index 94% rename from resources/global_settings.py rename to opencore_legacy_patcher/utilities/global_settings.py index 7ce87d7d17..d69c2c4881 100644 --- a/resources/global_settings.py +++ b/opencore_legacy_patcher/utilities/global_settings.py @@ -1,14 +1,19 @@ -# Alternative to Apple's 'defaults' tool -# Store data in '/Users/Shared' -# This is to ensure compatibility when running without a user -# ie. during automated patching +""" +global_settings.py: Library for querying and writing global enviroment settings + +Alternative to Apple's 'defaults' tool +Store data in '/Users/Shared' +This is to ensure compatibility when running without a user +ie. during automated patching +""" -from pathlib import Path -import plistlib -import logging import os +import logging +import plistlib import subprocess +from pathlib import Path + class GlobalEnviromentSettings: """ diff --git a/resources/install.py b/opencore_legacy_patcher/utilities/install.py similarity index 98% rename from resources/install.py rename to opencore_legacy_patcher/utilities/install.py index 68daa76408..f27455d980 100644 --- a/resources/install.py +++ b/opencore_legacy_patcher/utilities/install.py @@ -1,6 +1,6 @@ -# Installation of OpenCore files to ESP -# Usage solely for TUI -# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk +""" +install.py: Installation of OpenCore files to ESP +""" import logging import plistlib @@ -9,8 +9,10 @@ from pathlib import Path -from resources import utilities, constants -from data import os_data +from .. import constants + +from ..datasets import os_data +from ..utilities import utilities class tui_disk_installation: diff --git a/resources/integrity_verification.py b/opencore_legacy_patcher/utilities/integrity_verification.py similarity index 94% rename from resources/integrity_verification.py rename to opencore_legacy_patcher/utilities/integrity_verification.py index b249d02d0c..69db79ca9f 100644 --- a/resources/integrity_verification.py +++ b/opencore_legacy_patcher/utilities/integrity_verification.py @@ -1,7 +1,9 @@ -# Validate the integrity of Apple downloaded files via .chunklist and .integrityDataV1 files -# Based off of chunklist.py: -# - https://gist.github.com/dhinakg/cbe30edf31ddc153fd0b0c0570c9b041 -# Copyright (C) 2021-2023, Dhinak G, Mykola Grymalyuk +""" +integrity_verification.py: Validate the integrity of Apple downloaded files via .chunklist and .integrityDataV1 files + +Based off of chunklist.py: +- https://gist.github.com/dhinakg/cbe30edf31ddc153fd0b0c0570c9b041 +""" import enum import hashlib diff --git a/resources/kdk_handler.py b/opencore_legacy_patcher/utilities/kdk_handler.py similarity index 98% rename from resources/kdk_handler.py rename to opencore_legacy_patcher/utilities/kdk_handler.py index 0306a5e475..380fca5b9d 100644 --- a/resources/kdk_handler.py +++ b/opencore_legacy_patcher/utilities/kdk_handler.py @@ -1,22 +1,26 @@ -# Module for parsing and determining best Kernel Debug Kit for host OS -# Copyright (C) 2022-2023, Dhinak G, Mykola Grymalyuk +""" +kdk_handler.py: Module for parsing and determining best Kernel Debug Kit for host OS +""" -import datetime -from pathlib import Path -from typing import cast -import tempfile +import os +import logging import plistlib - -import packaging.version import requests - +import tempfile import subprocess -import os +import packaging.version -import logging +from typing import cast +from pathlib import Path + +from .. import constants + +from ..datasets import os_data -from resources import utilities, network_handler, constants -from data import os_data +from ..utilities import ( + utilities, + network_handler +) KDK_INSTALL_PATH: str = "/Library/Developer/KDKs" KDK_INFO_PLIST: str = "KDKInfo.plist" @@ -89,7 +93,7 @@ def __init__(self, global_constants: constants.Constants, self._get_latest_kdk() - def _get_remote_kdks(self) -> list or None: + def _get_remote_kdks(self) -> list: """ Fetches a list of available KDKs from the KdkSupportPkg API Additionally caches the list for future use, avoiding extra API calls @@ -247,7 +251,7 @@ def _get_latest_kdk(self, host_build: str = None, host_version: str = None) -> N self.success = True - def retrieve_download(self, override_path: str = "") -> network_handler.DownloadObject or None: + def retrieve_download(self, override_path: str = "") -> network_handler.DownloadObject: """ Returns a DownloadObject for the KDK @@ -381,7 +385,7 @@ def _local_kdk_valid_legacy(self, kdk_path: Path) -> bool: return True - def _local_kdk_installed(self, match: str = None, check_version: bool = False) -> str or None: + def _local_kdk_installed(self, match: str = None, check_version: bool = False) -> str: """ Checks if KDK matching build is installed If so, validates it has not been corrupted diff --git a/resources/logging_handler.py b/opencore_legacy_patcher/utilities/logging_handler.py similarity index 98% rename from resources/logging_handler.py rename to opencore_legacy_patcher/utilities/logging_handler.py index e368fb79d8..464a87bbda 100644 --- a/resources/logging_handler.py +++ b/opencore_legacy_patcher/utilities/logging_handler.py @@ -1,3 +1,7 @@ +""" +logging_handler.py: Initialize logging framework for program +""" + import os import sys import pprint @@ -10,7 +14,12 @@ from pathlib import Path from datetime import datetime -from resources import constants, analytics_handler, global_settings +from .. import constants + +from ..utilities import ( + analytics_handler, + global_settings +) class InitializeLoggingSupport: diff --git a/resources/macos_installer_handler.py b/opencore_legacy_patcher/utilities/macos_installer_handler.py similarity index 99% rename from resources/macos_installer_handler.py rename to opencore_legacy_patcher/utilities/macos_installer_handler.py index 8d0984912b..b75ddc7f90 100644 --- a/resources/macos_installer_handler.py +++ b/opencore_legacy_patcher/utilities/macos_installer_handler.py @@ -1,15 +1,22 @@ -# Handler for macOS installers, both local and remote +""" +macos_installer_handler.py: Handler for macOS installers, both local and remote +""" -from pathlib import Path -import plistlib -import subprocess -import tempfile import enum import logging +import plistlib +import tempfile +import subprocess import applescript -from data import os_data -from resources import network_handler, utilities +from pathlib import Path + +from ..datasets import os_data + +from ..utilities import ( + network_handler, + utilities +) APPLICATION_SEARCH_PATH: str = "/Applications" diff --git a/resources/network_handler.py b/opencore_legacy_patcher/utilities/network_handler.py similarity index 97% rename from resources/network_handler.py rename to opencore_legacy_patcher/utilities/network_handler.py index a6029ce9d1..c9623f426a 100644 --- a/resources/network_handler.py +++ b/opencore_legacy_patcher/utilities/network_handler.py @@ -1,7 +1,9 @@ -# Library dedicated to Network Handling tasks including downloading files -# Primarily based around the DownloadObject class, which provides a simple -# object for libraries to query download progress and status -# Copyright (C) 2023, Mykola Grymalyuk +""" +network_handler.py: Library dedicated to Network Handling tasks including downloading files + +Primarily based around the DownloadObject class, which provides a simple +object for libraries to query download progress and status +""" import time import requests @@ -10,9 +12,11 @@ import enum import hashlib import atexit + +from typing import Union from pathlib import Path -from resources import utilities +from ..utilities import utilities SESSION = requests.Session() @@ -218,7 +222,7 @@ def download(self, display_progress: bool = False, spawn_thread: bool = True, ve self._download(display_progress) - def download_simple(self, verify_checksum: bool = False) -> str or bool: + def download_simple(self, verify_checksum: bool = False) -> Union[str, bool]: """ Alternative to download(), mimics utilities.py's old download_file() function diff --git a/resources/reroute_payloads.py b/opencore_legacy_patcher/utilities/reroute_payloads.py similarity index 95% rename from resources/reroute_payloads.py rename to opencore_legacy_patcher/utilities/reroute_payloads.py index e974e7e76e..2633529067 100644 --- a/resources/reroute_payloads.py +++ b/opencore_legacy_patcher/utilities/reroute_payloads.py @@ -1,15 +1,19 @@ -# Reroute binaries to tmp directory, and mount a disk image of the payloads -# Implements a shadowfile to avoid direct writes to the dmg -# Copyright (C) 2022, Mykola Grymalyuk +""" +reroute_payloads.py: Reroute binaries to tmp directory, and mount a disk image of the payloads +Implements a shadowfile to avoid direct writes to the dmg +""" +import atexit import plistlib -from pathlib import Path -import subprocess import tempfile -import atexit +import subprocess + import logging -from resources import constants +from pathlib import Path + +from .. import constants + class RoutePayloadDiskImage: diff --git a/resources/updates.py b/opencore_legacy_patcher/utilities/updates.py similarity index 94% rename from resources/updates.py rename to opencore_legacy_patcher/utilities/updates.py index 9b12df5305..3a85c83db2 100644 --- a/resources/updates.py +++ b/opencore_legacy_patcher/utilities/updates.py @@ -1,13 +1,19 @@ -# Copyright (C) 2022, Mykola Grymalyuk -# Check whether new updates are available for OpenCore Legacy Patcher binary -# Call check_binary_updates() to determine if any updates are available -# Returns dict with Link and Version of the latest binary update if available +""" +updates.py: Check for OpenCore Legacy Patcher binary updates + +Call check_binary_updates() to determine if any updates are available +Returns dict with Link and Version of the latest binary update if available +""" + import logging -from typing import Optional, Union +from typing import Optional, Union from packaging import version -from resources import constants, network_handler +from .. import constants + +from ..utilities import network_handler + REPO_LATEST_RELEASE_URL: str = "https://api.github.com/repos/dortania/OpenCore-Legacy-Patcher/releases/latest" diff --git a/resources/utilities.py b/opencore_legacy_patcher/utilities/utilities.py similarity index 98% rename from resources/utilities.py rename to opencore_legacy_patcher/utilities/utilities.py index b442448143..addf1493e8 100644 --- a/resources/utilities.py +++ b/opencore_legacy_patcher/utilities/utilities.py @@ -1,20 +1,29 @@ -# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +""" +utilities.py: Utility functions for OpenCore Legacy Patcher +""" -import argparse -import atexit -import binascii -import logging -import math import os -import plistlib import re +import math +import atexit import shutil +import logging +import argparse +import binascii +import plistlib import subprocess -from pathlib import Path import py_sip_xnu -from data import os_data, sip_data -from resources import constants, ioreg +from pathlib import Path + +from .. import constants + +from ..detections import ioreg + +from ..datasets import ( + os_data, + sip_data +) def hexswap(input_hex: str): @@ -553,7 +562,7 @@ def elevated(*args, **kwargs) -> subprocess.CompletedProcess: return subprocess.run(["/usr/bin/sudo"] + [args[0][0]] + args[0][1:], **kwargs) -def fetch_staged_update(variant: str = "Update") -> (str, str): +def fetch_staged_update(variant: str = "Update") -> tuple[str, str]: """ Check for staged macOS update Supported variants: diff --git a/resources/validation.py b/opencore_legacy_patcher/utilities/validation.py similarity index 97% rename from resources/validation.py rename to opencore_legacy_patcher/utilities/validation.py index 4385a29dd4..89c806cd0a 100644 --- a/resources/validation.py +++ b/opencore_legacy_patcher/utilities/validation.py @@ -1,11 +1,24 @@ +""" +validation.py: Validation class for the patcher +""" + import logging import subprocess + from pathlib import Path -from resources.sys_patch import sys_patch_helpers -from resources.build import build -from resources import constants, network_handler -from data import example_data, model_array, sys_patch_dict, os_data +from .. import constants + +from ..sys_patch import sys_patch_helpers +from ..utilities import network_handler +from ..efi_builder import build + +from ..datasets import ( + example_data, + model_array, + sys_patch_dict, + os_data +) class PatcherValidation: diff --git a/resources/wx_gui/gui_about.py b/opencore_legacy_patcher/wx_gui/gui_about.py similarity index 95% rename from resources/wx_gui/gui_about.py rename to opencore_legacy_patcher/wx_gui/gui_about.py index 107427f154..0b0be744e1 100644 --- a/resources/wx_gui/gui_about.py +++ b/opencore_legacy_patcher/wx_gui/gui_about.py @@ -1,12 +1,14 @@ -# About frame, just to sat +""" +gui_about.py: About frame +""" import wx import wx.adv import logging -from resources.wx_gui import gui_support +from .. import constants -from resources import constants +from ..wx_gui import gui_support class AboutFrame(wx.Frame): diff --git a/resources/wx_gui/gui_build.py b/opencore_legacy_patcher/wx_gui/gui_build.py similarity index 97% rename from resources/wx_gui/gui_build.py rename to opencore_legacy_patcher/wx_gui/gui_build.py index fd5525ce50..a6caaf3fbc 100644 --- a/resources/wx_gui/gui_build.py +++ b/opencore_legacy_patcher/wx_gui/gui_build.py @@ -1,12 +1,17 @@ -# Generate UI for Building OpenCore +""" +gui_build.py: Generate UI for Building OpenCore +""" + import wx import logging import threading import traceback -from resources import constants -from resources.build import build -from resources.wx_gui import ( +from .. import constants + +from ..efi_builder import build + +from ..wx_gui import ( gui_main_menu, gui_install_oc, gui_support diff --git a/resources/wx_gui/gui_cache_os_update.py b/opencore_legacy_patcher/wx_gui/gui_cache_os_update.py similarity index 97% rename from resources/wx_gui/gui_cache_os_update.py rename to opencore_legacy_patcher/wx_gui/gui_cache_os_update.py index 83888adc08..8ff6514925 100644 --- a/resources/wx_gui/gui_cache_os_update.py +++ b/opencore_legacy_patcher/wx_gui/gui_cache_os_update.py @@ -1,5 +1,5 @@ """ -UI to display to users before a macOS update is applied +gui_cache_os_update.py: UI to display to users before a macOS update is applied Primarily for caching updates required for incoming OS (ex. KDKs) """ @@ -11,8 +11,9 @@ from pathlib import Path -from resources import constants, kdk_handler, utilities -from resources.wx_gui import gui_support, gui_download +from .. import constants +from ..utilities import kdk_handler, utilities +from ..wx_gui import gui_support, gui_download class OSUpdateFrame(wx.Frame): diff --git a/resources/wx_gui/gui_download.py b/opencore_legacy_patcher/wx_gui/gui_download.py similarity index 96% rename from resources/wx_gui/gui_download.py rename to opencore_legacy_patcher/wx_gui/gui_download.py index fb5a456568..910117898e 100644 --- a/resources/wx_gui/gui_download.py +++ b/opencore_legacy_patcher/wx_gui/gui_download.py @@ -1,16 +1,19 @@ -# Generate UI for downloading files +""" +gui_download.py: Generate UI for downloading files +""" + import wx import logging -from resources import ( - constants, +from .. import constants + +from ..wx_gui import gui_support + +from ..utilities import ( network_handler, utilities ) -from resources.wx_gui import gui_support - - class DownloadFrame(wx.Frame): """ @@ -67,7 +70,7 @@ def _generate_elements(self, frame: wx.Dialog = None) -> None: self.download_obj.download() while self.download_obj.is_active(): - + percentage: int = round(self.download_obj.get_percent()) if percentage == 0: percentage = 1 diff --git a/resources/wx_gui/gui_entry.py b/opencore_legacy_patcher/wx_gui/gui_entry.py similarity index 94% rename from resources/wx_gui/gui_entry.py rename to opencore_legacy_patcher/wx_gui/gui_entry.py index 3c6e648dbe..d5de49bd88 100644 --- a/resources/wx_gui/gui_entry.py +++ b/opencore_legacy_patcher/wx_gui/gui_entry.py @@ -1,11 +1,17 @@ -# Entry point for the wxPython GUI +""" +gui_entry.py: Entry point for the wxPython GUI +""" + import wx import sys import atexit import logging -from resources import constants -from resources.wx_gui import ( +from .. import constants + +from ..sys_patch import sys_patch_detect + +from ..wx_gui import ( gui_cache_os_update, gui_main_menu, gui_build, @@ -13,7 +19,6 @@ gui_sys_patch_start, gui_update, ) -from resources.sys_patch import sys_patch_detect class SupportedEntryPoints: diff --git a/resources/wx_gui/gui_help.py b/opencore_legacy_patcher/wx_gui/gui_help.py similarity index 96% rename from resources/wx_gui/gui_help.py rename to opencore_legacy_patcher/wx_gui/gui_help.py index 5907ebfb7d..177aeb38ed 100644 --- a/resources/wx_gui/gui_help.py +++ b/opencore_legacy_patcher/wx_gui/gui_help.py @@ -1,11 +1,14 @@ -# Generate UI for help menu +""" +gui_help.py: GUI Help Menu +""" + import wx import logging import webbrowser -from resources import constants +from .. import constants -from resources.wx_gui import gui_support +from ..wx_gui import gui_support class HelpFrame(wx.Frame): diff --git a/resources/wx_gui/gui_install_oc.py b/opencore_legacy_patcher/wx_gui/gui_install_oc.py similarity index 98% rename from resources/wx_gui/gui_install_oc.py rename to opencore_legacy_patcher/wx_gui/gui_install_oc.py index 58182d653a..e45aacf5b0 100644 --- a/resources/wx_gui/gui_install_oc.py +++ b/opencore_legacy_patcher/wx_gui/gui_install_oc.py @@ -1,11 +1,22 @@ +""" +gui_install_oc.py: Frame for installing OpenCore to disk +""" + import wx -import threading import logging +import threading import traceback -from resources.wx_gui import gui_main_menu, gui_support, gui_sys_patch_display -from resources import constants, install -from data import os_data +from .. import constants + +from ..datasets import os_data +from ..utilities import install + +from ..wx_gui import ( + gui_main_menu, + gui_support, + gui_sys_patch_display +) class InstallOCFrame(wx.Frame): diff --git a/resources/wx_gui/gui_macos_installer_download.py b/opencore_legacy_patcher/wx_gui/gui_macos_installer_download.py similarity index 98% rename from resources/wx_gui/gui_macos_installer_download.py rename to opencore_legacy_patcher/wx_gui/gui_macos_installer_download.py index 81e30aa450..1e159a90a1 100644 --- a/resources/wx_gui/gui_macos_installer_download.py +++ b/opencore_legacy_patcher/wx_gui/gui_macos_installer_download.py @@ -1,25 +1,34 @@ +""" +gui_macos_installer_download.py: macOS Installer Download Frame +""" + import wx +import locale import logging import threading import webbrowser -import locale from pathlib import Path -from resources.wx_gui import ( +from .. import constants + +from ..datasets import ( + os_data, + smbios_data, + cpu_data +) +from ..wx_gui import ( gui_main_menu, gui_support, gui_download, gui_macos_installer_flash ) -from resources import ( - constants, +from ..utilities import ( macos_installer_handler, utilities, network_handler, integrity_verification ) -from data import os_data, smbios_data, cpu_data class macOSInstallerDownloadFrame(wx.Frame): @@ -51,7 +60,7 @@ def _icon_to_bitmap(self, icon: str, size: tuple = (32, 32)) -> wx.Bitmap: Convert icon to bitmap """ return wx.Bitmap(wx.Bitmap(icon, wx.BITMAP_TYPE_ICON).ConvertToImage().Rescale(size[0], size[1], wx.IMAGE_QUALITY_HIGH)) - + def _macos_version_to_icon(self, version: int) -> int: """ Convert macOS version to icon @@ -143,20 +152,20 @@ def _display_available_installers(self, event: wx.Event = None, show_full: bool """ Display available installers in frame """ - + bundles = [wx.BitmapBundle.FromBitmaps(icon) for icon in self.icons] - + self.frame_modal.Destroy() self.frame_modal = wx.Dialog(self, title="Select macOS Installer", size=(460, 500)) # Title: Select macOS Installer title_label = wx.StaticText(self.frame_modal, label="Select macOS Installer", pos=(-1,-1)) title_label.SetFont(gui_support.font_factory(19, wx.FONTWEIGHT_BOLD)) - + # macOS Installers list id = wx.NewIdRef() - + self.list = wx.ListCtrl(self.frame_modal, id, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_NO_HEADER | wx.BORDER_SUNKEN) self.list.SetSmallImages(bundles) @@ -226,7 +235,7 @@ def _display_available_installers(self, event: wx.Event = None, show_full: bool checkboxsizer = wx.BoxSizer(wx.HORIZONTAL) checkboxsizer.Add(self.showolderversions_checkbox, 0, wx.ALIGN_CENTRE | wx.RIGHT, 5) - + sizer = wx.BoxSizer(wx.VERTICAL) sizer.AddSpacer(10) sizer.Add(title_label, 0, wx.ALIGN_CENTRE | wx.ALL, 0) @@ -253,15 +262,15 @@ def on_copy_link(self, installers: dict) -> None: wx.MessageDialog(self.frame_modal, "Download link copied to clipboard", "", wx.OK | wx.ICON_INFORMATION).ShowModal() - + def on_select_list(self, event): if self.list.GetSelectedItemCount() > 0: self.select_button.Enable() - self.copy_button.Enable() + self.copy_button.Enable() else: self.select_button.Disable() self.copy_button.Disable() - + def on_download_installer(self, installers: dict) -> None: """ Download macOS installer @@ -322,7 +331,7 @@ def on_download_installer(self, installers: dict) -> None: self._validate_installer(list(installers.values())[selected_item]['integrity']) - + def _validate_installer(self, chunklist_link: str) -> None: """ Validate macOS installer diff --git a/resources/wx_gui/gui_macos_installer_flash.py b/opencore_legacy_patcher/wx_gui/gui_macos_installer_flash.py similarity index 99% rename from resources/wx_gui/gui_macos_installer_flash.py rename to opencore_legacy_patcher/wx_gui/gui_macos_installer_flash.py index a0c78c8643..0a347d7cae 100644 --- a/resources/wx_gui/gui_macos_installer_flash.py +++ b/opencore_legacy_patcher/wx_gui/gui_macos_installer_flash.py @@ -1,3 +1,7 @@ +""" +gui_macos_installer_flash.py: macOS Installer Flash Frame +""" + import wx import time import logging @@ -8,15 +12,21 @@ from pathlib import Path -from resources.wx_gui import gui_main_menu, gui_build, gui_support -from resources import ( - constants, +from .. import constants + +from ..datasets import os_data + +from ..wx_gui import ( + gui_main_menu, + gui_build, + gui_support +) +from ..utilities import ( macos_installer_handler, utilities, network_handler, kdk_handler, ) -from data import os_data class macOSInstallerFlashFrame(wx.Frame): diff --git a/resources/wx_gui/gui_main_menu.py b/opencore_legacy_patcher/wx_gui/gui_main_menu.py similarity index 98% rename from resources/wx_gui/gui_main_menu.py rename to opencore_legacy_patcher/wx_gui/gui_main_menu.py index c38f10c939..479f468795 100644 --- a/resources/wx_gui/gui_main_menu.py +++ b/opencore_legacy_patcher/wx_gui/gui_main_menu.py @@ -1,19 +1,31 @@ -# Generate GUI for main menu -# Portions of this file Copyright (c) 2023 Jazzzny +""" +gui_main_menu.py: Generate GUI for main menu +""" import wx import wx.html2 -import markdown2 -import requests + import sys import logging +import requests +import markdown2 import threading import webbrowser import subprocess from pathlib import Path -from resources.wx_gui import ( +from .. import constants + +from ..utilities import ( + global_settings, + updates +) +from ..datasets import ( + os_data, + css_data +) +from ..wx_gui import ( gui_build, gui_macos_installer_download, gui_support, @@ -22,12 +34,6 @@ gui_sys_patch_display, gui_update, ) -from resources import ( - constants, - global_settings, - updates -) -from data import os_data, css_data class MainFrame(wx.Frame): diff --git a/resources/wx_gui/gui_settings.py b/opencore_legacy_patcher/wx_gui/gui_settings.py similarity index 99% rename from resources/wx_gui/gui_settings.py rename to opencore_legacy_patcher/wx_gui/gui_settings.py index 1316dcff23..5b2b7ec6b5 100644 --- a/resources/wx_gui/gui_settings.py +++ b/opencore_legacy_patcher/wx_gui/gui_settings.py @@ -1,26 +1,32 @@ +""" +gui_settings.py: Settings Frame for the GUI +""" + +import os import wx import wx.adv import pprint import logging import py_sip_xnu import subprocess -import os from pathlib import Path -from resources.sys_patch.sys_patch import PatchSysVolume -from resources.wx_gui import ( +from .. import constants + +from ..sys_patch import sys_patch + +from ..wx_gui import ( gui_support, gui_update ) -from resources import ( - constants, +from ..utilities import ( global_settings, defaults, generate_smbios, network_handler ) -from data import ( +from ..datasets import ( model_array, sip_data, smbios_data, @@ -1322,7 +1328,7 @@ def on_mount_root_vol(self, event: wx.Event) -> None: wx.MessageDialog(self.parent, "Please relaunch as Root to mount the Root Volume", "Error", wx.OK | wx.ICON_ERROR).ShowModal() else: #Don't need to pass model as we're bypassing all logic - if PatchSysVolume("",self.constants)._mount_root_vol() == True: + if sys_patch.PatchSysVolume("",self.constants)._mount_root_vol() == True: wx.MessageDialog(self.parent, "Root Volume Mounted, remember to fix permissions before saving the Root Volume", "Success", wx.OK | wx.ICON_INFORMATION).ShowModal() else: wx.MessageDialog(self.parent, "Root Volume Mount Failed, check terminal output", "Error", wx.OK | wx.ICON_ERROR).ShowModal() @@ -1332,7 +1338,7 @@ def on_bless_root_vol(self, event: wx.Event) -> None: wx.MessageDialog(self.parent, "Please relaunch as Root to save changes", "Error", wx.OK | wx.ICON_ERROR).ShowModal() else: #Don't need to pass model as we're bypassing all logic - if PatchSysVolume("",self.constants)._rebuild_root_volume() == True: + if sys_patch.PatchSysVolume("",self.constants)._rebuild_root_volume() == True: wx.MessageDialog(self.parent, "Root Volume saved, please reboot to apply changes", "Success", wx.OK | wx.ICON_INFORMATION).ShowModal() else: wx.MessageDialog(self.parent, "Root Volume update Failed, check terminal output", "Error", wx.OK | wx.ICON_ERROR).ShowModal() \ No newline at end of file diff --git a/resources/wx_gui/gui_support.py b/opencore_legacy_patcher/wx_gui/gui_support.py similarity index 98% rename from resources/wx_gui/gui_support.py rename to opencore_legacy_patcher/wx_gui/gui_support.py index 70942e9150..6fc3cbf753 100644 --- a/resources/wx_gui/gui_support.py +++ b/opencore_legacy_patcher/wx_gui/gui_support.py @@ -1,21 +1,30 @@ -import datetime -import logging +""" +gui_support.py: Utilities for interacting with wxPython GUI +""" + import os -import plistlib -import random -import subprocess +import wx import sys -import threading import time -from pathlib import Path - +import logging +import plistlib +import threading +import subprocess import applescript import packaging.version -import wx -from data import model_array, os_data, smbios_data -from resources import constants, device_probe -from resources.wx_gui import gui_about +from pathlib import Path + +from .. import constants + +from ..wx_gui import gui_about +from ..detections import device_probe + +from ..datasets import ( + model_array, + os_data, + smbios_data +) def get_font_face(): diff --git a/resources/wx_gui/gui_sys_patch_display.py b/opencore_legacy_patcher/wx_gui/gui_sys_patch_display.py similarity index 98% rename from resources/wx_gui/gui_sys_patch_display.py rename to opencore_legacy_patcher/wx_gui/gui_sys_patch_display.py index 78b57eeaec..898d046453 100644 --- a/resources/wx_gui/gui_sys_patch_display.py +++ b/opencore_legacy_patcher/wx_gui/gui_sys_patch_display.py @@ -1,19 +1,20 @@ +""" +gui_sys_patch_display.py: Display root patching menu +""" -import wx import os +import wx import logging import plistlib import threading from pathlib import Path -from resources import ( - constants, -) -from resources.sys_patch import ( - sys_patch_detect -) -from resources.wx_gui import ( +from .. import constants + +from ..sys_patch import sys_patch_detect + +from ..wx_gui import ( gui_main_menu, gui_support, gui_sys_patch_start, diff --git a/resources/wx_gui/gui_sys_patch_start.py b/opencore_legacy_patcher/wx_gui/gui_sys_patch_start.py similarity index 98% rename from resources/wx_gui/gui_sys_patch_start.py rename to opencore_legacy_patcher/wx_gui/gui_sys_patch_start.py index 20efae159f..5413f28166 100644 --- a/resources/wx_gui/gui_sys_patch_start.py +++ b/opencore_legacy_patcher/wx_gui/gui_sys_patch_start.py @@ -1,3 +1,6 @@ +""" +gui_sys_patch_start.py: Root Patching Frame +""" import wx import sys @@ -10,20 +13,21 @@ from pathlib import Path -from resources import ( - constants, - kdk_handler, -) -from resources.sys_patch import ( +from .. import constants + +from ..datasets import os_data +from ..utilities import kdk_handler + +from ..sys_patch import ( sys_patch, sys_patch_detect ) -from resources.wx_gui import ( +from ..wx_gui import ( gui_main_menu, gui_support, gui_download, ) -from data import os_data + class SysPatchStartFrame(wx.Frame): diff --git a/resources/wx_gui/gui_update.py b/opencore_legacy_patcher/wx_gui/gui_update.py similarity index 98% rename from resources/wx_gui/gui_update.py rename to opencore_legacy_patcher/wx_gui/gui_update.py index 7c76e35af0..ba9ae5f7f4 100644 --- a/resources/wx_gui/gui_update.py +++ b/opencore_legacy_patcher/wx_gui/gui_update.py @@ -1,4 +1,7 @@ -# Generate UI for updating the patcher +""" +gui_update.py: Generate UI for updating the patcher +""" + import wx import sys import time @@ -9,9 +12,13 @@ from pathlib import Path -from resources.wx_gui import gui_download, gui_support -from resources import ( - constants, +from .. import constants + +from ..wx_gui import ( + gui_download, + gui_support +) +from ..utilities import ( network_handler, updates ) diff --git a/payloads/OC-Patcher.icns b/payloads/Icon/AppIcons/OC-Patcher.icns similarity index 100% rename from payloads/OC-Patcher.icns rename to payloads/Icon/AppIcons/OC-Patcher.icns diff --git a/payloads/OC-Patcher-TUI.icns b/payloads/OC-Patcher-TUI.icns deleted file mode 100644 index 9d06074313..0000000000 Binary files a/payloads/OC-Patcher-TUI.icns and /dev/null differ diff --git a/payloads/launcher.sh b/payloads/launcher.sh deleted file mode 100755 index 57152644bc..0000000000 --- a/payloads/launcher.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -cd "$(dirname "$0")" - -chmod +x OpenCore-Patcher -open OpenCore-Patcher \ No newline at end of file