commit d264cd93cd4edcc86c91feb8cef2e7dd44bec22e Author: Nico Meister Date: Sun Oct 18 17:05:44 2026 +0200 MBMNET-App v2.8.2: Quellcode (GPLv3) Co-Authored-By: Claude Opus 5.5 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ccb0a48 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Build-Ergebnisse +build/ +*.3dsx +*.cia +*.elf +*.smdh +*.o +*.bin +ftpmodul/build/ + +# Alter Versuch (nicht mehr in Benutzung) +unbenutzt-kontowechsel/ + +.DS_Store diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a910d90 --- /dev/null +++ b/Makefile @@ -0,0 +1,107 @@ +#--------------------------------------------------------------------------------- +# MBMNET Switcher - 3DS Homebrew (.3dsx) +# Benötigt devkitPro mit dem Paket "3ds-dev" (libctru, citro3d, citro2d). +#--------------------------------------------------------------------------------- +.SUFFIXES: + +ifeq ($(strip $(DEVKITARM)),) +$(error "DEVKITARM ist nicht gesetzt. Bitte devkitPro installieren.") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITARM)/3ds_rules + +TARGET := mbmnet +BUILD := build +SOURCES := source +INCLUDES := source + +# Bei jedem Release erhöhen - das Auto-Update vergleicht diese Nummer +VERSION := 2.8.2 + +APP_TITLE := MBMNET +APP_DESCRIPTION := Dein eigenes 3DS-Netzwerk (v$(VERSION)) +APP_AUTHOR := MBMNET +ICON := icon.png + +# CIA: feste Titel-ID 000400000FB4E000 +APP_PRODUCT_CODE := CTR-H-MBMN +APP_UNIQUE_ID := 0xFB4E0 +VERSION_PARTS := $(subst ., ,$(VERSION)) +# Titelversion für die CIA. Muss bei jedem Release steigen, sonst verweigert der 3DS die +# Installation (Downgrade). makerom übernimmt die mittlere Stelle nicht, deshalb kodieren wir +# Haupt- und Unterversion zusammen in der ersten Stelle: 2.2.3 -> 22.0.3 (Unterversion max. 9). +TITLE_MAJOR := $(shell echo $$(( $(word 1,$(VERSION_PARTS)) * 10 + $(word 2,$(VERSION_PARTS)) ))) +VERSION_NUM := $(shell echo $$(( ($(TITLE_MAJOR) << 10) | $(word 3,$(VERSION_PARTS)) ))) + +ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft +CFLAGS := -g -Wall -O2 -mword-relocations -ffunction-sections $(ARCH) $(INCLUDE) -D__3DS__ -DAPP_VERSION=\"$(VERSION)\" +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) +LIBS := -lcitro2d -lcitro3d -lctru -lm +LIBDIRS := $(CTRULIB) $(PORTLIBS) + +ifneq ($(BUILD),$(notdir $(CURDIR))) + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +export LD := $(CC) +export OFILES := $(CFILES:.c=.o) +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) +export APP_ICON := $(TOPDIR)/$(ICON) +export _3DSXDEPS := $(OUTPUT).smdh +export _3DSXFLAGS += --smdh=$(OUTPUT).smdh + +.PHONY: all clean cia $(BUILD) + +all: $(BUILD) + +# CIA zum Installieren mit FBI o. Ä. (braucht makerom und bannertool, siehe tools/Dockerfile) +cia: $(BUILD) + @bannertool makebanner -i assets/banner.png -a assets/banner.wav -o $(BUILD)/banner.bnr + @bannertool makesmdh -s "$(APP_TITLE)" -l "$(APP_DESCRIPTION)" -p "$(APP_AUTHOR)" -i $(ICON) -o $(BUILD)/icon.icn + @makerom -f cia -o $(TARGET).cia -elf $(TARGET).elf -rsf cia.rsf -target t -exefslogo \ + -icon $(BUILD)/icon.icn -banner $(BUILD)/banner.bnr \ + -DAPP_TITLE="$(APP_TITLE)" -DAPP_PRODUCT_CODE="$(APP_PRODUCT_CODE)" -DAPP_UNIQUE_ID="$(APP_UNIQUE_ID)" \ + -ver $(VERSION_NUM) + @echo built ... $(TARGET).cia + +$(BUILD): + @mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +# FTP-Hintergrund-Modul bauen und als Byte-Feld in die App einbetten +ftpmodul/ftpmodul.cxi: $(wildcard ftpmodul/source/*) ftpmodul/ftpmodul.rsf ftpmodul/Makefile + @$(MAKE) --no-print-directory -C ftpmodul + +source/ftpmodul_data.c: ftpmodul/ftpmodul.cxi + @echo "// Automatisch erzeugt aus ftpmodul/ftpmodul.cxi - nicht bearbeiten" > $@ + @echo "#include <3ds/types.h>" >> $@ + @echo "const u8 ftpmodul_cxi[] __attribute__((aligned(4))) = {" >> $@ + @od -An -v -tx1 $< | sed -e 's/ \([0-9a-f][0-9a-f]\)/0x\1,/g' >> $@ + @echo "};" >> $@ + @echo "const u32 ftpmodul_cxi_size = sizeof(ftpmodul_cxi);" >> $@ + @echo "const u32 ftpmodul_status_addr = $$(cat ftpmodul/ftpmodul.sym);" >> $@ + +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).3dsx $(TARGET).smdh $(TARGET).elf $(TARGET).cia source/ftpmodul_data.c + @$(MAKE) --no-print-directory -C ftpmodul clean + +else + +DEPENDS := $(OFILES:.o=.d) + +$(OUTPUT).3dsx : $(OUTPUT).elf $(_3DSXDEPS) +$(OUTPUT).elf : $(OFILES) + +-include $(DEPENDS) + +endif diff --git a/README.md b/README.md new file mode 100644 index 0000000..38c0313 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# MBMNET-App (Quellcode) + +Die 3DS-App von MBMNET: schaltet den 3DS zwischen MBMNET und Nintendo um, legt ein eigenes +MBMNET-Freundekonto an, aktiviert Miiverse und SpotPass über MBMNET und aktualisiert sich selbst. + +Fertige Versionen (`.cia` / `.3dsx`) und Anleitung: [MrMaho/MBMNET](https://git.mbm.wtf/MrMaho/MBMNET) + +## Bauen + +Am einfachsten mit Docker (enthält devkitARM, libctru, makerom und bannertool): + +```bash +docker build -t mbmnet-3ds-build tools +docker run --rm -v "$PWD":/app -w /app mbmnet-3ds-build bash -c 'make && make cia' +``` + +Ergebnis: `mbmnet.3dsx` und `mbmnet.cia`. Version steht in `Makefile` (`VERSION`). + +`release.sh` baut, legt die Dateien ins Repo `MBMNET` und erstellt dort ein Gitea-Release. + +## Aufbau + +| Datei | Was | +|---|---| +| `source/main.c` | Oberfläche, Umschalten MBMNET / Nintendo, Werkzeuge | +| `source/patcher.c` | Luma3DS-Patches (`/luma/sysmodules`, `/luma/titles`) schreiben und entfernen | +| `source/olvpatch.c` | Miiverse-Patch (Discovery-Adresse und MBMNET-Zertifikat) | +| `source/frdswitch.c` | Eigenes MBMNET-Freundekonto | +| `source/nnid.c` | Verknüpfte Nintendo Network ID lösen | +| `source/spotpass.c` | SpotPass-Aufgabe für MBMNET-Mitteilungen | +| `source/lumaconfig.c` | Spiel-Patches in der Luma-Konfiguration einschalten | +| `source/update.c` | Selbst-Update aus dem Repo `MBMNET` | +| `source/admin.c` | Entwickler-Werkzeuge nur für Admins | +| `ftpmodul/` | Kleiner FTP-Server für die Entwickler-Werkzeuge | + +## Lizenz + +GPLv3, siehe `LICENSE`. Die Miiverse-Patches stammen aus Pretendos +[Nimbus](https://github.com/PretendoNetwork/Nimbus) (GPLv3); das eigene Freundekonto ist nach Nimbus' Vorbild gebaut. + +Große Teile des Codes wurden mit Hilfe eines KI-Assistenten (Claude) geschrieben. diff --git a/assets/banner.png b/assets/banner.png new file mode 100644 index 0000000..2fbb6dd Binary files /dev/null and b/assets/banner.png differ diff --git a/assets/banner.wav b/assets/banner.wav new file mode 100644 index 0000000..a5b0bac Binary files /dev/null and b/assets/banner.wav differ diff --git a/assets/splash.png b/assets/splash.png new file mode 100644 index 0000000..82e6214 Binary files /dev/null and b/assets/splash.png differ diff --git a/cia.rsf b/cia.rsf new file mode 100644 index 0000000..7c4f7a5 --- /dev/null +++ b/cia.rsf @@ -0,0 +1,272 @@ +# Einstellungen für die CIA-Version der MBMNET-App (makerom). +# Werte mit $(...) setzt das Makefile. + +BasicInfo: + Title : $(APP_TITLE) + ProductCode : $(APP_PRODUCT_CODE) + Logo : Homebrew + +TitleInfo: + Category : Application + UniqueId : $(APP_UNIQUE_ID) + +Option: + UseOnSD : true + FreeProductCode : true + MediaFootPadding : false + EnableCrypt : false + EnableCompress : true + +AccessControlInfo: + CoreVersion : 2 + DescVersion : 2 + ReleaseKernelMajor : "02" + ReleaseKernelMinor : "33" + + # Eigene Extdata (ID = Unique ID): Speicher, den SpotPass (BOSS) für die Mitteilungs-Aufgabe braucht + UseExtSaveData : true + ExtSaveDataId : 0xFB4E0 + + # Dateisystem: SD-Karte (Patches, Updates) und Systemtitel lesen (Module patchen) + FileSystemAccess: + - CategorySystemApplication + - CategoryHardwareCheck + - CategoryFileSystemTool + - Debug + - TwlCardBackup + - TwlNandData + - Boss + - DirectSdmc + - Core + - CtrNandRo + - CtrNandRw + - CtrNandRoWrite + - CategorySystemSettings + - CardBoard + - ExportImportIvs + - DirectSdmcWrite + - SwitchCleanup + - SaveDataMove + - Shop + - Shell + - CategoryHomeMenu + - SeedDB + IoAccessControl: + - FsMountNand + - FsMountNandRoWrite + - FsMountTwln + - FsMountWnand + - FsMountCardSpi + - UseSdif3 + - CreateSeed + - UseCardSpi + + MemoryType : Application + SystemMode : 64MB + IdealProcessor : 0 + AffinityMask : 1 + Priority : 16 + MaxCpu : 0x9E + HandleTableSize : 0x200 + DisableDebug : false + EnableForceDebug : false + CanWriteSharedPage : true + CanUsePrivilegedPriority : false + CanUseNonAlphabetAndNumber : true + PermitMainFunctionArgument : true + CanShareDeviceMemory : true + RunnableOnSleep : false + SpecialMemoryArrange : true + + SystemModeExt : Legacy + CpuSpeed : 804MHz + EnableL2Cache : true + CanAccessCore2 : true + + IORegisterMapping: + - 1ff00000-1ff7ffff + MemoryMapping: + - 1f000000-1f5fffff:r + + SystemCallAccess: + ControlMemory: 1 + QueryMemory: 2 + ExitProcess: 3 + GetProcessAffinityMask: 4 + SetProcessAffinityMask: 5 + GetProcessIdealProcessor: 6 + SetProcessIdealProcessor: 7 + CreateThread: 8 + ExitThread: 9 + SleepThread: 10 + GetThreadPriority: 11 + SetThreadPriority: 12 + GetThreadAffinityMask: 13 + SetThreadAffinityMask: 14 + GetThreadIdealProcessor: 15 + SetThreadIdealProcessor: 16 + GetCurrentProcessorNumber: 17 + Run: 18 + CreateMutex: 19 + ReleaseMutex: 20 + CreateSemaphore: 21 + ReleaseSemaphore: 22 + CreateEvent: 23 + SignalEvent: 24 + ClearEvent: 25 + CreateTimer: 26 + SetTimer: 27 + CancelTimer: 28 + ClearTimer: 29 + CreateMemoryBlock: 30 + MapMemoryBlock: 31 + UnmapMemoryBlock: 32 + CreateAddressArbiter: 33 + ArbitrateAddress: 34 + CloseHandle: 35 + WaitSynchronization1: 36 + WaitSynchronizationN: 37 + SignalAndWait: 38 + DuplicateHandle: 39 + GetSystemTick: 40 + GetHandleInfo: 41 + GetSystemInfo: 42 + GetProcessInfo: 43 + GetThreadInfo: 44 + ConnectToPort: 45 + SendSyncRequest1: 46 + SendSyncRequest2: 47 + SendSyncRequest3: 48 + SendSyncRequest4: 49 + SendSyncRequest: 50 + OpenProcess: 51 + OpenThread: 52 + GetProcessId: 53 + GetProcessIdOfThread: 54 + GetThreadId: 55 + GetResourceLimit: 56 + GetResourceLimitLimitValues: 57 + GetResourceLimitCurrentValues: 58 + GetThreadContext: 59 + Break: 60 + OutputDebugString: 61 + ControlPerformanceCounter: 62 + CreatePort: 71 + CreateSessionToPort: 72 + CreateSession: 73 + AcceptSession: 74 + ReplyAndReceive1: 75 + ReplyAndReceive2: 76 + ReplyAndReceive3: 77 + ReplyAndReceive4: 78 + ReplyAndReceive: 79 + BindInterrupt: 80 + UnbindInterrupt: 81 + InvalidateProcessDataCache: 82 + StoreProcessDataCache: 83 + FlushProcessDataCache: 84 + StartInterProcessDma: 85 + StopDma: 86 + GetDmaState: 87 + RestartDma: 88 + DebugActiveProcess: 96 + BreakDebugProcess: 97 + TerminateDebugProcess: 98 + GetProcessDebugEvent: 99 + ContinueDebugEvent: 100 + GetProcessList: 101 + GetThreadList: 102 + GetDebugThreadContext: 103 + SetDebugThreadContext: 104 + QueryDebugProcessMemory: 105 + ReadProcessMemory: 106 + WriteProcessMemory: 107 + SetHardwareBreakPoint: 108 + GetDebugThreadParam: 109 + ControlProcessMemory: 112 + MapProcessMemory: 113 + UnmapProcessMemory: 114 + CreateCodeSet: 115 + CreateProcess: 117 + TerminateProcess: 118 + SetProcessResourceLimits: 119 + CreateResourceLimit: 120 + SetResourceLimitValues: 121 + AddCodeSegment: 122 + Backdoor: 123 + KernelSetState: 124 + QueryProcessMemory: 125 + + # Dienste: u. a. am:net (Updates installieren), http:C (Updates laden), fs:USER, ptm:sysm (Neustart), + # frd:a (Freundekonto umschalten), pm:app (FTP-Modul starten/beenden) + ServiceAccessControl: + - APT:U + - ac:u + - act:a + - act:u + - am:net + - boss:U + - boss:P + - cecd:u + - cfg:nor + - cfg:u + - csnd:SND + - dsp::DSP + - frd:a + - frd:u + - fs:USER + - gsp::Gpu + - gsp::Lcd + - hid:USER + - http:C + - ir:rst + - ir:u + - ir:USER + - mic:u + - ndm:u + - news:s + - nwm::EXT + - nwm::UDS + - pm:app + - ptm:sysm + - ptm:u + - pxi:dev + - soc:U + - ssl:C + - y2r:u + +SystemControlInfo: + SaveDataSize: 0KB + RemasterVersion: 0 + StackSize: 0x40000 + Dependency: + ac: 0x0004013000002402 + am: 0x0004013000001502 + boss: 0x0004013000003402 + camera: 0x0004013000001602 + cecd: 0x0004013000002602 + cfg: 0x0004013000001702 + codec: 0x0004013000001802 + csnd: 0x0004013000002702 + dlp: 0x0004013000002802 + dsp: 0x0004013000001a02 + friends: 0x0004013000003202 + gpio: 0x0004013000001b02 + gsp: 0x0004013000001c02 + hid: 0x0004013000001d02 + http: 0x0004013000002902 + i2c: 0x0004013000001e02 + ir: 0x0004013000003302 + mcu: 0x0004013000001f02 + mic: 0x0004013000002002 + ndm: 0x0004013000002b02 + news: 0x0004013000003502 + nim: 0x0004013000002c02 + nwm: 0x0004013000002d02 + pdn: 0x0004013000002102 + ps: 0x0004013000003102 + ptm: 0x0004013000002202 + ro: 0x0004013000003702 + socket: 0x0004013000002e02 + spi: 0x0004013000002302 + ssl: 0x0004013000002f02 diff --git a/ftpmodul/Makefile b/ftpmodul/Makefile new file mode 100644 index 0000000..0722606 --- /dev/null +++ b/ftpmodul/Makefile @@ -0,0 +1,27 @@ +# MBMNET-FTP-Modul (Hintergrund-Prozess). Wird vom Makefile der App mitgebaut und in die App eingebettet. +ifeq ($(strip $(DEVKITARM)),) +$(error "DEVKITARM ist nicht gesetzt.") +endif + +CC := $(DEVKITARM)/bin/arm-none-eabi-gcc +ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft +CFLAGS := -O2 -Wall -mword-relocations -ffunction-sections $(ARCH) -D__3DS__ -I$(DEVKITPRO)/libctru/include +LDFLAGS := -specs=3dsx.specs $(ARCH) -Wl,--gc-sections -L$(DEVKITPRO)/libctru/lib +SOURCES := $(wildcard source/*.c) + +ftpmodul.cxi: ftpmodul.elf ftpmodul.rsf + @makerom -f ncch -rsf ftpmodul.rsf -elf ftpmodul.elf -o ftpmodul.cxi + @# Lumas pm stürzt ab, wenn die Kennung eines Systemmoduls nicht auf 02 endet (panic 4) + @test "$$(od -An -tx1 -j 0x118 -N 1 ftpmodul.cxi | tr -d ' ')" = "02" || { echo "FEHLER: Kennung endet nicht auf 02"; rm -f ftpmodul.cxi; exit 1; } + @echo built ... ftpmodul.cxi + +ftpmodul.elf: $(SOURCES) $(wildcard source/*.h) + @$(CC) $(CFLAGS) $(SOURCES) $(LDFLAGS) -lctru -lm -o $@ + @# Adresse des Statusblocks für die App (liest ihn per Debug-Zugriff) + @$(DEVKITARM)/bin/arm-none-eabi-nm $@ | awk '$$3 == "ftpStatus" { print "0x" $$1 }' > ftpmodul.sym + @test -s ftpmodul.sym || { echo "FEHLER: ftpStatus nicht gefunden"; exit 1; } + +clean: + @rm -f ftpmodul.elf ftpmodul.cxi ftpmodul.sym + +.PHONY: clean diff --git a/ftpmodul/ftpmodul.rsf b/ftpmodul/ftpmodul.rsf new file mode 100644 index 0000000..3d30d0e --- /dev/null +++ b/ftpmodul/ftpmodul.rsf @@ -0,0 +1,162 @@ +# MBMNET-FTP-Modul: Hintergrund-Prozess (Systemmodul-Kennung 0004013000F1E002). +# Luma lädt es als /luma/sysmodules/0004013000F1E002.cxi, die MBMNET-App startet es. +BasicInfo: + Title : mbmnetftp + CompanyCode : "00" + ProductCode : CTR-S-MFTP + ContentType : Application + Logo : None + +TitleInfo: + UniqueId : 0xF1E0 + Category : Base + Version : 2 # = letzte Stelle der Kennung (02 = normales System). Muss 2 sein, sonst stürzt Lumas pm ab! + +Option: + UseOnSD : false + FreeProductCode : true + MediaFootPadding : false + EnableCrypt : false + EnableCompress : false + +AccessControlInfo: + IdealProcessor : 1 + AffinityMask : 3 + Priority : 40 + DisableDebug : false + EnableForceDebug : false + CanWriteSharedPage : false + CanUsePrivilegedPriority : false + CanUseNonAlphabetAndNumber : false + PermitMainFunctionArgument : false + CanShareDeviceMemory : true + RunnableOnSleep : false + SpecialMemoryArrange : true + ResourceLimitCategory : Other + CoreVersion : 2 + DescVersion : 2 + MemoryType : Base + HandleTableSize : 0x80 + + SystemCallAccess: + ControlMemory: 1 + QueryMemory: 2 + ExitProcess: 3 + GetProcessAffinityMask: 4 + SetProcessAffinityMask: 5 + GetProcessIdealProcessor: 6 + SetProcessIdealProcessor: 7 + CreateThread: 8 + ExitThread: 9 + SleepThread: 10 + GetThreadPriority: 11 + SetThreadPriority: 12 + GetThreadAffinityMask: 13 + SetThreadAffinityMask: 14 + GetThreadIdealProcessor: 15 + SetThreadIdealProcessor: 16 + GetCurrentProcessorNumber: 17 + Run: 18 + CreateMutex: 19 + ReleaseMutex: 20 + CreateSemaphore: 21 + ReleaseSemaphore: 22 + CreateEvent: 23 + SignalEvent: 24 + ClearEvent: 25 + CreateTimer: 26 + SetTimer: 27 + CancelTimer: 28 + ClearTimer: 29 + CreateMemoryBlock: 30 + MapMemoryBlock: 31 + UnmapMemoryBlock: 32 + CreateAddressArbiter: 33 + ArbitrateAddress: 34 + CloseHandle: 35 + WaitSynchronization1: 36 + WaitSynchronizationN: 37 + SignalAndWait: 38 + DuplicateHandle: 39 + GetSystemTick: 40 + GetHandleInfo: 41 + GetSystemInfo: 42 + GetProcessInfo: 43 + GetThreadInfo: 44 + ConnectToPort: 45 + SendSyncRequest1: 46 + SendSyncRequest2: 47 + SendSyncRequest3: 48 + SendSyncRequest4: 49 + SendSyncRequest: 50 + OpenProcess: 51 + OpenThread: 52 + GetProcessId: 53 + GetProcessIdOfThread: 54 + GetThreadId: 55 + GetResourceLimit: 56 + GetResourceLimitLimitValues: 57 + GetResourceLimitCurrentValues: 58 + GetThreadContext: 59 + Break: 60 + OutputDebugString: 61 + ControlPerformanceCounter: 62 + CreatePort: 71 + CreateSessionToPort: 72 + CreateSession: 73 + AcceptSession: 74 + ReplyAndReceive1: 75 + ReplyAndReceive2: 76 + ReplyAndReceive3: 77 + ReplyAndReceive4: 78 + ReplyAndReceive: 79 + BindInterrupt: 80 + UnbindInterrupt: 81 + InvalidateProcessDataCache: 82 + StoreProcessDataCache: 83 + FlushProcessDataCache: 84 + StartInterProcessDma: 85 + StopDma: 86 + GetDmaState: 87 + RestartDma: 88 + DebugActiveProcess: 96 + BreakDebugProcess: 97 + TerminateDebugProcess: 98 + GetProcessDebugEvent: 99 + ContinueDebugEvent: 100 + GetProcessList: 101 + GetThreadList: 102 + GetDebugThreadContext: 103 + SetDebugThreadContext: 104 + QueryDebugProcessMemory: 105 + ReadProcessMemory: 106 + WriteProcessMemory: 107 + SetHardwareBreakPoint: 108 + GetDebugThreadParam: 109 + ControlProcessMemory: 112 + MapProcessMemory: 113 + UnmapProcessMemory: 114 + CreateCodeSet: 115 + CreateProcess: 117 + TerminateProcess: 118 + SetProcessResourceLimits: 119 + CreateResourceLimit: 120 + SetResourceLimitValues: 121 + AddCodeSegment: 122 + Backdoor: 123 + KernelSetState: 124 + QueryProcessMemory: 125 + + ServiceAccessControl: + - fs:USER + - soc:U + - ac:u + + FileSystemAccess: + - DirectSdmc + - DirectSdmcWrite + +SystemControlInfo: + SaveDataSize: 0KB + RemasterVersion: 0 + StackSize: 0x8000 diff --git a/ftpmodul/source/ftp.c b/ftpmodul/source/ftp.c new file mode 100644 index 0000000..947b324 --- /dev/null +++ b/ftpmodul/source/ftp.c @@ -0,0 +1,335 @@ +// FTP-Kern des MBMNET-FTP-Moduls (Hintergrund-Prozess, siehe main.c). +// +// - Ohne Benutzername/Passwort (jede Anmeldung wird angenommen), nur Passiv-Modus (PASV/EPSV). +// - Lesen: ganze SD-Karte. Schreiben/Löschen/Ordner anlegen: nur unter /3ds/mbmnet, damit niemand im +// WLAN Luma oder boot.firm überschreiben kann. +// - Eine Verbindung nach der anderen. +#include <3ds.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ftp.h" + +#define WRITE_ROOT "/3ds/mbmnet" +#define XFER_SIZE (32 * 1024) + + +// --- Hilfen --------------------------------------------------------------------------- + +static void reply(int fd, const char *fmt, ...) +{ + char line[512]; + va_list ap; + va_start(ap, fmt); + int n = vsnprintf(line, sizeof(line) - 2, fmt, ap); + va_end(ap); + if (n < 0) return; + if (n > (int)sizeof(line) - 3) n = sizeof(line) - 3; + line[n++] = '\r'; + line[n++] = '\n'; + send(fd, line, n, 0); +} + +static bool send_all(int fd, const char *buf, size_t len) +{ + while (len) { + ssize_t n = send(fd, buf, len, 0); + if (n <= 0) return false; + buf += n; + len -= n; + } + return true; +} + +// Pfad auflösen: absolut oder relativ zu cwd, ".." und "." entfernen. Ergebnis beginnt mit "/". +static void resolve(const char *cwd, const char *arg, char *out, size_t len) +{ + char tmp[512]; + if (!arg || !arg[0]) snprintf(tmp, sizeof(tmp), "%s", cwd); + else if (arg[0] == '/') snprintf(tmp, sizeof(tmp), "%s", arg); + else snprintf(tmp, sizeof(tmp), "%s/%s", strcmp(cwd, "/") ? cwd : "", arg); + + char *parts[64]; + int count = 0; + for (char *p = strtok(tmp, "/"); p && count < 64; p = strtok(NULL, "/")) { + if (!strcmp(p, ".")) continue; + if (!strcmp(p, "..")) { if (count) count--; continue; } + parts[count++] = p; + } + size_t o = 0; + out[0] = 0; + for (int i = 0; i < count && o + 2 < len; i++) o += snprintf(out + o, len - o, "/%s", parts[i]); + if (!count) snprintf(out, len, "/"); +} + +static void sd_path(const char *path, char *out, size_t len) { snprintf(out, len, "sdmc:%s", path); } + +static bool writable(const char *path) +{ + size_t n = strlen(WRITE_ROOT); + return !strncmp(path, WRITE_ROOT, n) && (path[n] == 0 || path[n] == '/'); +} + +// --- Daten-Verbindung (passiv) ---------------------------------------------------------- + +static int open_passive(int ctrl, bool extended) +{ + static int nextPort = CONTROL_PORT + 1; + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) return -1; + struct sockaddr_in addr = { .sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY }; + for (int tries = 0; tries < 50; tries++) { + int port = nextPort++; + if (nextPort > CONTROL_PORT + 200) nextPort = CONTROL_PORT + 1; + addr.sin_port = htons(port); + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0 && listen(fd, 1) == 0) { + u32 ip = (u32)gethostid(); + if (extended) reply(ctrl, "229 Entering Extended Passive Mode (|||%d|)", port); + else reply(ctrl, "227 Entering Passive Mode (%lu,%lu,%lu,%lu,%d,%d)", (unsigned long)(ip & 0xFF), + (unsigned long)((ip >> 8) & 0xFF), (unsigned long)((ip >> 16) & 0xFF), (unsigned long)(ip >> 24), + port >> 8, port & 0xFF); + return fd; + } + } + close(fd); + return -1; +} + +// Wartet auf den Client (höchstens 10 s) und gibt die Daten-Verbindung zurück +static int accept_data(int pasvFd) +{ + struct pollfd p = { .fd = pasvFd, .events = POLLIN }; + if (poll(&p, 1, 10000) <= 0) return -1; + return accept(pasvFd, NULL, NULL); +} + +// --- Befehle ----------------------------------------------------------------------------- + +// Ein Eintrag im MLSD/MLST-Format (maschinenlesbar, wie FileZilla es abfragt) +static int mlsx_fact(char *out, size_t len, const struct stat *st, bool dir, const char *name) +{ + char modify[20] = "20000101000000"; + if (st->st_mtime > 0) strftime(modify, sizeof(modify), "%Y%m%d%H%M%S", gmtime(&st->st_mtime)); + return snprintf(out, len, "type=%s;size=%llu;modify=%s;perm=%s; %s\r\n", dir ? "dir" : "file", + (unsigned long long)(dir ? 0 : st->st_size), modify, dir ? "el" : "r", name); +} + +enum { LIST_UNIX, LIST_NAMES, LIST_MLSD }; + +static void list_dir(int ctrl, int data, const char *path, int mode) +{ + char sd[600]; + sd_path(path, sd, sizeof(sd)); + DIR *d = opendir(sd); + if (!d) { reply(ctrl, "550 Ordner nicht gefunden"); return; } + reply(ctrl, "150 Liste folgt"); + struct dirent *e; + char line[700], child[900]; + while ((e = readdir(d))) { + if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, "..")) continue; + if (mode == LIST_NAMES) { int n = snprintf(line, sizeof(line), "%s\r\n", e->d_name); send_all(data, line, n); continue; } + snprintf(child, sizeof(child), "%s/%s", sd, e->d_name); + struct stat st = { 0 }; + stat(child, &st); + bool dir = S_ISDIR(st.st_mode) || e->d_type == DT_DIR; + if (mode == LIST_MLSD) { + int n = mlsx_fact(line, sizeof(line), &st, dir, e->d_name); + if (!send_all(data, line, n)) break; + continue; + } + char date[16] = "Jan 1 2000"; + if (st.st_mtime > 0) strftime(date, sizeof(date), "%b %d %H:%M", localtime(&st.st_mtime)); + int n = snprintf(line, sizeof(line), "%s 1 3ds 3ds %10llu %s %s\r\n", dir ? "drwxr-xr-x" : "-rw-r--r--", + (unsigned long long)(dir ? 0 : st.st_size), date, e->d_name); + if (!send_all(data, line, n)) break; + } + closedir(d); + reply(ctrl, "226 Fertig"); +} + +static void retrieve(int ctrl, int data, const char *path) +{ + char sd[600]; + sd_path(path, sd, sizeof(sd)); + FILE *f = fopen(sd, "rb"); + if (!f) { reply(ctrl, "550 Datei nicht gefunden"); return; } + reply(ctrl, "150 Sende Datei"); + char *buf = malloc(XFER_SIZE); + bool ok = buf != NULL; + size_t n; + while (ok && (n = fread(buf, 1, XFER_SIZE, f)) > 0) ok = send_all(data, buf, n); + free(buf); + fclose(f); + reply(ctrl, ok ? "226 Fertig" : "426 Übertragung abgebrochen"); +} + +static void store(int ctrl, int data, const char *path) +{ + char sd[600]; + sd_path(path, sd, sizeof(sd)); + FILE *f = fopen(sd, "wb"); + if (!f) { reply(ctrl, "550 Datei nicht schreibbar"); return; } + reply(ctrl, "150 Empfange Datei"); + char *buf = malloc(XFER_SIZE); + bool ok = buf != NULL; + ssize_t n; + while (ok && (n = recv(data, buf, XFER_SIZE, 0)) > 0) ok = fwrite(buf, 1, n, f) == (size_t)n; + free(buf); + fclose(f); + reply(ctrl, ok ? "226 Fertig" : "451 Schreiben fehlgeschlagen"); +} + +static void session(int ctrl) +{ + char cwd[512] = "/", line[600], path[512], sd[600], renameFrom[512] = ""; + int pasvFd = -1; + size_t used = 0; + reply(ctrl, "220 MBMNET-FTP (ohne Passwort, Schreiben nur in " WRITE_ROOT ")"); + + while (!ftp_should_exit()) { + // Eine Zeile lesen + char *eol; + while (!(eol = memchr(line, '\n', used))) { + struct pollfd p = { .fd = ctrl, .events = POLLIN }; + if (ftp_should_exit()) goto done; + int r = poll(&p, 1, 500); + if (r < 0) goto done; + if (r == 0) continue; + if (used >= sizeof(line) - 1) used = 0; // zu lange Zeile verwerfen + ssize_t n = recv(ctrl, line + used, sizeof(line) - 1 - used, 0); + if (n <= 0) goto done; + used += n; + } + *eol = 0; + if (eol > line && eol[-1] == '\r') eol[-1] = 0; + char cmd[600]; + snprintf(cmd, sizeof(cmd), "%s", line); + size_t rest = used - (eol - line + 1); + memmove(line, eol + 1, rest); + used = rest; + + char *arg = strchr(cmd, ' '); + if (arg) *arg++ = 0; + for (char *c = cmd; *c; c++) if (*c >= 'a' && *c <= 'z') *c -= 32; + + if (!strcmp(cmd, "USER")) reply(ctrl, "331 Passwort egal"); + else if (!strcmp(cmd, "PASS")) reply(ctrl, "230 Angemeldet"); + else if (!strcmp(cmd, "SYST")) reply(ctrl, "215 UNIX Type: L8"); + else if (!strcmp(cmd, "FEAT")) { reply(ctrl, "211-Features:\r\n PASV\r\n EPSV\r\n SIZE\r\n MDTM\r\n MLST type*;size*;modify*;perm*;\r\n UTF8\r\n211 Ende"); } + else if (!strcmp(cmd, "OPTS")) reply(ctrl, "200 OK"); + else if (!strcmp(cmd, "NOOP")) reply(ctrl, "200 OK"); + else if (!strcmp(cmd, "TYPE") || !strcmp(cmd, "MODE") || !strcmp(cmd, "STRU")) reply(ctrl, "200 OK"); + else if (!strcmp(cmd, "PWD") || !strcmp(cmd, "XPWD")) reply(ctrl, "257 \"%s\"", cwd); + else if (!strcmp(cmd, "CWD") || !strcmp(cmd, "CDUP")) { + resolve(cwd, !strcmp(cmd, "CDUP") ? ".." : arg, path, sizeof(path)); + sd_path(path, sd, sizeof(sd)); + struct stat st; + if (stat(sd, &st) == 0 && S_ISDIR(st.st_mode)) { snprintf(cwd, sizeof(cwd), "%s", path); reply(ctrl, "250 OK"); } + else if (!strcmp(path, "/")) { snprintf(cwd, sizeof(cwd), "/"); reply(ctrl, "250 OK"); } + else reply(ctrl, "550 Ordner nicht gefunden"); + } + else if (!strcmp(cmd, "PASV") || !strcmp(cmd, "EPSV")) { + if (pasvFd >= 0) close(pasvFd); + pasvFd = open_passive(ctrl, !strcmp(cmd, "EPSV")); + if (pasvFd < 0) reply(ctrl, "425 Kein Daten-Port frei"); + } + else if (!strcmp(cmd, "SIZE")) { + resolve(cwd, arg, path, sizeof(path)); + sd_path(path, sd, sizeof(sd)); + struct stat st; + if (stat(sd, &st) == 0 && !S_ISDIR(st.st_mode)) reply(ctrl, "213 %llu", (unsigned long long)st.st_size); + else reply(ctrl, "550 Nicht gefunden"); + } + else if (!strcmp(cmd, "MLST")) { + // Ein einzelner Eintrag, direkt auf der Steuer-Verbindung + resolve(cwd, arg, path, sizeof(path)); + sd_path(path, sd, sizeof(sd)); + struct stat st = { 0 }; + bool root = !strcmp(path, "/"); + if (!root && stat(sd, &st) != 0) { reply(ctrl, "550 Nicht gefunden"); continue; } + char fact[700]; + mlsx_fact(fact, sizeof(fact), &st, root || S_ISDIR(st.st_mode), path); + fact[strcspn(fact, "\r\n")] = 0; + reply(ctrl, "250-Eintrag\r\n %s\r\n250 Ende", fact); + } + else if (!strcmp(cmd, "MDTM")) { + resolve(cwd, arg, path, sizeof(path)); + sd_path(path, sd, sizeof(sd)); + struct stat st; + char modify[20] = "20000101000000"; + if (stat(sd, &st) != 0) { reply(ctrl, "550 Nicht gefunden"); continue; } + if (st.st_mtime > 0) strftime(modify, sizeof(modify), "%Y%m%d%H%M%S", gmtime(&st.st_mtime)); + reply(ctrl, "213 %s", modify); + } + else if (!strcmp(cmd, "LIST") || !strcmp(cmd, "NLST") || !strcmp(cmd, "MLSD") || !strcmp(cmd, "RETR") || !strcmp(cmd, "STOR")) { + bool isList = cmd[0] == 'L' || cmd[0] == 'N' || cmd[0] == 'M'; + // "LIST -la" u. ä.: Optionen ignorieren + const char *target = arg && arg[0] == '-' ? NULL : arg; + resolve(cwd, target, path, sizeof(path)); + if (!strcmp(cmd, "STOR") && !writable(path)) { reply(ctrl, "550 Schreiben nur in " WRITE_ROOT); continue; } + if (pasvFd < 0) { reply(ctrl, "425 Erst PASV senden"); continue; } + int data = accept_data(pasvFd); + close(pasvFd); + pasvFd = -1; + if (data < 0) { reply(ctrl, "425 Keine Daten-Verbindung"); continue; } + if (isList) list_dir(ctrl, data, path, cmd[0] == 'N' ? LIST_NAMES : cmd[0] == 'M' ? LIST_MLSD : LIST_UNIX); + else if (cmd[0] == 'R') retrieve(ctrl, data, path); + else store(ctrl, data, path); + close(data); + } + else if (!strcmp(cmd, "DELE") || !strcmp(cmd, "RMD") || !strcmp(cmd, "MKD") || !strcmp(cmd, "XMKD")) { + resolve(cwd, arg, path, sizeof(path)); + if (!writable(path) || !strcmp(path, WRITE_ROOT)) { reply(ctrl, "550 Ändern nur in " WRITE_ROOT); continue; } + sd_path(path, sd, sizeof(sd)); + int r = !strcmp(cmd, "DELE") ? remove(sd) : !strcmp(cmd, "RMD") ? rmdir(sd) : mkdir(sd, 0777); + if (r == 0) reply(ctrl, cmd[0] == 'M' || cmd[0] == 'X' ? "257 \"%s\" angelegt" : "250 OK", path); + else reply(ctrl, "550 Fehlgeschlagen"); + } + else if (!strcmp(cmd, "RNFR")) { + resolve(cwd, arg, renameFrom, sizeof(renameFrom)); + if (!writable(renameFrom)) { renameFrom[0] = 0; reply(ctrl, "550 Ändern nur in " WRITE_ROOT); } + else reply(ctrl, "350 Weiter mit RNTO"); + } + else if (!strcmp(cmd, "RNTO")) { + resolve(cwd, arg, path, sizeof(path)); + char from[600]; + sd_path(renameFrom, from, sizeof(from)); + sd_path(path, sd, sizeof(sd)); + if (renameFrom[0] && writable(path) && rename(from, sd) == 0) reply(ctrl, "250 OK"); + else reply(ctrl, "550 Umbenennen fehlgeschlagen"); + renameFrom[0] = 0; + } + else if (!strcmp(cmd, "QUIT")) { reply(ctrl, "221 Tschüss"); break; } + else reply(ctrl, "502 Nicht unterstützt"); + } +done: + if (pasvFd >= 0) close(pasvFd); +} + +// Nimmt Verbindungen an, bis das Netz weg ist, sich die IP ändert oder das Modul aufhören soll. +void ftp_serve(int listenFd, u32 ip) +{ + while (!ftp_should_exit()) { + if ((u32)gethostid() != ip) return; // WLAN gewechselt oder weg + struct pollfd p = { .fd = listenFd, .events = POLLIN }; + int r = poll(&p, 1, 2000); + if (r < 0 || (p.revents & (POLLERR | POLLHUP | POLLNVAL))) return; + if (r == 0) continue; + int ctrl = accept(listenFd, NULL, NULL); + if (ctrl < 0) return; + session(ctrl); + close(ctrl); + } +} diff --git a/ftpmodul/source/ftp.h b/ftpmodul/source/ftp.h new file mode 100644 index 0000000..ee38fe6 --- /dev/null +++ b/ftpmodul/source/ftp.h @@ -0,0 +1,10 @@ +#pragma once +#include <3ds/types.h> + +#define CONTROL_PORT 5000 + +// Nimmt FTP-Verbindungen an, bis das Netz weg ist oder sich die IP ändert +void ftp_serve(int listenFd, u32 ip); + +// Soll das Modul aufhören? (Stopp-Datei der App oder Beenden-Aufforderung des Systems; in main.c) +bool ftp_should_exit(void); diff --git a/ftpmodul/source/ftpstatus.h b/ftpmodul/source/ftpstatus.h new file mode 100644 index 0000000..25d1dce --- /dev/null +++ b/ftpmodul/source/ftpstatus.h @@ -0,0 +1,28 @@ +#pragma once +// Statusblock des FTP-Moduls. Die App liest ihn per Debug-Zugriff direkt aus dem Speicher des Moduls +// (die Adresse steht beim Bauen fest) - so klappt die Anzeige auch, wenn das Modul nicht an die SD kommt. +// Über "stop" kann die App das Modul ebenfalls ohne SD zum Beenden auffordern. +// Wird von ftpmodul/source/main.c und source/ftpctl.c (App) benutzt. +#include <3ds/types.h> + +#define FTP_STATUS_MAGIC 0x5446424D // "MBFT" + +enum { + FTP_STAGE_START = 0, // vor __appInit / srvInit + FTP_STAGE_INIT, // srv, fs, SD erledigt (Ergebnisse in srv/fs/sdmc) + FTP_STAGE_SOC, // wartet auf den Netzwerk-Dienst (socInit, Ergebnis in soc) + FTP_STAGE_WIFI, // wartet auf WLAN (keine IP) + FTP_STAGE_PORT, // Port 5000 lässt sich nicht öffnen (errno in bindErrno) + FTP_STAGE_READY, // bereit, IP in ip + FTP_STAGE_EXIT, // beendet sich +}; + +typedef struct { + u32 magic; + u32 stage; + s32 srv, fs, sdmc, soc; + u32 ip; + u32 heartbeat; // zählt hoch, solange das Modul lebt + u32 stop; // die App setzt 1: Modul beendet sich sauber + s32 bindErrno; +} FtpStatus; diff --git a/ftpmodul/source/main.c b/ftpmodul/source/main.c new file mode 100644 index 0000000..be1fd3c --- /dev/null +++ b/ftpmodul/source/main.c @@ -0,0 +1,181 @@ +// MBMNET-FTP-Modul: läuft als eigener Hintergrund-Prozess, auch wenn die MBMNET-App geschlossen ist. +// +// Die App legt dieses Modul als /luma/sysmodules/0004013000F1E002.cxi ab und startet es über den +// Prozess-Manager (Luma lädt Systemmodule mit dieser Kennung von der SD). "FTP aus" in der App +// beendet den Prozess. Nach einem Neustart des 3DS ist es aus, bis die App es wieder startet. +// +// Die aktuelle Adresse steht für die App in /3ds/mbmnet/ftp-adresse.txt. +// +// Beenden immer sauber durch das Modul selbst (nie von außen abschießen - das brachte den 3DS zum +// Absturz): "FTP aus" legt /3ds/mbmnet/ftp-stopp an, beim Neustart/Ausschalten schickt das System +// die Benachrichtigung 0x100. Dann Verbindungen und Netzwerk-Dienst schließen und zurückkehren. +#include <3ds.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ftp.h" +#include "ftpstatus.h" + +// Statusblock für die App (Adresse fest, siehe Makefile -> ftpmodul.sym) +volatile FtpStatus ftpStatus __attribute__((used, aligned(4))) = { .magic = FTP_STATUS_MAGIC }; + +#define SOC_BUFFER_SIZE 0x20000 +#define ADDRESS_FILE "sdmc:/3ds/mbmnet/ftp-adresse.txt" +#define LOG_FILE "sdmc:/3ds/mbmnet/ftp.log" +#define STOP_FILE "sdmc:/3ds/mbmnet/ftp-stopp" + +static Handle notificationSemaphore; +static bool quit; + + +// Protokoll für die Fehlersuche (die App zeigt die letzte Zeile, wenn der Server nicht antwortet) +static void logf_(const char *fmt, ...) +{ + FILE *f = fopen(LOG_FILE, "a"); + if (!f) return; + va_list ap; + va_start(ap, fmt); + vfprintf(f, fmt, ap); + va_end(ap); + fputc('\n', f); + fclose(f); +} + +// Ein Hintergrund-Modul bekommt nur wenig Speicher: Heap fest vorgeben statt "alles, was frei ist" +u32 __ctru_heap_size = 0x80000; +u32 __ctru_linear_heap_size = 0x1000; + +// Nur die Dienste, die das Modul braucht (kein Grafik-/HOME-Menü-Dienst wie bei einer App) +void __appInit(void) +{ + // srv ist beim Start evtl. noch belegt: kurz wiederholen + for (int i = 0; i < 100 && R_FAILED(ftpStatus.srv = srvInit()); i++) svcSleepThread(50 * 1000 * 1000); + ftpStatus.fs = fsInit(); + ftpStatus.sdmc = archiveMountSdmc(); + ftpStatus.stage = FTP_STAGE_INIT; +} + +void __appExit(void) +{ + archiveUnmountAll(); + fsExit(); + srvExit(); +} + +bool ftp_should_exit(void) +{ + ftpStatus.heartbeat++; + if (ftpStatus.stop) quit = true; // Stopp-Bit der App (geht auch ohne SD) + if (quit) return true; + // Beenden-Aufforderung des Systems (Neustart, Ausschalten) + if (notificationSemaphore && R_SUCCEEDED(svcWaitSynchronization(notificationSemaphore, 0))) { + u32 id = 0; + if (R_SUCCEEDED(srvReceiveNotification(&id)) && id == 0x100) quit = true; + } + // Stopp-Datei der App, höchstens alle 2 Sekunden nachsehen + static u64 lastCheck; + u64 now = osGetTime(); + if (!quit && now - lastCheck >= 2000) { + lastCheck = now; + struct stat st; + if (stat(STOP_FILE, &st) == 0) quit = true; + } + return quit; +} + +// Wartet ms Millisekunden, bricht aber ab, sobald das Modul aufhören soll +static void sleep_ms(int ms) +{ + for (int waited = 0; waited < ms && !ftp_should_exit(); waited += 100) svcSleepThread(100LL * 1000 * 1000); +} + +static void write_address(u32 ip) +{ + mkdir("sdmc:/3ds", 0777); + mkdir("sdmc:/3ds/mbmnet", 0777); + FILE *f = fopen(ADDRESS_FILE, "w"); + if (!f) return; + if (ip) fprintf(f, "%lu.%lu.%lu.%lu:%d\n", (unsigned long)(ip & 0xFF), (unsigned long)((ip >> 8) & 0xFF), + (unsigned long)((ip >> 16) & 0xFF), (unsigned long)(ip >> 24), CONTROL_PORT); + fclose(f); +} + +int main(void) +{ + remove(LOG_FILE); + remove(STOP_FILE); + srvEnableNotification(¬ificationSemaphore); // für die Beenden-Aufforderung 0x100 + logf_("MBMNET-FTP-Modul gestartet: srv %08lX, fs %08lX, sdmc %08lX, frei (Base) %lld KB", + (unsigned long)ftpStatus.srv, (unsigned long)ftpStatus.fs, (unsigned long)ftpStatus.sdmc, + osGetMemRegionFree(MEMREGION_BASE) / 1024); + u32 *socBuffer = memalign(0x1000, SOC_BUFFER_SIZE); + if (!socBuffer) { logf_("Fehler: kein Speicher für den Netzwerk-Puffer"); return 1; } + + while (!ftp_should_exit()) { + // Netzwerk-Dienst (nach dem Schlafmodus ggf. neu) + Result rc; + int tries = 0; + ftpStatus.stage = FTP_STAGE_SOC; + while (R_FAILED(rc = ftpStatus.soc = socInit(socBuffer, SOC_BUFFER_SIZE))) { + if (ftp_should_exit()) goto done; + if (tries++ % 15 == 0) logf_("Netzwerk-Dienst (socInit) fehlgeschlagen: %08lX", (unsigned long)rc); + sleep_ms(2000); + } + logf_("Netzwerk-Dienst bereit"); + + int failures = 0, waits = 0; + while (failures < 5 && !ftp_should_exit()) { + u32 ip = (u32)gethostid(); + ftpStatus.ip = ip; + if (!ip) { // noch kein WLAN + ftpStatus.stage = FTP_STAGE_WIFI; + if (waits++ % 15 == 0) logf_("Warte auf WLAN (keine IP)"); + write_address(0); + sleep_ms(2000); + continue; + } + waits = 0; + + int fd = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(CONTROL_PORT), .sin_addr.s_addr = INADDR_ANY }; + if (fd < 0 || bind(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0 || listen(fd, 2) != 0) { + logf_("Port %d öffnen fehlgeschlagen (Socket %d, errno %d)", CONTROL_PORT, fd, errno); + ftpStatus.stage = FTP_STAGE_PORT; + ftpStatus.bindErrno = errno; + if (fd >= 0) close(fd); + failures++; + sleep_ms(2000); + continue; + } + failures = 0; + ftpStatus.stage = FTP_STAGE_READY; + write_address(ip); + logf_("Bereit: ftp://%lu.%lu.%lu.%lu:%d", (unsigned long)(ip & 0xFF), (unsigned long)((ip >> 8) & 0xFF), + (unsigned long)((ip >> 16) & 0xFF), (unsigned long)(ip >> 24), CONTROL_PORT); + ftp_serve(fd, ip); // kehrt zurück, wenn das Netz weg ist oder sich die IP ändert + close(fd); + sleep_ms(500); + } + socExit(); + if (ftp_should_exit()) break; + // Mehrfach kein Socket möglich (z. B. nach dem Schlafmodus): Netzwerk-Dienst neu aufsetzen + logf_("Netzwerk-Dienst wird neu aufgesetzt"); + sleep_ms(2000); + } +done: + ftpStatus.stage = FTP_STAGE_EXIT; + // Sauber beenden: Adresse weg, Stopp-Datei weg; libctru schließt danach fs und srv + remove(ADDRESS_FILE); + remove(STOP_FILE); + logf_("Beendet"); + free(socBuffer); + return 0; +} diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..627e784 Binary files /dev/null and b/icon.png differ diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..d889b37 --- /dev/null +++ b/release.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Baut die App und lädt sie ins Repo "MBMNET" hoch. Danach aktualisiert sich jede +# MBMNET-App beim nächsten Start von selbst. +# Zusätzlich legt es auf Gitea ein Release "vX.Y.Z" mit .cia und .3dsx an (für Universal-Updater). +# +# Vorher in Makefile die VERSION erhöhen! +# ./release.sh ["Release-Notizen"] bauen, hochladen, Release anlegen +# ./release.sh --nur-release ["Notizen"] nur das Release zur aktuellen Version anlegen +set -euo pipefail +cd "$(dirname "$0")" + +VERSION=$(sed -n 's/^VERSION *:= *//p' Makefile) +RELEASE=../release +GITEA=https://git.mbm.wtf +REPO=MrMaho/MBMNET + +NUR_RELEASE=0 +if [ "${1:-}" = "--nur-release" ]; then NUR_RELEASE=1; shift; fi +NOTIZEN=${1:-"MBMNET-App v$VERSION"} + +if [ "$NUR_RELEASE" = 0 ]; then + # Build-Umgebung mit makerom und bannertool (für die CIA), wird nur beim ersten Mal gebaut + docker image inspect mbmnet-3ds-build >/dev/null 2>&1 || docker build -t mbmnet-3ds-build tools + + echo "Baue MBMNET-App v$VERSION ..." + docker run --rm -v "$PWD":/app -w /app mbmnet-3ds-build bash -c 'make clean >/dev/null && make && make cia' + + cp mbmnet.3dsx mbmnet.cia "$RELEASE/" + echo "$VERSION" > "$RELEASE/version.txt" + + (cd "$RELEASE" && git add mbmnet.3dsx mbmnet.cia version.txt && git commit -m "MBMNET-App v$VERSION" && git push) +fi + +# --- Gitea-Release ------------------------------------------------------------------- +# Zugangsdaten wie bei git push aus dem Schlüsselbund; sie landen nur in einer curl-Konfiguration +# über stdin (nicht in der Prozessliste, nicht in der Ausgabe). +CRED=$(printf 'protocol=https\nhost=git.mbm.wtf\n\n' | git credential fill) +GUSER=$(sed -n 's/^username=//p' <<<"$CRED") +GPASS=$(sed -n 's/^password=//p' <<<"$CRED") +api() { # api METHODE PFAD [weitere curl-Argumente] + local method=$1 path=$2; shift 2 + printf 'user = "%s:%s"\n' "$GUSER" "$GPASS" | curl -sS --fail-with-body -K - -X "$method" "$GITEA/api/v1/repos/$REPO$path" "$@" +} +json() { python3 -c "import json,sys; d=json.load(sys.stdin); print($1)"; } + +TAG="v$VERSION" +COMMIT=$(git -C "$RELEASE" rev-parse HEAD) +if ID=$( (api GET "/releases/tags/$TAG" | json "d['id']") 2>/dev/null ); then + echo "Release $TAG gibt es schon (ID $ID), ersetze die Dateien ..." +else + BODY=$(TAG="$TAG" COMMIT="$COMMIT" NOTIZEN="$NOTIZEN" python3 -c \ + 'import json,os; print(json.dumps({"tag_name": os.environ["TAG"], "target_commitish": os.environ["COMMIT"], "name": "MBMNET " + os.environ["TAG"], "body": os.environ["NOTIZEN"]}))') + ID=$(api POST /releases -H 'Content-Type: application/json' -d "$BODY" | json "d['id']") + echo "Release $TAG angelegt (ID $ID)" +fi + +# Vorhandene Dateien gleichen Namens löschen (bei erneutem Lauf), dann hochladen +for f in mbmnet.cia mbmnet.3dsx; do + for old in $(api GET "/releases/$ID/assets" | json "' '.join(str(a['id']) for a in d if a['name']=='$f')"); do + api DELETE "/releases/$ID/assets/$old" >/dev/null + done + api POST "/releases/$ID/assets?name=$f" -F "attachment=@$RELEASE/$f" >/dev/null + echo " $f hochgeladen" +done + +echo "Fertig: v$VERSION ist veröffentlicht ($GITEA/$REPO/releases/tag/$TAG)." diff --git a/source/admin.c b/source/admin.c new file mode 100644 index 0000000..5e0ec4c --- /dev/null +++ b/source/admin.c @@ -0,0 +1,57 @@ +// Entwickler-Werkzeuge nur für Admins: Die App fragt bei MBMNET, ob die verknüpfte NNID einem Admin +// gehört (GET /mbmnet/app-info?pid=...). Die Antwort wird auf der SD gemerkt, damit die Werkzeuge +// auch im Nintendo-Modus und ohne Verbindung da sind. +#include <3ds.h> +#include +#include + +#include "admin.h" + +#define CACHE_FILE "sdmc:/3ds/mbmnet/admin" + +static volatile bool isAdmin; +static Thread thread; +static char url[128]; + +static void remember(bool on) +{ + FILE *f = fopen(CACHE_FILE, "w"); + if (f) { fputs(on ? "1" : "0", f); fclose(f); } +} + +static void worker(void *arg) +{ + (void)arg; + httpcContext ctx; + if (R_FAILED(httpcOpenContext(&ctx, HTTPC_METHOD_GET, url, 1))) return; + httpcAddRequestHeaderField(&ctx, "User-Agent", "MBMNET-Switcher/" APP_VERSION); + u32 status = 0, got = 0; + char body[32] = { 0 }; + Result rc = httpcBeginRequest(&ctx); + if (R_SUCCEEDED(rc)) rc = httpcGetResponseStatusCodeTimeout(&ctx, &status, 8ULL * 1000 * 1000 * 1000); + if (R_SUCCEEDED(rc) && status == 200) httpcDownloadData(&ctx, (u8 *)body, sizeof(body) - 1, &got); + httpcCloseContext(&ctx); + if (status != 200 || strncmp(body, "admin=", 6) != 0) return; // keine Antwort: gemerkte gilt weiter + isAdmin = body[6] == '1'; + remember(isAdmin); +} + +void admin_start(const char *server, u32 pid) +{ + FILE *f = fopen(CACHE_FILE, "r"); + if (f) { isAdmin = fgetc(f) == '1'; fclose(f); } + if (!pid) return; + snprintf(url, sizeof(url), "http://%s/mbmnet/app-info?pid=%lu", server, (unsigned long)pid); + s32 prio = 0x30; + svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); + thread = threadCreate(worker, NULL, 16 * 1024, prio + 1, -2, false); +} + +bool admin_is(void) { return isAdmin; } + +void admin_finish(void) +{ + if (!thread) return; + if (R_SUCCEEDED(threadJoin(thread, 3ULL * 1000 * 1000 * 1000))) threadFree(thread); + thread = NULL; +} diff --git a/source/admin.h b/source/admin.h new file mode 100644 index 0000000..f6fcff7 --- /dev/null +++ b/source/admin.h @@ -0,0 +1,9 @@ +#pragma once +#include <3ds/types.h> + +// Fragt im Hintergrund bei MBMNET, ob die verknüpfte NNID (pid) einem Admin gehört. +// pid = 0: nicht fragen, nur die gemerkte Antwort vom letzten Mal benutzen. +void admin_start(const char *server, u32 pid); +// Admin? (gemerkte Antwort, bis der Server geantwortet hat) +bool admin_is(void); +void admin_finish(void); diff --git a/source/blz.c b/source/blz.c new file mode 100644 index 0000000..1d3d99f --- /dev/null +++ b/source/blz.c @@ -0,0 +1,58 @@ +// Entpacker für das "Backwards LZ"-Format, mit dem Nintendo die .code von +// Systemmodulen komprimiert. Luma3DS wendet code.ips-Patches auf die +// ENTPACKTE .code an, deshalb müssen wir genauso rechnen. +#include +#include "blz.h" + +static u32 read32(const u8 *p) { return p[0] | (p[1] << 8) | (p[2] << 16) | ((u32)p[3] << 24); } + +bool blz_looks_compressed(const u8 *buf, u32 size) +{ + if (size < 8) return false; + u32 enc = read32(buf + size - 8); + u32 add = read32(buf + size - 4); + u32 hdr = enc >> 24; + u32 enclen = enc & 0xFFFFFF; + return hdr >= 8 && hdr <= 0x10 && enclen >= hdr && enclen <= size && add > 0 && add < 0x1000000; +} + +u32 blz_decompressed_size(const u8 *buf, u32 size) +{ + return size + read32(buf + size - 4); +} + +// buf muss mindestens blz_decompressed_size() Bytes groß sein. +// Daten liegen am Anfang von buf, es wird rückwärts in-place entpackt. +bool blz_decompress(u8 *buf, u32 size) +{ + u32 enc = read32(buf + size - 8); + u32 hdr = enc >> 24; + u32 enclen = enc & 0xFFFFFF; + u32 outsize = blz_decompressed_size(buf, size); + + u8 *src = buf + size - hdr; + u8 *srcEnd = buf + size - enclen; + u8 *dst = buf + outsize; + + while (src > srcEnd) { + u8 flags = *--src; + for (int i = 0; i < 8 && src > srcEnd; i++, flags <<= 1) { + if (flags & 0x80) { + if (src - 2 < buf) return false; + u8 hi = *--src; + u8 lo = *--src; + u32 len = (hi >> 4) + 3; + u32 disp = (((hi & 0x0F) << 8) | lo) + 3; + for (u32 j = 0; j < len; j++) { + if (dst - 1 < buf || dst - 1 + disp >= buf + outsize) return false; + dst--; + *dst = dst[disp]; + } + } else { + if (dst - 1 < buf) return false; + *--dst = *--src; + } + } + } + return true; +} diff --git a/source/blz.h b/source/blz.h new file mode 100644 index 0000000..23e9990 --- /dev/null +++ b/source/blz.h @@ -0,0 +1,6 @@ +#pragma once +#include <3ds/types.h> + +bool blz_looks_compressed(const u8 *buf, u32 size); +u32 blz_decompressed_size(const u8 *buf, u32 size); +bool blz_decompress(u8 *buf, u32 size); diff --git a/source/frdswitch.c b/source/frdswitch.c new file mode 100644 index 0000000..de2cc6c --- /dev/null +++ b/source/frdswitch.c @@ -0,0 +1,245 @@ +// Eigenes MBMNET-Freundekonto, wie bei Pretendos Nimbus: +// +// Freundekonto 1: Nintendo - mit Konto-Platz 1 (Nintendo Network ID) und der Nintendo-Freundesliste +// Freundekonto 3: MBMNET - mit eigenem Konto-Platz (MBMNET-Konto) und eigener Freundesliste +// +// (Freundekonto 2 benutzt Pretendos Nimbus, das bleibt unangetastet.) +// +// Umschalten: beide Konten abmelden, das andere laden, seinen Konto-Platz zum Standard machen, Neustart. +// Beim ersten Mal legt die App das MBMNET-Freundekonto an. Es hat noch keine Kennung; beim ersten +// Login holt es sich bei MBMNET ein neues Konto (NASC "passwd"), der Server gibt ihm den Freundescode +// des MBMNET-Kontos von der Webseite. +#include <3ds.h> +#include +#include +#include + +#include "frdswitch.h" + +#define RESULT_LOCAL_ACCOUNT_NOT_EXISTS 0xC880C4ED +#define LOG_FILE "sdmc:/3ds/mbmnet/konto.log" + +static bool ready; +static FILE *logf; +static const char *failedStep; + +static Result step(const char *name, Result rc) +{ + if (logf) fprintf(logf, "%-36s %08lX%s\n", name, (unsigned long)rc, R_FAILED(rc) ? " <- FEHLER" : ""); + if (R_FAILED(rc) && !failedStep) failedStep = name; + return rc; +} + +static void note(const char *name, Result rc) +{ + if (logf) fprintf(logf, "%-36s %08lX%s\n", name, (unsigned long)rc, R_FAILED(rc) ? " (ignoriert)" : ""); +} + +Result frdswitch_init(void) +{ + Result rc = ndmuInit(); + if (R_SUCCEEDED(rc)) rc = frdInit(false); // frd:a (Verwaltung) + if (R_SUCCEEDED(rc)) rc = actInit(false); // act:a + // Ohne diese SDK-Version lehnt der Freunde-Dienst Anlegen und Umschalten ab (so macht es Nimbus; + // daran scheiterte unser erster Versuch mit C960C4F6) + if (R_SUCCEEDED(rc)) rc = FRD_SetClientSdkVersion(0x70000c8); + ready = R_SUCCEEDED(rc); + return rc; +} + +void frdswitch_exit(void) +{ + actExit(); + frdExit(); + ndmuExit(); +} + +u8 frdswitch_current(void) +{ + u8 id = 0; + if (ready) FRD_GetMyLocalAccountId(&id); + return id; +} + +// Konto-Platz (act) zu einem Freundekonto. 0 = keiner. +static u32 act_slot_of(u8 friendAccount) +{ + u8 count = 0; + if (R_FAILED(ACT_GetCommonInfo(&count, sizeof(count), INFO_TYPE_COMMON_NUM_ACCOUNTS))) return 0; + for (u8 slot = 1; slot <= count; slot++) { + u8 fp = 0; + if (R_SUCCEEDED(ACT_GetAccountInfo(&fp, sizeof(fp), slot, INFO_TYPE_FP_LOCAL_ACCOUNT_ID)) && fp == friendAccount) return slot; + } + return 0; +} + +bool frdswitch_slot_linked(u8 friendAccount, char *id, size_t len) +{ + id[0] = 0; + u32 slot = ready ? act_slot_of(friendAccount) : 0; + if (!slot) return false; + AccountId acc = { 0 }; + if (R_FAILED(ACT_GetAccountInfo(acc, sizeof(acc), slot, INFO_TYPE_ACCOUNT_ID))) return false; + snprintf(id, len, "%s", acc); + return id[0] != 0; +} + +// Beide Konten abmelden. Das Freundekonto lässt sich nur offline entladen. +static Result unload(void) +{ + note("Konto (act) abmelden", ACTA_UnloadConsoleAccount()); // ohne geladenes Konto: "ungültiger Zustand" + + Result rc = step("Offline gehen (exklusiv)", NDMU_EnterExclusiveState(NDM_EXCLUSIVE_STATE_LOCAL_COMMUNICATIONS)); + if (R_FAILED(rc)) return rc; + for (int i = 0; i < 150; i++) { // höchstens 15 Sekunden + bool online = true; + if (R_FAILED(FRD_IsOnline(&online)) || !online) break; + svcSleepThread(100 * 1000 * 1000); + } + // Hängt der Freunde-Dienst noch an einer Anfrage, kurz wiederholen + for (int attempt = 1; attempt <= 20; attempt++) { + rc = FRDA_UnloadLocalAccount(); + if (R_SUCCEEDED(rc)) { + if (logf) fprintf(logf, "%-36s %08lX (Versuch %d)\n", "Freundekonto abmelden", (unsigned long)rc, attempt); + return rc; + } + svcSleepThread(500 * 1000 * 1000); + } + return step("Freundekonto abmelden (10 s)", rc); +} + +// Freundekonto laden. "Schon geladen" (z. B. direkt nach dem Anlegen) zählt als Erfolg. +static Result load_friend_account(u8 friendAccount) +{ + Result rc = FRDA_LoadLocalAccount(friendAccount); + if (R_FAILED(rc) && frdswitch_current() == friendAccount) { + note("Freundekonto laden (war schon geladen)", rc); + return 0; + } + return step("Freundekonto laden", rc); +} + +// Konto-Platz (act) des Freundekontos zum Standard machen; fehlt er, anlegen. *created: neu angelegt. +static Result use_act_slot(u8 friendAccount, u32 *slotOut, bool *created) +{ + Result rc = 0; + u32 slot = act_slot_of(friendAccount); + *created = false; + if (!slot) { + u8 count = 0; + rc = step("Konto-Plätze zählen", ACT_GetCommonInfo(&count, sizeof(count), INFO_TYPE_COMMON_NUM_ACCOUNTS)); + if (R_SUCCEEDED(rc)) rc = step("Konto-Platz anlegen", ACTA_CreateConsoleAccount()); + if (R_FAILED(rc)) return rc; + slot = count + 1; + rc = step("Konto-Platz speichern", ACTA_CommitConsoleAccount(slot)); + if (R_FAILED(rc)) return rc; + *created = true; + } + if (logf) fprintf(logf, " -> Konto-Platz %lu\n", (unsigned long)slot); + *slotOut = slot; + return step("Standard-Konto setzen", ACTA_SetDefaultAccount(slot)); +} + +bool frdswitch_to(u8 target, bool *created, char *msg, size_t msglen) +{ + *created = false; + if (!ready) { + snprintf(msg, msglen, "Kontodienste nicht verfügbar.\nIst Luma3DS aktuell?"); + return false; + } + mkdir("sdmc:/3ds/mbmnet", 0777); + logf = fopen(LOG_FILE, "w"); + failedStep = NULL; + u8 from = frdswitch_current(); + if (logf) fprintf(logf, "MBMNET: Freundekonto %u -> %u (App v%s)\n\n", from, target, APP_VERSION); + + u32 slot = 0; + bool newSlot = false; + Result rc = unload(); + if (R_SUCCEEDED(rc)) { + rc = FRDA_LoadLocalAccount(target); + if (rc == (Result)RESULT_LOCAL_ACCOUNT_NOT_EXISTS && target == FRIEND_ACCOUNT_MBMNET) { + // Erstes Mal: eigenes MBMNET-Freundekonto anlegen (normale Umgebung, die Patches lenken sie um) + note("Freundekonto laden (gibt es noch nicht)", rc); + rc = step("MBMNET-Freundekonto anlegen", FRDA_CreateLocalAccount(FRIEND_ACCOUNT_MBMNET, 0, 0, 1)); + if (R_SUCCEEDED(rc)) { *created = true; rc = load_friend_account(target); } + } else if (R_FAILED(rc) && frdswitch_current() == target) { + note("Freundekonto laden (war schon geladen)", rc); + rc = 0; + } else { + step("Freundekonto laden", rc); + } + if (R_SUCCEEDED(rc)) rc = use_act_slot(target, &slot, &newSlot); + // Neuer Platz: frisch zurücksetzen, damit "Vorhandene ID verknüpfen" angeboten wird (darf scheitern) + if (R_SUCCEEDED(rc) && newSlot) note("Konto-Platz zurücksetzen", ACTA_UnbindServerAccount(slot, true)); + } + + if (R_FAILED(rc)) { + // Zurück auf das vorherige Freundekonto, damit der 3DS nicht ohne/mit falschem Konto dasteht. + // Erst entladen - ein geladenes Konto lässt sich nicht einfach ersetzen. + u8 back = from ? from : FRIEND_ACCOUNT_NINTENDO; + if (frdswitch_current() != back) { + note("Rückweg: Freundekonto abmelden", FRDA_UnloadLocalAccount()); + note("Rückweg: altes Freundekonto laden", FRDA_LoadLocalAccount(back)); + } + NDMU_LeaveExclusiveState(); + } + if (logf) { fprintf(logf, "\nErgebnis: %s\n", R_SUCCEEDED(rc) ? "OK" : "FEHLER"); fclose(logf); logf = NULL; } + if (R_FAILED(rc)) { + snprintf(msg, msglen, "Umschalten fehlgeschlagen bei:\n%s (Fehler %08lX)\nProtokoll: /3ds/mbmnet/konto.log", + failedStep ? failedStep : "?", (unsigned long)rc); + return false; + } + return true; +} + +u32 frdswitch_my_pid(void) +{ + FriendKey key = { 0 }; + if (!ready || R_FAILED(FRD_GetMyFriendKey(&key))) return 0; + return key.principalId; +} + +bool frdswitch_pid_is_mbmnet(u32 pid) +{ + return pid >= MBMNET_PID_FIRST && pid <= MBMNET_PID_LAST; +} + +// Das MBMNET-Freundekonto neu anlegen (es hat eine Kennung von einem anderen Server, z. B. Pretendo). +// Der Konto-Platz mit der verknüpften MBMNET-ID bleibt, nur das Freundekonto wird ersetzt. Danach +// Neustart: Beim ersten Login holt es sich bei MBMNET eine neue Kennung. +bool frdswitch_recreate_mbmnet(char *msg, size_t msglen) +{ + if (!ready || frdswitch_current() != FRIEND_ACCOUNT_MBMNET) { + snprintf(msg, msglen, "MBMNET-Freundekonto ist nicht geladen."); + return false; + } + mkdir("sdmc:/3ds/mbmnet", 0777); + logf = fopen(LOG_FILE, "w"); + failedStep = NULL; + if (logf) fprintf(logf, "MBMNET: Freundekonto 3 neu anlegen, alte Kennung %lu (App v%s)\n\n", + (unsigned long)frdswitch_my_pid(), APP_VERSION); + + u32 slot = 0; + bool newSlot = false; + Result rc = unload(); + if (R_SUCCEEDED(rc)) rc = step("MBMNET-Freundekonto neu anlegen", FRDA_CreateLocalAccount(FRIEND_ACCOUNT_MBMNET, 0, 0, 1)); + if (R_SUCCEEDED(rc)) rc = load_friend_account(FRIEND_ACCOUNT_MBMNET); + if (R_SUCCEEDED(rc)) rc = use_act_slot(FRIEND_ACCOUNT_MBMNET, &slot, &newSlot); + if (R_FAILED(rc)) { + if (frdswitch_current() != FRIEND_ACCOUNT_MBMNET) note("Rückweg: Freundekonto laden", FRDA_LoadLocalAccount(FRIEND_ACCOUNT_MBMNET)); + NDMU_LeaveExclusiveState(); + } + if (logf) { fprintf(logf, "\nErgebnis: %s\n", R_SUCCEEDED(rc) ? "OK" : "FEHLER"); fclose(logf); logf = NULL; } + if (R_FAILED(rc)) { + snprintf(msg, msglen, "Neu anlegen fehlgeschlagen bei:\n%s (Fehler %08lX)\nProtokoll: /3ds/mbmnet/konto.log", + failedStep ? failedStep : "?", (unsigned long)rc); + return false; + } + return true; +} + +u8 frdswitch_slot_of(u8 friendAccount) +{ + return ready ? (u8)act_slot_of(friendAccount) : 0; +} diff --git a/source/frdswitch.h b/source/frdswitch.h new file mode 100644 index 0000000..e769ec1 --- /dev/null +++ b/source/frdswitch.h @@ -0,0 +1,27 @@ +#pragma once +#include <3ds/types.h> +#include + +#define FRIEND_ACCOUNT_NINTENDO 1 +#define FRIEND_ACCOUNT_MBMNET 3 // 2 benutzt Pretendos Nimbus + +// Kennungen (PIDs), die MBMNET für Freundekonten vergibt (FRIEND_PID_BASE in db.js) +#define MBMNET_PID_FIRST 1900000001u +#define MBMNET_PID_LAST 1999999999u + +Result frdswitch_init(void); +void frdswitch_exit(void); +// Geladenes Freundekonto (1 = Nintendo, 3 = MBMNET, 0 = unbekannt) +u8 frdswitch_current(void); +// Ist im Konto-Platz dieses Freundekontos eine ID verknüpft? (Name in id) +bool frdswitch_slot_linked(u8 friendAccount, char *id, size_t len); +// Auf ein Freundekonto umschalten (MBMNET: beim ersten Mal anlegen, *created = true). +// Danach muss der 3DS neu starten. false + msg bei Fehler. +bool frdswitch_to(u8 target, bool *created, char *msg, size_t msglen); +// Kennung des geladenen Freundekontos (0 = noch keine) +u32 frdswitch_my_pid(void); +bool frdswitch_pid_is_mbmnet(u32 pid); +// MBMNET-Freundekonto neu anlegen (hat eine fremde Kennung). Danach Neustart. +bool frdswitch_recreate_mbmnet(char *msg, size_t msglen); +// Konto-Platz (act) eines Freundekontos, 0 = keiner +u8 frdswitch_slot_of(u8 friendAccount); diff --git a/source/ftpcore.c b/source/ftpcore.c new file mode 100644 index 0000000..d3dd1d7 --- /dev/null +++ b/source/ftpcore.c @@ -0,0 +1,2 @@ +// FTP-Kern (Befehle, Pfade, Schreibschutz) aus dem FTP-Modul wiederverwenden - eine Quelle für beides +#include "../ftpmodul/source/ftp.c" diff --git a/source/ftpctl.c b/source/ftpctl.c new file mode 100644 index 0000000..661fa36 --- /dev/null +++ b/source/ftpctl.c @@ -0,0 +1,109 @@ +// FTP-Server in der App (Entwickler-Werkzeuge). Läuft in einem eigenen Thread, solange die App offen ist. +// +// Das Hintergrund-Modul (ftpmodul/, eigener Prozess auf Kern 1) ist abgeschaltet: Es brachte den +// Kernel-Scheduler auf Kern 1 zum Absturz (PC FFF21584, kaputter Thread in der Warteschlange). Die App +// räumt seine Dateien weg, damit es nie wieder startet. +// +// Ohne Passwort, Port 5000, Lesen von der ganzen SD, Schreiben/Löschen nur in /3ds/mbmnet (ftp.c). +#include <3ds.h> +#include +#include +#include +#include +#include +#include +#include + +#include "ftpctl.h" +#include "../ftpmodul/source/ftp.h" + +#define SOC_BUFFER_SIZE 0x100000 + +static u32 *socBuffer; +static Thread thread; +static volatile bool running; +static char address[32]; +static char status[64]; + +bool ftp_should_exit(void) { return !running; } + +static void server(void *arg) +{ + (void)arg; + while (running) { + u32 ip = (u32)gethostid(); + if (!ip) { snprintf(status, sizeof(status), "kein WLAN"); address[0] = 0; svcSleepThread(1000000000LL); continue; } + int fd = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(CONTROL_PORT), .sin_addr.s_addr = INADDR_ANY }; + if (fd < 0 || bind(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0 || listen(fd, 2) != 0) { + if (fd >= 0) close(fd); + snprintf(status, sizeof(status), "Port %d belegt", CONTROL_PORT); + svcSleepThread(2000000000LL); + continue; + } + snprintf(address, sizeof(address), "%lu.%lu.%lu.%lu:%d", (unsigned long)(ip & 0xFF), (unsigned long)((ip >> 8) & 0xFF), + (unsigned long)((ip >> 16) & 0xFF), (unsigned long)(ip >> 24), CONTROL_PORT); + ftp_serve(fd, ip); // bis WLAN weg, IP neu oder "FTP aus" + close(fd); + address[0] = 0; + } +} + +// Reste des abgeschalteten Hintergrund-Moduls entfernen (sonst startete eine alte App-Version es wieder) +void ftpctl_cleanup_module(void) +{ + remove("sdmc:/luma/sysmodules/0004013000F1E002.cxi"); + remove("sdmc:/luma/sysmodules/0004013000F1E001.cxi"); + remove("sdmc:/3ds/mbmnet/ftp-an"); + remove("sdmc:/3ds/mbmnet/ftp-stopp"); + remove("sdmc:/3ds/mbmnet/ftp-adresse.txt"); +} + +bool ftpctl_running(void) { return running; } + +bool ftpctl_start(char *msg, size_t msglen) +{ + if (running) return true; + socBuffer = memalign(0x1000, SOC_BUFFER_SIZE); + if (!socBuffer || R_FAILED(socInit(socBuffer, SOC_BUFFER_SIZE))) { + free(socBuffer); + socBuffer = NULL; + snprintf(msg, msglen, "FTP: Netzwerk nicht verfügbar."); + return false; + } + running = true; + status[0] = address[0] = 0; + s32 prio = 0x30; + svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); + thread = threadCreate(server, NULL, 32 * 1024, prio + 1, -2, false); + if (!thread) { + running = false; + socExit(); + free(socBuffer); + socBuffer = NULL; + snprintf(msg, msglen, "FTP: konnte nicht starten."); + return false; + } + snprintf(msg, msglen, "FTP-Server an (läuft, solange die App offen ist).\nOhne Passwort, Port 5000. Herunterladen von der ganzen SD,\n" + "Hochladen/Löschen nur in /3ds/mbmnet."); + return true; +} + +void ftpctl_stop(char *msg, size_t msglen) +{ + if (running) { + running = false; + threadJoin(thread, 5000000000LL); + threadFree(thread); + thread = NULL; + socExit(); + free(socBuffer); + socBuffer = NULL; + } + address[0] = 0; + if (msg) snprintf(msg, msglen, "FTP-Server aus."); +} + +bool ftpctl_resume(char *msg, size_t msglen) { (void)msg; (void)msglen; return false; } +const char *ftpctl_address(void) { return address; } +const char *ftpctl_status(void) { return status[0] ? status : "startet ..."; } diff --git a/source/ftpctl.h b/source/ftpctl.h new file mode 100644 index 0000000..b0571c3 --- /dev/null +++ b/source/ftpctl.h @@ -0,0 +1,16 @@ +#pragma once +#include <3ds/types.h> +#include + +// FTP-Server in der App (läuft, solange die App offen ist) +bool ftpctl_running(void); +bool ftpctl_start(char *msg, size_t msglen); +void ftpctl_stop(char *msg, size_t msglen); +// Nach einem Neustart des 3DS: wieder starten, wenn FTP zuletzt an war. true = gestartet (msg gesetzt) +bool ftpctl_resume(char *msg, size_t msglen); +// "192.168.1.42:5000", leer solange das Modul noch keine Adresse hat +const char *ftpctl_address(void); +// Letzte Zeile aus dem Protokoll des Moduls (/3ds/mbmnet/ftp.log), leer wenn keins +const char *ftpctl_status(void); +// Reste des abgeschalteten Hintergrund-Moduls entfernen +void ftpctl_cleanup_module(void); diff --git a/source/lumaconfig.c b/source/lumaconfig.c new file mode 100644 index 0000000..fe007b9 --- /dev/null +++ b/source/lumaconfig.c @@ -0,0 +1,135 @@ +// Ändert Optionen in Lumas Konfiguration (/luma/config.ini): +// splash_position -> Boot-Splash "MBMNET aktiv" anzeigen +// enable_external_firm_and_modules -> nötig, damit Luma die Patches in /luma/sysmodules lädt +// enable_game_patching -> nötig, damit Luma Patches in /luma/titles lädt (Miiverse) +// Beim Zurücksetzen wird eine Option nur wieder ausgeschaltet, wenn MBMNET sie eingeschaltet hat +// (Merker in /3ds/mbmnet/...). +#include +#include +#include +#include +#include + +#include "lumaconfig.h" + +#define CONFIG_FILE "sdmc:/luma/config.ini" +#define SPLASH_MARKER "sdmc:/3ds/mbmnet/splash-war-aus" +#define MODULES_MARKER "sdmc:/3ds/mbmnet/module-waren-aus" +#define PATCHING_MARKER "sdmc:/3ds/mbmnet/game-patching-war-aus" + +// Setzt "key = value". Gibt den alten Wert in oldValue zurück. false, wenn Datei/Option fehlt. +static bool set_option(const char *key, const char *value, char *oldValue, size_t oldLen) +{ + FILE *f = fopen(CONFIG_FILE, "rb"); + if (!f) return false; + fseek(f, 0, SEEK_END); + long size = ftell(f); + fseek(f, 0, SEEK_SET); + if (size <= 0 || size > 64 * 1024) { fclose(f); return false; } + char *in = malloc(size + 1); + char *out = malloc(size + 128); + bool ok = in && out && fread(in, 1, size, f) == (size_t)size; + fclose(f); + if (!ok) { free(in); free(out); return false; } + in[size] = 0; + + size_t keyLen = strlen(key); + bool found = false; + size_t o = 0; + for (char *line = in; *line;) { + char *end = strchr(line, '\n'); + size_t len = end ? (size_t)(end - line + 1) : strlen(line); + char *p = line; + while (*p == ' ' || *p == '\t') p++; + char *eq = strchr(p, '='); + bool isKey = !found && strncmp(p, key, keyLen) == 0 && (p[keyLen] == ' ' || p[keyLen] == '=') + && eq && eq < line + len; + if (isKey) { + char *v = eq + 1; + while (*v == ' ') v++; + size_t vl = strcspn(v, "\r\n"); + snprintf(oldValue, oldLen, "%.*s", (int)vl, v); + o += sprintf(out + o, "%s = %s%s", key, value, (end && end > line && end[-1] == '\r') ? "\r\n" : "\n"); + found = true; + } else { + memcpy(out + o, line, len); + o += len; + } + line += len; + } + + if (found && strcasecmp(oldValue, value) != 0) { + f = fopen(CONFIG_FILE, "wb"); + ok = f && fwrite(out, 1, o, f) == o; + if (f) fclose(f); + } + free(in); + free(out); + return found && ok; +} + +static void touch(const char *path) +{ + FILE *m = fopen(path, "w"); + if (m) fclose(m); +} + +static bool exists(const char *path) +{ + struct stat st; + return stat(path, &st) == 0; +} + +bool lumaconfig_enable_splash(void) +{ + char old[32] = ""; + if (!set_option("splash_position", "after payloads", old, sizeof(old))) return false; + if (strcasecmp(old, "off") == 0) touch(SPLASH_MARKER); + return true; +} + +void lumaconfig_restore_splash(void) +{ + if (!exists(SPLASH_MARKER)) return; // war schon vorher an: nichts ändern + char old[32] = ""; + set_option("splash_position", "off", old, sizeof(old)); + remove(SPLASH_MARKER); +} + +bool lumaconfig_enable_modules(void) +{ + char old[8] = ""; + if (!set_option("enable_external_firm_and_modules", "1", old, sizeof(old))) return false; + if (strcmp(old, "0") == 0) touch(MODULES_MARKER); + return true; +} + +void lumaconfig_keep_modules(void) +{ + remove(MODULES_MARKER); +} + +void lumaconfig_restore_modules(void) +{ + if (!exists(MODULES_MARKER)) return; + char old[8] = ""; + set_option("enable_external_firm_and_modules", "0", old, sizeof(old)); + remove(MODULES_MARKER); +} + +bool lumaconfig_enable_game_patching(void) +{ + char old[8] = ""; + if (!set_option("enable_game_patching", "1", old, sizeof(old))) return false; + if (strcmp(old, "0") != 0) return false; // war schon an + touch(PATCHING_MARKER); + return true; +} + +void lumaconfig_restore_game_patching(void) +{ + if (!exists(PATCHING_MARKER)) return; + char old[8] = ""; + set_option("enable_game_patching", "0", old, sizeof(old)); + remove(PATCHING_MARKER); +} diff --git a/source/lumaconfig.h b/source/lumaconfig.h new file mode 100644 index 0000000..9c492c9 --- /dev/null +++ b/source/lumaconfig.h @@ -0,0 +1,21 @@ +#pragma once +#include + +// Splash in Lumas Konfiguration einschalten ("after payloads"). false, wenn config.ini fehlt. +bool lumaconfig_enable_splash(void); +// Splash wieder ausschalten, falls MBMNET ihn eingeschaltet hat. +void lumaconfig_restore_splash(void); + +// "Enable loading external FIRMs and system modules" einschalten - ohne diese Option lädt +// Luma die Patches in /luma/sysmodules nicht. +bool lumaconfig_enable_modules(void); +// Wieder ausschalten, falls MBMNET sie eingeschaltet hat. +void lumaconfig_restore_modules(void); +// Option dauerhaft anlassen (das FTP-Modul braucht sie auch im Nintendo-Modus) +void lumaconfig_keep_modules(void); + +// "Enable game patching" einschalten - ohne sie lädt Luma die Patches in /luma/titles (Miiverse) nicht. +// true, wenn sie dadurch erst eingeschaltet wurde (dann ist ein Neustart nötig). +bool lumaconfig_enable_game_patching(void); +// Wieder ausschalten, falls MBMNET sie eingeschaltet hat. +void lumaconfig_restore_game_patching(void); diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..3003c0a --- /dev/null +++ b/source/main.c @@ -0,0 +1,547 @@ +// MBMNET Switcher - schaltet den 3DS zwischen MBMNET und Nintendo (Original) um. +// +// Unten zwei Kacheln: MBMNET und Nintendo. Antippen schaltet um, unter der aktiven steht "Aktiv". +// SELECT blendet die Entwickler-Werkzeuge ein und aus (beim Öffnen immer aus). +#include <3ds.h> +#include +#include +#include + +#include "patcher.h" +#include "update.h" +#include "relaunch.h" +#include "nnid.h" +#include "frdswitch.h" +#include "admin.h" +#include "ftpctl.h" +#include "spotpass.h" + +#define TOP_W 400 +#define BOT_W 320 +#define SCR_H 240 + +// Farben (gleiche Palette wie Logo und Webseite) +#define COL_RED C2D_Color32(0xE4, 0x00, 0x2B, 0xFF) +#define COL_RED_DARK C2D_Color32(0x9E, 0x00, 0x1E, 0xFF) +#define COL_BG C2D_Color32(0x16, 0x19, 0x1F, 0xFF) +#define COL_BG2 C2D_Color32(0x22, 0x26, 0x2E, 0xFF) +#define COL_CARD C2D_Color32(0x2A, 0x2F, 0x39, 0xFF) +#define COL_CARD_HI C2D_Color32(0x3A, 0x41, 0x4E, 0xFF) +#define COL_WHITE C2D_Color32(0xFF, 0xFF, 0xFF, 0xFF) +#define COL_MUTED C2D_Color32(0x9A, 0xA3, 0xAF, 0xFF) +#define COL_GREEN C2D_Color32(0x22, 0xC5, 0x5E, 0xFF) +#define COL_AMBER C2D_Color32(0xF5, 0x9E, 0x0B, 0xFF) +#define COL_NINTENDO C2D_Color32(0xE6, 0x00, 0x12, 0xFF) + +// Bedienelemente auf dem unteren Bildschirm. Die Werkzeuge gibt es nur für Admins. +enum { BTN_ENABLE, BTN_DISABLE, BTN_DIAG, BTN_FTP, BTN_UNLINK, BTN_SPOTPASS, BTN_REBOOT, BTN_COUNT }; + +typedef struct { float x, y, w, h; } Box; + +#define TILE_Y 14 +#define TILE_W 142 +#define TILE_H_FULL 210 +#define TILE_H_ADMIN 160 +#define TOOL_COUNT 5 +static const Box toolBoxes[TOOL_COUNT] = { { 12, 184, 56, 42 }, { 72, 184, 56, 42 }, { 132, 184, 56, 42 }, { 192, 184, 56, 42 }, { 252, 184, 56, 42 } }; + +static Box box_of(int btn, bool admin) +{ + float h = admin ? TILE_H_ADMIN : TILE_H_FULL; + switch (btn) { + case BTN_ENABLE: return (Box){ 12, TILE_Y, TILE_W, h }; + case BTN_DISABLE: return (Box){ 166, TILE_Y, TILE_W, h }; + case BTN_DIAG: return toolBoxes[0]; + case BTN_FTP: return toolBoxes[1]; + case BTN_UNLINK: return toolBoxes[2]; + case BTN_SPOTPASS: return toolBoxes[3]; + default: return toolBoxes[4]; + } +} + +static C2D_TextBuf textBuf; +static int spotpassTestFrames = -1; // läuft der SpotPass-Test? (Bilder seit dem Start) +static bool ftpOn; // läuft das FTP-Modul? (alle 2 s geprüft, nicht in jedem Bild) + +// --- Zeichenhilfen ------------------------------------------------------------ + +static void text(const char *s, float x, float y, float size, u32 color, u32 flags) +{ + C2D_Text t; + C2D_TextParse(&t, textBuf, s); + C2D_TextOptimize(&t); + C2D_DrawText(&t, C2D_WithColor | flags, x, y, 0.5f, size, size, color); +} + +static void round_rect(float x, float y, float w, float h, float r, u32 color) +{ + C2D_DrawRectSolid(x + r, y, 0.5f, w - 2 * r, h, color); + C2D_DrawRectSolid(x, y + r, 0.5f, w, h - 2 * r, color); + C2D_DrawCircleSolid(x + r, y + r, 0.5f, r, color); + C2D_DrawCircleSolid(x + w - r, y + r, 0.5f, r, color); + C2D_DrawCircleSolid(x + r, y + h - r, 0.5f, r, color); + C2D_DrawCircleSolid(x + w - r, y + h - r, 0.5f, r, color); +} + +// Das MBMNET-Logo: rotes abgerundetes Quadrat mit einem "M" aus verbundenen Netzwerk-Knoten. +// Geometrie identisch zu assets/logo.svg (100x100-Raster). +static void draw_logo(float x, float y, float size) +{ + float s = size / 100.0f; + round_rect(x, y, size, size, 22 * s, COL_RED_DARK); + round_rect(x, y, size, size - 4 * s, 22 * s, COL_RED); + + static const float pts[5][2] = { {24, 72}, {24, 30}, {50, 56}, {76, 30}, {76, 72} }; + for (int i = 0; i < 4; i++) { + C2D_DrawLine(x + pts[i][0] * s, y + pts[i][1] * s, COL_WHITE, + x + pts[i + 1][0] * s, y + pts[i + 1][1] * s, COL_WHITE, 7 * s, 0.5f); + } + for (int i = 0; i < 5; i++) { + C2D_DrawCircleSolid(x + pts[i][0] * s, y + pts[i][1] * s, 0.5f, 9 * s, COL_WHITE); + if (i == 2) C2D_DrawCircleSolid(x + pts[i][0] * s, y + pts[i][1] * s, 0.5f, 4 * s, COL_RED); + } +} + +// Nintendo-Schriftzug im roten Rahmen (nachgezeichnet, kein Bild) +static void draw_nintendo(float cx, float cy, float w) +{ + float h = w * 0.36f, r = h / 2; + round_rect(cx - w / 2, cy - h / 2, w, h, r, COL_NINTENDO); + round_rect(cx - w / 2 + 3, cy - h / 2 + 3, w - 6, h - 6, r - 3, COL_WHITE); + text("Nintendo", cx, cy - h * 0.36f, w / 150.0f, COL_NINTENDO, C2D_AlignCenter); +} + +// --- Bildschirme --------------------------------------------------------------- + +static void draw_update_line(bool admin) +{ + char line[64]; + const char *v = update_new_version(); + switch (update_state()) { + case UPD_CHECKING: snprintf(line, sizeof(line), "v" APP_VERSION); break; + case UPD_AVAILABLE: snprintf(line, sizeof(line), "Update auf v%s bereit", v); break; + case UPD_DOWNLOADING: + if (update_attempt() > 1) snprintf(line, sizeof(line), "lade v%s (Versuch %d) ...", v, update_attempt()); + else snprintf(line, sizeof(line), "lade v%s ...", v); + break; + case UPD_INSTALLED: snprintf(line, sizeof(line), "v%s installiert", v); break; + case UPD_ERROR: snprintf(line, sizeof(line), admin ? "Update-Server offline" : "v" APP_VERSION); break; + default: snprintf(line, sizeof(line), "v" APP_VERSION); break; + } + u32 color = update_state() == UPD_INSTALLED ? COL_GREEN : update_pending() ? COL_AMBER : COL_MUTED; + text(line, TOP_W - 10, 4, 0.4f, color, C2D_AlignRight); +} + +static void draw_top(PatchState st, const char *msg, bool admin, bool isAdmin) +{ + C2D_DrawRectangle(0, 0, 0, TOP_W, SCR_H, COL_BG2, COL_BG2, COL_BG, COL_BG); + draw_update_line(admin); + const char *hint = admin ? "START: Beenden SELECT: Werkzeuge aus" : "START: Beenden SELECT: Werkzeuge"; + text(hint, 10, 4, 0.4f, COL_MUTED, 0); + if (ftpOn) { + // FTP-Adresse direkt daneben + C2D_Text t; + float w = 0; + C2D_TextParse(&t, textBuf, hint); + C2D_TextGetDimensions(&t, 0.4f, 0.4f, &w, NULL); + char ftp[112]; + const char *a = ftpctl_address(); + const char *st = ftpctl_status(); + if (a[0]) snprintf(ftp, sizeof(ftp), "FTP %s", a); + else snprintf(ftp, sizeof(ftp), "FTP: %s", st[0] ? st : "startet ..."); + text(ftp, 10 + w + 12, 4, 0.4f, COL_GREEN, 0); + } + + float y = msg[0] || admin ? 26 : 62; + draw_logo(TOP_W / 2 - 32, y, 64); + text("MBMNET", TOP_W / 2, y + 70, 0.9f, COL_WHITE, C2D_AlignCenter); + y += 108; + + // Admins: was gerade wirklich los ist + if (admin) { + char line[96], id[20]; + const char *label = st == STATE_MBMNET ? "Patch: MBMNET" : st == STATE_FOREIGN ? "Patch: fremd (z. B. Pretendo)" : "Patch: keiner"; + snprintf(line, sizeof(line), "%s · NNID: %s%s", label, nnid_linked(id, sizeof(id)) ? id : "keine", isAdmin ? " · Admin" : ""); + text(line, TOP_W / 2, y, 0.42f, COL_MUTED, C2D_AlignCenter); + y += 18; + } + if (msg[0]) { + round_rect(16, y, TOP_W - 32, SCR_H - y - 8, 10, COL_CARD); + text(msg, 28, y + 6, 0.46f, COL_WHITE, 0); + } else if (!admin) { + text("Tippe unten auf MBMNET oder Nintendo.", TOP_W / 2, 200, 0.45f, COL_MUTED, C2D_AlignCenter); + } +} + +static void draw_tile(int btn, bool sel, bool active, bool admin) +{ + Box b = box_of(btn, admin); + if (sel) round_rect(b.x - 3, b.y - 3, b.w + 6, b.h + 6, 15, COL_RED); + round_rect(b.x, b.y, b.w, b.h, 12, active ? COL_CARD_HI : COL_CARD); + + float cx = b.x + b.w / 2, logoCy = b.y + b.h / 2 - 12; + if (btn == BTN_ENABLE) draw_logo(cx - 36, logoCy - 36, 72); + else draw_nintendo(cx, logoCy, 116); + + if (active) { + C2D_DrawCircleSolid(cx - 26, b.y + b.h - 26, 0.5f, 5, COL_GREEN); + text("Aktiv", cx + 6, b.y + b.h - 36, 0.6f, COL_GREEN, C2D_AlignCenter); + } +} + +static void draw_bottom(int selected, PatchState st, bool admin) +{ + C2D_DrawRectSolid(0, 0, 0, BOT_W, SCR_H, COL_BG); + draw_tile(BTN_ENABLE, selected == BTN_ENABLE, st == STATE_MBMNET, admin); + draw_tile(BTN_DISABLE, selected == BTN_DISABLE, st == STATE_ORIGINAL, admin); + if (!admin) return; + + const char *labels[TOOL_COUNT] = { "Diagnose", ftpOn ? "FTP aus" : "FTP an", "ID lösen", "SpotPass", "Neustart" }; + for (int i = 0; i < TOOL_COUNT; i++) { + Box b = toolBoxes[i]; + bool sel = selected == BTN_DIAG + i; + bool on = i == 1 && ftpOn; + round_rect(b.x, b.y, b.w, b.h, 10, sel ? COL_CARD_HI : COL_CARD); + if (sel) C2D_DrawRectSolid(b.x, b.y + 10, 0.5f, 4, b.h - 20, COL_RED); + if (on) C2D_DrawCircleSolid(b.x + 12, b.y + b.h / 2, 0.5f, 4, COL_GREEN); + text(labels[i], b.x + b.w / 2, b.y + 13, 0.45f, on ? COL_GREEN : COL_WHITE, C2D_AlignCenter); + } +} + +// --- Aktionen -------------------------------------------------------------------- +// +// Wie bei Pretendo hat MBMNET ein eigenes Freundekonto (Nr. 3) mit eigenem Konto-Platz. Umschalten = +// Patches an/aus + auf das andere Freundekonto wechseln + Neustart. Beide Anmeldungen bleiben dabei +// erhalten, die Nintendo-Freundesliste auch. + +// Merker älterer Versionen (bis v2.4): Die MBMNET-ID wurde damals im Nintendo-Platz verknüpft +#define UNLINKED_MARKER "sdmc:/3ds/mbmnet/nnid-geloest" +static bool old_mbmnet_link(void) { FILE *f = fopen(UNLINKED_MARKER, "r"); if (f) fclose(f); return f != NULL; } + +static int armed = -1; // Sicherheitsabfrage (zweimal antippen) + +// Name der MBMNET-ID, gemerkt beim Wechsel zu Nintendo. Der 3DS erlaubt dieselbe ID nicht in zwei Konto-Plätzen +// (022-2571): Heißt die Pretendo-ID genauso, muss sie beim Wechsel zurück zu MBMNET dort gelöst werden. +#define MBMNET_ID_FILE "sdmc:/3ds/mbmnet/mbmnet-id.txt" +static void remember_mbmnet_id(const char *id) +{ + FILE *f = fopen(MBMNET_ID_FILE, "w"); + if (f) { fputs(id, f); fclose(f); } +} +static void remembered_mbmnet_id(char *out, size_t len) +{ + out[0] = 0; + FILE *f = fopen(MBMNET_ID_FILE, "r"); + if (!f) return; + if (fgets(out, len, f)) out[strcspn(out, "\r\n")] = 0; + fclose(f); +} + +// Umschalten auf MBMNET. true = der 3DS muss jetzt neu starten. +static bool enable(bool confirmed, char *msg, size_t msglen) +{ + char detail[160] = "", id[20]; + if (patch_state() == STATE_MBMNET && frdswitch_current() == FRIEND_ACCOUNT_MBMNET) { + // Freundekonto mit fremder Kennung (z. B. von Pretendo geholt): neu anlegen, dann holt es sich + // beim nächsten Start eine Kennung bei MBMNET + u32 pid = frdswitch_my_pid(); + if (pid && !frdswitch_pid_is_mbmnet(pid)) { + if (!confirmed) { + armed = BTN_ENABLE; + snprintf(msg, msglen, "Dein MBMNET-Freundekonto hat eine fremde Kennung\n(%lu, nicht von MBMNET). Neu anlegen?\n" + "Die Verknüpfung mit deinem MBMNET-Konto bleibt.\nZum Bestätigen nochmal antippen.", (unsigned long)pid); + return false; + } + if (!frdswitch_recreate_mbmnet(msg, msglen)) return false; + snprintf(msg, msglen, "MBMNET-Freundekonto neu angelegt. Der 3DS startet neu.\n" + "Danach holt es sich bei MBMNET deinen Freundescode."); + return true; + } + bool linked = frdswitch_slot_linked(FRIEND_ACCOUNT_MBMNET, id, sizeof(id)); + snprintf(msg, msglen, linked ? "MBMNET ist schon aktiv (Konto %s)." : "MBMNET ist schon aktiv.\n" + "Jetzt dein MBMNET-Konto verknüpfen:\nEinstellungen > Nintendo Network ID", id); + return false; + } + + // Umstieg von älteren Versionen: Dort steckte die MBMNET-ID im Nintendo-Platz. Sie muss dort raus, + // sonst lässt sie sich im eigenen MBMNET-Platz nicht verknüpfen (Fehler 022-2571). + bool migrate = old_mbmnet_link() && frdswitch_slot_linked(FRIEND_ACCOUNT_NINTENDO, id, sizeof(id)); + // Die gemerkte MBMNET-ID steckt noch in einem anderen Platz (z. B. Pretendo mit gleichem Namen)? + char mbmnetId[20]; + remembered_mbmnet_id(mbmnetId, sizeof(mbmnetId)); + u8 mbmnetSlot = frdswitch_slot_of(FRIEND_ACCOUNT_MBMNET); + bool sameNameElsewhere = !migrate && mbmnetId[0] && nnid_name_elsewhere(mbmnetId, mbmnetSlot); + if (sameNameElsewhere && !confirmed) { + armed = BTN_ENABLE; + snprintf(msg, msglen, "\"%s\" ist noch in einem anderen Platz verknüpft (z. B. Pretendo).\n" + "Der 3DS erlaubt sie nur einmal: Sie wird dort gelöst, damit du sie\nbei MBMNET verknüpfen kannst. Zum Bestätigen nochmal antippen.", mbmnetId); + return false; + } + if (migrate && !confirmed) { + armed = BTN_ENABLE; + snprintf(msg, msglen, "Umstellung auf ein eigenes MBMNET-Freundekonto:\n\"%s\" wird aus dem Nintendo-Platz gelöst\n" + "und danach im MBMNET-Platz neu verknüpft.\nZum Bestätigen nochmal antippen.", id); + return false; + } + + bool changed = false; + if (!patch_enable(MBMNET_SERVER, &changed, detail, sizeof(detail))) { + snprintf(msg, msglen, "%s", detail); + return false; + } + if (migrate && !nnid_unlink(msg, msglen)) return false; + remove(UNLINKED_MARKER); + if (sameNameElsewhere && !nnid_unlink_named(mbmnetId, mbmnetSlot, msg, msglen)) { + char ignore[160]; + patch_disable(ignore, sizeof(ignore)); + return false; + } + + bool created = false; + if (!frdswitch_to(FRIEND_ACCOUNT_MBMNET, &created, msg, msglen)) { + char ignore[160]; + patch_disable(ignore, sizeof(ignore)); // nichts halb umgestellt lassen + return false; + } + bool linked = frdswitch_slot_linked(FRIEND_ACCOUNT_MBMNET, id, sizeof(id)); + char ignore[96]; + spotpass_register(MBMNET_SERVER, ignore, sizeof(ignore)); // Mitteilungen per SpotPass + snprintf(msg, msglen, "MBMNET aktiv! Der 3DS startet neu.\n%s", + created ? "Eigenes MBMNET-Freundekonto angelegt. Danach einmal:\nEinstellungen > Nintendo Network ID > Vorhandene ID" + : linked ? "Deine MBMNET-Anmeldung und -Freundesliste sind wieder da." + : "Danach einmal: Einstellungen > Nintendo Network ID"); + return true; +} + +// Zurück zu Nintendo. true = der 3DS muss jetzt neu starten. +static bool disable(bool confirmed, char *msg, size_t msglen) +{ + (void)confirmed; + char detail[160] = ""; + PatchState st = patch_state(); + if (st == STATE_ORIGINAL && frdswitch_current() == FRIEND_ACCOUNT_NINTENDO) { + snprintf(msg, msglen, "Nintendo ist schon aktiv."); + return false; + } + if (st == STATE_FOREIGN) { + snprintf(msg, msglen, "MBMNET ist nicht aktiv (anderer Patch)."); + return false; + } + // MBMNET-ID aus dem MBMNET-Platz lösen und merken: Heißt die Pretendo-ID genauso, ließe sie sich sonst + // im Pretendo-Platz nicht verknüpfen (022-2571). Beim Wechsel zurück zu MBMNET neu anmelden. + char id[20] = ""; + bool unlinked = false; + if (frdswitch_current() == FRIEND_ACCOUNT_MBMNET && nnid_linked(id, sizeof(id))) { + remember_mbmnet_id(id); + if (!nnid_unlink(msg, msglen)) return false; + unlinked = true; + } + bool created = false; + if (frdswitch_current() != FRIEND_ACCOUNT_NINTENDO && !frdswitch_to(FRIEND_ACCOUNT_NINTENDO, &created, msg, msglen)) return false; + patch_disable(detail, sizeof(detail)); + spotpass_unregister(); + if (unlinked) + snprintf(msg, msglen, "Nintendo aktiv! Der 3DS startet neu.\n\"%s\" wurde vom MBMNET-Platz gelöst (für Pretendo).\n" + "Zurück zu MBMNET: danach einmal neu anmelden.", id); + else + snprintf(msg, msglen, "Nintendo aktiv! Der 3DS startet neu.\nDeine Nintendo-Freundesliste ist wieder da."); + return true; +} + +// Führt eine Aktion aus. true = der 3DS muss jetzt neu starten. +static bool run(int action, char *msg, size_t msglen) +{ + bool confirmed = armed == action; + armed = -1; + // Während ein Update lädt oder installiert wird, nicht umschalten (der 3DS würde mittendrin neu starten) + if (action != BTN_DIAG && action != BTN_FTP && action != BTN_SPOTPASS && update_pending()) { + snprintf(msg, msglen, "Moment: Das Update auf v%s wird gerade installiert.\nDanach startet die App neu.", update_new_version()); + return false; + } + switch (action) { + case BTN_ENABLE: return enable(confirmed, msg, msglen); + case BTN_DISABLE: return disable(confirmed, msg, msglen); + case BTN_DIAG: patch_diagnose(msg, msglen); return false; + case BTN_UNLINK: { + // Verknüpfte NNID nur auf dem 3DS lösen (ohne Server) - z. B. wenn das Konto gelöscht wurde + char id[20]; + if (!nnid_linked(id, sizeof(id))) { snprintf(msg, msglen, "Hier ist keine ID verknüpft."); return false; } + if (!confirmed) { + armed = BTN_UNLINK; + snprintf(msg, msglen, "\"%s\" vom 3DS lösen?\nNur auf dem 3DS, das Konto selbst bleibt unberührt.\n" + "Zum Bestätigen nochmal antippen.", id); + return false; + } + if (!nnid_unlink(msg, msglen)) return false; + snprintf(msg, msglen, "\"%s\" gelöst. Der 3DS startet neu.\nDanach kannst du eine andere ID verknüpfen.", id); + return true; + } + case BTN_FTP: + if (ftpctl_running()) ftpctl_stop(msg, msglen); + else ftpctl_start(msg, msglen); + ftpOn = ftpctl_running(); + return false; + case BTN_SPOTPASS: + if (spotpassTestFrames >= 0) { snprintf(msg, msglen, "SpotPass-Test läuft schon ..."); return false; } + if (spotpass_test_start(MBMNET_SERVER, msg, msglen)) spotpassTestFrames = 0; + return false; + case BTN_REBOOT: return true; + } + return false; +} + +static bool inside(Box b, touchPosition tp) { return tp.px >= b.x && tp.px < b.x + b.w && tp.py >= b.y && tp.py < b.y + b.h; } + +int main(int argc, char **argv) +{ + gfxInitDefault(); + httpcInit(0); + // Als installierte CIA: am:net zum Installieren von Updates + bool am = !envIsHomebrew() && R_SUCCEEDED(amInit()); + C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); + C2D_Init(C2D_DEFAULT_MAX_OBJECTS); + C2D_Prepare(); + C3D_RenderTarget *top = C2D_CreateScreenTarget(GFX_TOP, GFX_LEFT); + C3D_RenderTarget *bot = C2D_CreateScreenTarget(GFX_BOTTOM, GFX_LEFT); + textBuf = C2D_TextBufNew(4096); + nnid_init(); + frdswitch_init(); + + const char *server = MBMNET_SERVER; + char msg[256] = ""; + + // Pfad der laufenden App (vom Homebrew Launcher übergeben), damit das Update sie ersetzen kann + const char *selfPath = argc > 0 && strncmp(argv[0], "sdmc:/", 6) == 0 ? argv[0] : "sdmc:/3ds/mbmnet.3dsx"; + update_start(server, selfPath); + UpdateState lastUpd = UPD_IDLE; + int restartIn = 0; // Frames bis zum automatischen Neustart der App nach einem Update + int rebootIn = 0; // Frames bis zum Neustart des 3DS nach dem Umschalten + + // Patches alter Versionen lagen an einer Stelle, an der Luma sie nicht lädt + if (patch_migrate()) + snprintf(msg, sizeof(msg), "Neuer Speicherort für die Patches!\nBitte MBMNET einmal neu antippen."); + PatchState st = patch_state(); + // Nur im MBMNET-Modus ist die verknüpfte NNID ein MBMNET-Konto + admin_start(server, st == STATE_MBMNET ? nnid_pid() : 0); + + // MBMNET aktiv, aber das Freundekonto hat eine fremde Kennung: darauf hinweisen + if (st == STATE_MBMNET && frdswitch_current() == FRIEND_ACCOUNT_MBMNET) { + u32 pid = frdswitch_my_pid(); + if (pid && !frdswitch_pid_is_mbmnet(pid)) + snprintf(msg, sizeof(msg), "Dein MBMNET-Freundekonto hat eine fremde Kennung (%lu).\n" + "Tippe auf MBMNET, um es neu anzulegen.", (unsigned long)pid); + } + // Mitteilungen per SpotPass: bei aktivem MBMNET die Hintergrund-Aufgabe (neu) anmelden + if (st == STATE_MBMNET) { + char ignore[96]; + spotpass_register(server, ignore, sizeof(ignore)); + // Patches auffrischen: neue Versionen bringen neue Ziele mit (z. B. Miiverse ab v2.8.0) + bool changed = false; + char detail[160]; + if (patch_enable(server, &changed, detail, sizeof(detail)) && changed && !msg[0]) + snprintf(msg, sizeof(msg), "Neue MBMNET-Patches (Miiverse) geschrieben.\n" + "Bitte den 3DS einmal neu starten (Werkzeuge: Neustart)."); + } + // Das Hintergrund-Modul ist abgeschaltet (Kernel-Absturz): Reste wegräumen, nie wieder starten + ftpctl_cleanup_module(); + ftpOn = ftpctl_running(); + int ftpCheckIn = 120; + + int selected = st == STATE_MBMNET ? BTN_DISABLE : BTN_ENABLE; + bool toolsToggled = false; + int queued = -1; // Aktion, die nach dem nächsten Bild läuft (damit sofort etwas passiert) + + while (aptMainLoop()) { + hidScanInput(); + u32 down = hidKeysDown(); + if (--ftpCheckIn <= 0) { ftpCheckIn = 120; ftpOn = ftpctl_running(); } + if (down & KEY_START && rebootIn == 0) break; // während des Umschaltens nicht abbrechen + if (down & KEY_SELECT) toolsToggled = !toolsToggled; + // Werkzeuge nur mit SELECT, beim Öffnen immer aus + bool admin = toolsToggled; + if (!admin && selected >= BTN_DIAG) selected = BTN_ENABLE; + + int action = -1; + // Oben die beiden Kacheln, unten (nur mit Werkzeugen) Diagnose / FTP / ID lösen / SpotPass / Neustart + bool left = down & (KEY_LEFT | KEY_CPAD_LEFT), right = down & (KEY_RIGHT | KEY_CPAD_RIGHT); + if (selected < BTN_DIAG) { if (left || right) selected ^= 1; } + else if (left) selected = selected == BTN_DIAG ? BTN_REBOOT : selected - 1; + else if (right) selected = selected == BTN_REBOOT ? BTN_DIAG : selected + 1; + if (admin && down & (KEY_DOWN | KEY_CPAD_DOWN) && selected < BTN_DIAG) selected = selected == BTN_ENABLE ? BTN_DIAG : BTN_REBOOT; + if (down & (KEY_UP | KEY_CPAD_UP) && selected >= BTN_DIAG) selected = selected == BTN_REBOOT ? BTN_DISABLE : BTN_ENABLE; + if (down & KEY_A) action = selected; + if (down & KEY_TOUCH) { + touchPosition tp; + hidTouchRead(&tp); + for (int i = 0; i < (admin ? BTN_COUNT : BTN_DIAG); i++) + if (inside(box_of(i, admin), tp)) selected = action = i; + } + if (queued >= 0) { + int a = queued; + queued = -1; + if (run(a, msg, sizeof(msg))) rebootIn = 45; // ca. 0,75 Sekunden zum Lesen + st = patch_state(); + } else if (action >= 0 && rebootIn == 0) { + queued = action; + snprintf(msg, sizeof(msg), action <= BTN_DISABLE ? "Schalte um ..." : "Einen Moment ..."); + } + + // Update gefunden: gleich laden, egal ob MBMNET oder Nintendo aktiv ist. Nicht während des + // Umschaltens, sonst startet der 3DS mitten in der Installation neu. + UpdateState upd = update_state(); + if (upd == UPD_AVAILABLE && rebootIn == 0 && queued < 0) { + update_download(); + snprintf(msg, sizeof(msg), "Lade Update auf v%s ...", update_new_version()); + upd = update_state(); + } + // Update fertig: kurz anzeigen, dann neu starten + if (upd == UPD_INSTALLED && lastUpd != UPD_INSTALLED) { + snprintf(msg, sizeof(msg), "Update auf v%s installiert!\nDie App startet gleich neu ...", update_new_version()); + restartIn = 90; // ca. 1,5 Sekunden + } + if (upd == UPD_ERROR && lastUpd == UPD_DOWNLOADING) { + char why[96]; + update_error(why, sizeof(why)); + snprintf(msg, sizeof(msg), "Update nach 3 Versuchen fehlgeschlagen:\n%s\nProtokoll: /3ds/mbmnet/update.log", why); + } + lastUpd = upd; + + // SpotPass-Test: jede Sekunde nachsehen + if (spotpassTestFrames >= 0 && ++spotpassTestFrames % 60 == 0 && + !spotpass_test_poll(spotpassTestFrames / 60, msg, sizeof(msg))) + spotpassTestFrames = -1; + + // Neustart erst, wenn die Freunde-Anmeldung durch ist (höchstens ein paar Sekunden) + if (rebootIn > 0 && --rebootIn == 0 && R_FAILED(APT_HardwareResetAsync())) { + snprintf(msg, sizeof(msg), "Neustart fehlgeschlagen.\nBitte den 3DS von Hand neu starten."); + } + + if (restartIn > 0 && --restartIn == 0) { + if (relaunch_prepare(selfPath)) break; + snprintf(msg, sizeof(msg), "Update installiert!\nBitte die App von Hand neu starten (START)."); + } + + C2D_TextBufClear(textBuf); + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + C2D_TargetClear(top, COL_BG); + C2D_SceneBegin(top); + draw_top(st, msg, admin, admin_is()); + C2D_TargetClear(bot, COL_BG); + C2D_SceneBegin(bot); + draw_bottom(selected, st, admin); + C3D_FrameEnd(0); + } + + ftpctl_stop(NULL, 0); + admin_finish(); + update_finish(); + frdswitch_exit(); + nnid_exit(); + httpcExit(); + if (am) amExit(); + C2D_TextBufDelete(textBuf); + C2D_Fini(); + C3D_Fini(); + gfxExit(); + return 0; +} diff --git a/source/nnid.c b/source/nnid.c new file mode 100644 index 0000000..21224bd --- /dev/null +++ b/source/nnid.c @@ -0,0 +1,217 @@ +// Nintendo Network ID auf dem 3DS: anzeigen und lokal lösen. +// +// Solange eine NNID verknüpft ist, bieten die Systemeinstellungen kein +// "Vorhandene ID verknüpfen" an. Damit man sich mit dem MBMNET-Konto anmelden kann, +// löst die App die Verknüpfung lokal (ohne Server). Name und PID der alten ID werden +// vorher in /3ds/mbmnet/alte-nnid.txt gesichert. +#include <3ds.h> +#include +#include +#include +#include +#include + +#include "nnid.h" + +#define OLD_NNID_FILE "sdmc:/3ds/mbmnet/alte-nnid.txt" +#define LOG_FILE "sdmc:/3ds/mbmnet/konto.log" + +static bool ready; + +Result nnid_init(void) +{ + Result rc = actInit(false); // false = act:a (Verwaltung) + ready = R_SUCCEEDED(rc); + return rc; +} + +void nnid_exit(void) +{ + if (ready) actExit(); +} + +static u8 current_slot(void) +{ + u8 slot = 0; + ACT_GetCommonInfo(&slot, sizeof(slot), INFO_TYPE_COMMON_CURRENT_ACCOUNT_SLOT); + return slot; +} + +bool nnid_linked(char *name, size_t len) +{ + name[0] = 0; + if (!ready) return false; + AccountId id = { 0 }; + if (R_FAILED(ACT_GetAccountInfo(id, sizeof(id), current_slot(), INFO_TYPE_ACCOUNT_ID))) return false; + snprintf(name, len, "%s", id); + return name[0] != 0; +} + +u32 nnid_pid(void) +{ + u32 pid = 0; + char name[20]; + if (nnid_linked(name, sizeof(name))) ACT_GetAccountInfo(&pid, sizeof(pid), current_slot(), INFO_TYPE_PRINCIPAL_ID); + return pid; +} + +// Verknüpfte IDs in ANDEREN Konto-Plätzen (z. B. die Pretendo-ID aus Nimbus' zweitem Platz). +// Eine ID, die dort steht, darf der 3DS nicht noch einmal verknüpfen (Fehler 022-2571). +int nnid_others(char *names, size_t len) +{ + names[0] = 0; + if (!ready) return 0; + u8 count = 0, current = current_slot(); + if (R_FAILED(ACT_GetCommonInfo(&count, sizeof(count), INFO_TYPE_COMMON_NUM_ACCOUNTS))) return 0; + int found = 0; + for (u8 slot = 1; slot <= count; slot++) { + if (slot == current) continue; + AccountId id = { 0 }; + if (R_FAILED(ACT_GetAccountInfo(id, sizeof(id), slot, INFO_TYPE_ACCOUNT_ID)) || !id[0]) continue; + size_t n = strlen(names); + snprintf(names + n, len - n, "%s\"%s\"", found ? ", " : "", id); + found++; + } + return found; +} + +bool nnid_unlink_others(char *msg, size_t msglen) +{ + if (!ready) return false; + u8 count = 0, current = current_slot(); + if (R_FAILED(ACT_GetCommonInfo(&count, sizeof(count), INFO_TYPE_COMMON_NUM_ACCOUNTS))) return false; + + mkdir("sdmc:/3ds/mbmnet", 0777); + FILE *log = fopen(LOG_FILE, "a"); + FILE *old = fopen(OLD_NNID_FILE, "a"); + bool ok = true; + for (u8 slot = 1; slot <= count; slot++) { + if (slot == current) continue; + AccountId id = { 0 }; + u32 pid = 0; + if (R_FAILED(ACT_GetAccountInfo(id, sizeof(id), slot, INFO_TYPE_ACCOUNT_ID)) || !id[0]) continue; + ACT_GetAccountInfo(&pid, sizeof(pid), slot, INFO_TYPE_PRINCIPAL_ID); + if (old) fprintf(old, "Konto-Platz %u ID: %s PID: %lu (anderer Platz, z. B. Pretendo)\n", slot, id, (unsigned long)pid); + Result rc = ACTA_UnbindServerAccount(slot, true); + if (log) fprintf(log, "Platz %u (%s) lösen %08lX\n", slot, id, (unsigned long)rc); + if (R_FAILED(rc)) { + snprintf(msg, msglen, "ID \"%s\" (Platz %u) konnte nicht gelöst werden\n(Fehler %08lX).", id, slot, (unsigned long)rc); + ok = false; + } + } + if (old) fclose(old); + if (log) fclose(log); + return ok; +} + +bool nnid_unlink(char *msg, size_t msglen) +{ + if (!ready) { + snprintf(msg, msglen, "Kontodienst nicht verfügbar.\nIst Luma3DS aktuell?"); + return false; + } + u8 slot = current_slot(); + AccountId id = { 0 }; + u32 pid = 0; + ACT_GetAccountInfo(id, sizeof(id), slot, INFO_TYPE_ACCOUNT_ID); + ACT_GetAccountInfo(&pid, sizeof(pid), slot, INFO_TYPE_PRINCIPAL_ID); + if (!id[0]) return true; // nichts verknüpft + + mkdir("sdmc:/3ds/mbmnet", 0777); + + // Alte ID merken, damit der Name nicht verloren geht + FILE *f = fopen(OLD_NNID_FILE, "a"); + if (f) { + time_t now = time(NULL); + char date[32]; + strftime(date, sizeof(date), "%Y-%m-%d %H:%M", localtime(&now)); + fprintf(f, "%s Konto-Platz %u NNID: %s PID: %lu\n", date, slot, id, (unsigned long)pid); + fclose(f); + } + + FILE *log = fopen(LOG_FILE, "w"); + if (log) fprintf(log, "MBMNET: NNID lösen (App v%s)\nKonto-Platz %u, NNID %s\n\n", APP_VERSION, slot, id); + + Result rc = ACTA_UnbindServerAccount(slot, true); + if (log) fprintf(log, "%-30s %08lX\n", "Verknüpfung lösen", (unsigned long)rc); + if (R_FAILED(rc)) { + // Manche Zustände erlauben das nur bei abgemeldetem Konto: abmelden und erneut versuchen + Result u = ACTA_UnloadConsoleAccount(); + if (log) fprintf(log, "%-30s %08lX\n", "Konto abmelden", (unsigned long)u); + rc = ACTA_UnbindServerAccount(slot, true); + if (log) fprintf(log, "%-30s %08lX\n", "Verknüpfung lösen (2.)", (unsigned long)rc); + } + if (log) { fprintf(log, "\nErgebnis: %s\n", R_SUCCEEDED(rc) ? "OK" : "FEHLER"); fclose(log); } + + if (R_FAILED(rc)) { + snprintf(msg, msglen, "NNID konnte nicht gelöst werden (Fehler %08lX).\nProtokoll: /3ds/mbmnet/konto.log", (unsigned long)rc); + return false; + } + return true; +} + +// Für die Diagnose: alle Konto-Plätze mit ihren Daten +void nnid_dump(FILE *f) +{ + if (!ready) { fprintf(f, " Kontodienst nicht verfügbar\n"); return; } + u8 count = 0, current = 0, def = 0; + ACT_GetCommonInfo(&count, sizeof(count), INFO_TYPE_COMMON_NUM_ACCOUNTS); + ACT_GetCommonInfo(¤t, sizeof(current), INFO_TYPE_COMMON_CURRENT_ACCOUNT_SLOT); + ACT_GetCommonInfo(&def, sizeof(def), INFO_TYPE_COMMON_DEFAULT_ACCOUNT_SLOT); + u8 friendAccount = 0; + FRD_GetMyLocalAccountId(&friendAccount); + fprintf(f, " %u Plätze, aktiv: %u, Standard: %u, geladenes Freundekonto: %u (1 = Nintendo, 3 = MBMNET)\n", + count, current, def, friendAccount); + for (u8 slot = 1; slot <= count; slot++) { + AccountId id = { 0 }, assigned = { 0 }; + u32 pid = 0, assignedPid = 0; + u8 fp = 0; + bool committed = false; + Result r1 = ACT_GetAccountInfo(id, sizeof(id), slot, INFO_TYPE_ACCOUNT_ID); + ACT_GetAccountInfo(assigned, sizeof(assigned), slot, INFO_TYPE_ASSIGNED_ACCOUNT_ID); + ACT_GetAccountInfo(&pid, sizeof(pid), slot, INFO_TYPE_PRINCIPAL_ID); + ACT_GetAccountInfo(&assignedPid, sizeof(assignedPid), slot, INFO_TYPE_ASSIGNED_PRINCIPAL_ID); + ACT_GetAccountInfo(&fp, sizeof(fp), slot, INFO_TYPE_FP_LOCAL_ACCOUNT_ID); + ACT_GetAccountInfo(&committed, sizeof(committed), slot, INFO_TYPE_IS_COMMITTED); + fprintf(f, " Platz %u: ID \"%s\" (Länge %u, Abfrage %08lX) PID %lu zugewiesen \"%s\"/%lu Freunde-Konto %u gespeichert %d\n", + slot, id, (unsigned)strlen(id), (unsigned long)r1, (unsigned long)pid, assigned, + (unsigned long)assignedPid, fp, committed); + } +} + +// Gibt es die ID "name" in einem Konto-Platz außer exceptSlot? +bool nnid_name_elsewhere(const char *name, u8 exceptSlot) +{ + if (!ready || !name[0]) return false; + u8 count = 0; + if (R_FAILED(ACT_GetCommonInfo(&count, sizeof(count), INFO_TYPE_COMMON_NUM_ACCOUNTS))) return false; + for (u8 slot = 1; slot <= count; slot++) { + if (slot == exceptSlot) continue; + AccountId id = { 0 }; + if (R_SUCCEEDED(ACT_GetAccountInfo(id, sizeof(id), slot, INFO_TYPE_ACCOUNT_ID)) && !strcasecmp(id, name)) return true; + } + return false; +} + +// Löst die ID "name" in allen Konto-Plätzen außer exceptSlot (nur auf dem 3DS). false + msg bei Fehler. +bool nnid_unlink_named(const char *name, u8 exceptSlot, char *msg, size_t msglen) +{ + if (!ready) return false; + u8 count = 0; + if (R_FAILED(ACT_GetCommonInfo(&count, sizeof(count), INFO_TYPE_COMMON_NUM_ACCOUNTS))) return false; + FILE *log = fopen(LOG_FILE, "a"); + bool ok = true; + for (u8 slot = 1; slot <= count; slot++) { + if (slot == exceptSlot) continue; + AccountId id = { 0 }; + if (R_FAILED(ACT_GetAccountInfo(id, sizeof(id), slot, INFO_TYPE_ACCOUNT_ID)) || strcasecmp(id, name)) continue; + Result rc = ACTA_UnbindServerAccount(slot, true); + if (log) fprintf(log, "Platz %u (%s) lösen (gleicher Name wie MBMNET) %08lX\n", slot, id, (unsigned long)rc); + if (R_FAILED(rc)) { + snprintf(msg, msglen, "\"%s\" (Platz %u) ließ sich nicht lösen (Fehler %08lX).", id, slot, (unsigned long)rc); + ok = false; + } + } + if (log) fclose(log); + return ok; +} diff --git a/source/nnid.h b/source/nnid.h new file mode 100644 index 0000000..43d8977 --- /dev/null +++ b/source/nnid.h @@ -0,0 +1,23 @@ +#pragma once +#include <3ds/types.h> +#include +#include + +Result nnid_init(void); +void nnid_exit(void); +// true, wenn auf dem aktuellen Konto eine NNID verknüpft ist (Name in name) +bool nnid_linked(char *name, size_t len); +// PID der verknüpften NNID (0 = keine) +u32 nnid_pid(void); +// IDs, die in ANDEREN Konto-Plätzen verknüpft sind (z. B. Pretendo). Anzahl, Namen in names. +int nnid_others(char *names, size_t len); +// Löst diese IDs lokal (Namen werden in /3ds/mbmnet/alte-nnid.txt gesichert) +bool nnid_unlink_others(char *msg, size_t msglen); +// Löst die verknüpfte NNID lokal (Name/PID werden in /3ds/mbmnet/alte-nnid.txt gesichert) +bool nnid_unlink(char *msg, size_t msglen); +// Gibt es die ID "name" in einem Konto-Platz außer exceptSlot? +bool nnid_name_elsewhere(const char *name, u8 exceptSlot); +// Löst die ID "name" in allen Konto-Plätzen außer exceptSlot (nur auf dem 3DS) +bool nnid_unlink_named(const char *name, u8 exceptSlot, char *msg, size_t msglen); +// Schreibt alle Konto-Plätze in die Diagnose +void nnid_dump(FILE *f); diff --git a/source/olvpatch.c b/source/olvpatch.c new file mode 100644 index 0000000..bac27cb --- /dev/null +++ b/source/olvpatch.c @@ -0,0 +1,109 @@ +// Miiverse-Patch: leitet die Miiverse-App auf MBMNET um und lässt sie der MBMNET-Zertifizierungsstelle (CA) +// vertrauen, denn ihre Seiten lädt sie nur per HTTPS. +// +// Die Code-Änderungen stammen aus Pretendos Nimbus (patches/miiverse, GPLv3, nach Stary und Sono): mit armips +// übersetzt, statt Pretendos Discovery-Adresse und GlobalSign-Zertifikat kommen MBMNET-Adresse und -CA hinein. +// Sie gelten für die letzte Version der Miiverse-App (alle Regionen gleich). Vorher wird geprüft, dass die +// Nintendo-Discovery-Adresse genau an der erwarteten Stelle steht - sonst wird nichts gepatcht. +// +// 0x176F28 fügt der HTTP-Verbindung die CA hinzu (httpC:AddRootCA), Länge der CA an Byte 72 +// 0x1D7FF8 / 0x1D80EC / 0x38DC30 SD-Karte zusätzlich einhängen und wieder aushängen +// 0x1E3224 / 0x1E3468 der Browser lädt seine CA aus sdmc:/3ds/mbmnet-ca.pem +// 0x38DCB0 die CA selbst (DER, höchstens 889 Bytes) +#include <3ds.h> +#include +#include + +#include "olvpatch.h" + +#define CODE_BASE 0x100000 +#define DISCOVERY_ADDR 0x15748C +#define DISCOVERY_URL "https://discovery.olv.nintendo.net/v1/endpoint" +#define CA_ADDR 0x38DCB0 +#define CA_MAX 889 +#define CA_PEM_FILE "sdmc:/3ds/mbmnet-ca.pem" + +static const u8 olv_176F28[] = { 0x3C, 0x00, 0x9F, 0xE5, 0x70, 0x4F, 0x1D, 0xEE, 0x0C, 0x10, 0x95, 0xE5, 0x14, 0x80, 0x95, 0xE5, 0x80, 0x00, 0xA4, 0xE5, 0x04, 0x10, 0x84, 0xE5, 0x08, 0x00, 0xA0, 0xE1, 0x24, 0x80, 0x9F, 0xE5, 0x24, 0x10, 0x9F, 0xE5, 0x08, 0x80, 0x84, 0xE5, 0x10, 0x10, 0x84, 0xE5, 0x08, 0x82, 0xA0, 0xE1, 0x0A, 0x80, 0x88, 0xE3, 0x0C, 0x80, 0x84, 0xE5, 0x32, 0x00, 0x00, 0xEF, 0x00, 0x00, 0xA0, 0xE1, 0x08, 0x00, 0x00, 0xEA, 0x82, 0x00, 0x24, 0x00, 0x79, 0x03, 0x00, 0x00, 0xB0, 0xDC, 0x38, 0x00, 0x00, 0x00, 0xA0, 0xE1, 0x00, 0x00, 0xA0, 0xE1, 0x00, 0x00, 0xA0, 0xE1 }; +static const u8 olv_1D7FF8[] = { 0x0C, 0xD7, 0x06, 0xEA }; +static const u8 olv_1D80EC[] = { 0xD4, 0xD6, 0x06, 0xEA }; +static const u8 olv_1E3224[] = { 0x01, 0x20, 0xA0, 0xE3 }; +static const u8 olv_1E3468[] = "3ds/mbmnet-ca.pem"; // mit Nullbyte: 18 Bytes +static const u8 olv_38DC30[] = { 0x00, 0x40, 0x2D, 0xE9, 0x2E, 0x28, 0xF9, 0xEB, 0x18, 0x00, 0x9F, 0xE5, 0x00, 0x40, 0xBD, 0xE8, 0xB6, 0x93, 0xF8, 0xEA, 0x00, 0x40, 0x2D, 0xE9, 0x02, 0x29, 0xF9, 0xEB, 0x04, 0x00, 0x9F, 0xE5, 0x00, 0x40, 0xBD, 0xE8, 0xBB, 0x92, 0xFA, 0xEA, 0x9C, 0x81, 0x1D, 0x00 }; +#define CA_LEN_BYTE 72 // in olv_176F28: Länge der CA (Literal-Pool) + +// Lädt eine Datei vom MBMNET-Server. Gibt die Länge zurück, 0 bei Fehler. +static u32 fetch(const char *server, const char *path, u8 *buf, u32 cap) +{ + char url[160]; + snprintf(url, sizeof(url), "http://%s%s", server, path); + httpcContext ctx; + if (R_FAILED(httpcOpenContext(&ctx, HTTPC_METHOD_GET, url, 1))) return 0; + httpcAddRequestHeaderField(&ctx, "User-Agent", "MBMNET-Switcher/" APP_VERSION); + u32 status = 0, got = 0; + Result rc = httpcBeginRequest(&ctx); + if (R_SUCCEEDED(rc)) rc = httpcGetResponseStatusCodeTimeout(&ctx, &status, 8ULL * 1000 * 1000 * 1000); + if (R_SUCCEEDED(rc) && status == 200) rc = httpcDownloadData(&ctx, buf, cap, &got); + httpcCloseContext(&ctx); + return R_SUCCEEDED(rc) && status == 200 && got < cap ? got : 0; +} + +bool olvpatch_fetch_ca(const char *server, u8 *der, u32 *derLen) +{ + static u8 pem[2048]; + u32 n = fetch(server, "/olv/ca.der", der, CA_MAX + 1); + if (n == 0 || n > CA_MAX) return false; + u32 p = fetch(server, "/olv/ca.pem", pem, sizeof(pem)); + if (p == 0) return false; + // Der Browser der Miiverse-App liest die CA von der SD-Karte + FILE *f = fopen(CA_PEM_FILE, "wb"); + bool ok = f && fwrite(pem, 1, p, f) == p; + if (f) fclose(f); + *derLen = n; + return ok; +} + +bool olvpatch_supported(const u8 *code, u32 size) +{ + u32 off = DISCOVERY_ADDR - CODE_BASE; + return off + sizeof(DISCOVERY_URL) <= size && memcmp(code + off, DISCOVERY_URL, sizeof(DISCOVERY_URL)) == 0; +} + +static u32 ips_record(u8 *out, u32 n, u32 cap, u32 addr, const u8 *data, u32 len) +{ + if (n + 5 + len + 3 > cap) return 0; + u32 off = addr - CODE_BASE; + u8 head[5] = { off >> 16, off >> 8, off, len >> 8, len }; + memcpy(out + n, head, 5); + memcpy(out + n + 5, data, len); + return n + 5 + len; +} + +u32 olvpatch_build(const char *server, const u8 *der, u32 derLen, u8 *out, u32 cap) +{ + // Discovery: "https://discovery.olv.nintendo.net/v1/endpoint" -> "http:///v1/endpoint", Rest Nullbytes + u8 discovery[sizeof(DISCOVERY_URL)] = { 0 }; + int len = snprintf((char *)discovery, sizeof(discovery), "http://%s/v1/endpoint", server); + if (len <= 0 || len >= (int)sizeof(discovery) || derLen == 0 || derLen > CA_MAX) return 0; + + u8 caHook[sizeof(olv_176F28)]; + memcpy(caHook, olv_176F28, sizeof(caHook)); + caHook[CA_LEN_BYTE] = derLen; + caHook[CA_LEN_BYTE + 1] = derLen >> 8; + + u32 n = 5; + memcpy(out, "PATCH", 5); + struct { u32 addr; const u8 *data; u32 len; } recs[] = { + { DISCOVERY_ADDR, discovery, sizeof(discovery) }, + { 0x176F28, caHook, sizeof(caHook) }, + { 0x1D7FF8, olv_1D7FF8, sizeof(olv_1D7FF8) }, + { 0x1D80EC, olv_1D80EC, sizeof(olv_1D80EC) }, + { 0x1E3224, olv_1E3224, sizeof(olv_1E3224) }, + { 0x1E3468, olv_1E3468, sizeof(olv_1E3468) }, + { 0x38DC30, olv_38DC30, sizeof(olv_38DC30) }, + { CA_ADDR, der, derLen }, + }; + for (size_t i = 0; i < sizeof(recs) / sizeof(recs[0]); i++) + if (!(n = ips_record(out, n, cap, recs[i].addr, recs[i].data, recs[i].len))) return 0; + memcpy(out + n, "EOF", 3); + return n + 3; +} diff --git a/source/olvpatch.h b/source/olvpatch.h new file mode 100644 index 0000000..e7a9c12 --- /dev/null +++ b/source/olvpatch.h @@ -0,0 +1,11 @@ +#pragma once +#include <3ds/types.h> + +// Miiverse-Patch (siehe olvpatch.c). Die CA kommt vom MBMNET-Server (/olv/ca.der, /olv/ca.pem). + +// Holt die MBMNET-CA (DER, höchstens 889 Bytes) und legt die PEM-Fassung für den Browser auf die SD. +bool olvpatch_fetch_ca(const char *server, u8 *der, u32 *derLen); +// Ist das genau die Miiverse-Version, für die der Patch gebaut ist? (entpackter .code) +bool olvpatch_supported(const u8 *code, u32 size); +// Baut den IPS-Patch. Gibt die Länge zurück, 0 bei Fehler. +u32 olvpatch_build(const char *server, const u8 *der, u32 derLen, u8 *out, u32 cap); diff --git a/source/patcher.c b/source/patcher.c new file mode 100644 index 0000000..6a5398a --- /dev/null +++ b/source/patcher.c @@ -0,0 +1,885 @@ +// Erzeugt und verwaltet die MBMNET-Patches. +// +// Gepatcht werden zwei Systemmodule: +// Freunde (0004013000003202): https://nasc.nintendowifi.net -> http:// +// Konto (0004013000003802): https://account.nintendo.net -> http:// +// +// Ablauf je Modul: +// 1. .code lesen (direkt aus dem NAND, sonst aus einem Dump auf der SD) +// 2. falls komprimiert: entpacken (Luma patcht die entpackte Version) +// 3. alle Nintendo-Adressen suchen und durch die MBMNET-Adresse ersetzen +// 4. als IPS-Patch nach /luma/titles//code.ips schreiben +// +// Am NAND wird nie etwas verändert. Luma3DS wendet die Patches nur beim Laden an. +#include <3ds.h> +#include +#include +#include +#include +#include + +#include "blz.h" +#include "patcher.h" +#include "lumaconfig.h" +#include "olvpatch.h" +#include "nnid.h" + +#define SYSMODULE_DIR "sdmc:/luma/sysmodules" + +#define MAX_HITS 8 + +// Boot-Splash: Luma zeigt beim Einschalten "MBMNET aktiv" (Bild in splash_data.c) +#define SPLASH_FILE "sdmc:/luma/splash.bin" +#define SPLASH_BACKUP "sdmc:/luma/splash.bin.vor-mbmnet" +#define SPLASH_SIZE (400 * 240 * 3) + +// Zwischenspeicher: fertige Patches und der Splash. Damit ist Umschalten nur noch Umbenennen und +// zwei kleine Dateien schreiben, statt die Module aus dem NAND zu lesen, zu entpacken und zu durchsuchen. +// Ein Patch gilt nur, solange Modul (Größe + Ende der .code), Server und Regeln gleich sind. +#define CACHE_DIR APP_DIR "/cache" +#define SPLASH_CACHE CACHE_DIR "/splash-" APP_VERSION ".bin" +#define RULES_VERSION "1" +extern const u8 splash_rle[]; +extern const u32 splash_rle_size; + +// Eine Ersetzungsregel. Es gibt zwei Arten: +// PREFIX: Text beginnt mit needle -> needle wird zu "http://", der Rest bleibt +// ("https://nasc.nintendowifi.net/ac" -> "http:///ac") +// EXACT: Text ist genau needle -> wird zu "http://" + suffix +// (für Vorlagen mit Platzhaltern, deren Werte der 3DS dann ins Leere schreibt) +typedef enum { RULE_PREFIX, RULE_EXACT } RuleType; + +typedef struct { + RuleType type; + const char *needle; + const char *suffix; // nur EXACT +} Rule; + +#define MAX_RULES 2 + +typedef struct { + u64 tid; + const char *dir; // Luma-Ordner für dieses Modul + const char *label; // Name für Meldungen + Rule rules[MAX_RULES]; + bool optional; // Anwendung statt Systemmodul: nur patchen, wenn installiert und Adresse gefunden +} Target; + +#define TITLES_DIR "sdmc:/luma/titles" + +// Umgelenkt wird die normale Nintendo-Umgebung: Alles, was der 3DS sonst zu +// nasc.nintendowifi.net und account.nintendo.net schickt, geht an MBMNET. +static const Target targets[] = { + { 0x0004013000003202ULL, SYSMODULE_DIR, "Freunde", { + { RULE_PREFIX, "https://nasc.nintendowifi.net" }, + } }, + { 0x0004013000003802ULL, SYSMODULE_DIR, "Konto", { + // Aktuelle Firmware: die beiden %s sind Zusätze für Nintendos Test-Server (sonst leer), + // %u ist die API-Version (immer 1). + { RULE_EXACT, "https://%s%saccount.nintendo.net/v%u/api/", "/v1/api/" }, + { RULE_PREFIX, "https://account.nintendo.net" }, + } }, + // Miiverse (JPN, USA, EUR): fragt zuerst den Discovery-Server, wohin es geht, und lädt dann seine Seiten + // per HTTPS. Gebaut wird der Patch in olvpatch.c (die Regel hier dient nur der Diagnose). Nur die + // installierte Region wird gepatcht. Luma lädt Patches für Anwendungen aus /luma/titles//code.ips (wie Nimbus). + { 0x000400300000BC02ULL, TITLES_DIR, "Miiverse", { { RULE_PREFIX, "https://discovery.olv.nintendo.net" } }, true }, + { 0x000400300000BD02ULL, TITLES_DIR, "Miiverse", { { RULE_PREFIX, "https://discovery.olv.nintendo.net" } }, true }, + { 0x000400300000BE02ULL, TITLES_DIR, "Miiverse", { { RULE_PREFIX, "https://discovery.olv.nintendo.net" } }, true }, +}; +#define TARGET_COUNT (sizeof(targets) / sizeof(targets[0])) + +typedef struct { + u32 offset; + u32 size; // Anzahl Bytes, die geschrieben werden + u8 data[160]; +} Hit; + +typedef struct { + Hit hits[MAX_HITS]; + int count; +} Patch; + +// --- Dateien --------------------------------------------------------------------- + +static bool file_exists(const char *path) +{ + struct stat st; + return stat(path, &st) == 0; +} + +// Luma3DS lädt IPS-Patches für Systemmodule aus /luma/sysmodules/.ips +// (nur wenn "Enable loading external FIRMs and system modules" an ist). +// Daneben legen wir einen Merker .mbmnet und ggf. die Sicherung eines fremden Patches ab. +static void path_in(char *out, size_t len, const Target *t, const char *file) +{ + // Anwendungen: /luma/titles//code.ips (+ mbmnet.txt, code.ips.vor-mbmnet) + if (strcmp(t->dir, TITLES_DIR) == 0) { + snprintf(out, len, "%s/%016llX/%s", t->dir, t->tid, file); + return; + } + const char *ext = strcmp(file, "code.ips") == 0 ? ".ips" + : strcmp(file, "mbmnet.txt") == 0 ? ".mbmnet" + : ".ips.vor-mbmnet"; + snprintf(out, len, "%s/%016llX%s", t->dir, t->tid, ext); +} + +// Bis v2.2.0 lagen die Patches unter /luma/titles//code.ips - dort wendet Luma sie für +// Systemmodule aber nicht an. Alte Dateien entfernen und gesicherte fremde Patches zurückholen. +bool patch_migrate(void) +{ + bool migrated = false; + for (size_t i = 0; i < TARGET_COUNT; i++) { + if (targets[i].optional) continue; // Anwendungen gehören nach /luma/titles + char dir[64], ips[96], marker[96], backup[96]; + snprintf(dir, sizeof(dir), "sdmc:/luma/titles/%016llX", targets[i].tid); + snprintf(ips, sizeof(ips), "%s/code.ips", dir); + snprintf(marker, sizeof(marker), "%s/mbmnet.txt", dir); + snprintf(backup, sizeof(backup), "%s/code.ips.vor-mbmnet", dir); + if (!file_exists(marker)) continue; + remove(ips); + remove(marker); + if (file_exists(backup)) rename(backup, ips); + migrated = true; + } + return migrated; +} + +static void mkdirs(const char *path) +{ + char tmp[256]; + snprintf(tmp, sizeof(tmp), "%s", path); + for (char *p = tmp + strlen("sdmc:/"); *p; p++) { + if (*p == '/') { + *p = 0; + mkdir(tmp, 0777); + *p = '/'; + } + } + mkdir(tmp, 0777); +} + +PatchState patch_state(void) +{ + char path[128]; + bool foreign = false; + for (size_t i = 0; i < TARGET_COUNT; i++) { + path_in(path, sizeof(path), &targets[i], "mbmnet.txt"); + if (file_exists(path)) return STATE_MBMNET; + path_in(path, sizeof(path), &targets[i], "code.ips"); + if (!targets[i].optional && file_exists(path)) foreign = true; + } + return foreign ? STATE_FOREIGN : STATE_ORIGINAL; +} + +// --- .code lesen ------------------------------------------------------------ + +static Result read_from_nand(u64 tid, u8 **out, u32 *outSize) +{ + u32 archPath[4] = { (u32)tid, (u32)(tid >> 32), MEDIATYPE_NAND, 0 }; + // ExeFS-Datei ".code" + static const u32 filePath[5] = { 0, 0, 2, 0x646F632E, 0x00000065 }; + FS_Path arch = { PATH_BINARY, sizeof(archPath), archPath }; + FS_Path file = { PATH_BINARY, sizeof(filePath), filePath }; + + Handle h; + Result rc = FSUSER_OpenFileDirectly(&h, ARCHIVE_SAVEDATA_AND_CONTENT, arch, file, FS_OPEN_READ, 0); + if (R_FAILED(rc)) return rc; + + u64 size = 0; + rc = FSFILE_GetSize(h, &size); + if (R_SUCCEEDED(rc)) { + u8 *buf = malloc(size); + u32 read = 0; + if (!buf) rc = -1; + else rc = FSFILE_Read(h, &read, 0, buf, size); + if (R_SUCCEEDED(rc)) { *out = buf; *outSize = read; } + else free(buf); + } + FSFILE_Close(h); + return rc; +} + +// Ersatzweise ein Dump von der SD: /3ds/mbmnet/.bin +static bool read_from_sd(u64 tid, u8 **out, u32 *outSize) +{ + char path[64]; + snprintf(path, sizeof(path), APP_DIR "/%016llX.bin", tid); + FILE *f = fopen(path, "rb"); + if (!f) return false; + fseek(f, 0, SEEK_END); + long size = ftell(f); + fseek(f, 0, SEEK_SET); + u8 *buf = size > 0 ? malloc(size) : NULL; + bool ok = buf && fread(buf, 1, size, f) == (size_t)size; + fclose(f); + if (!ok) { free(buf); return false; } + *out = buf; + *outSize = size; + return true; +} + +static bool load_code(const Target *t, u8 **out, u32 *outSize, char *msg, size_t msglen) +{ + u8 *buf = NULL; + u32 size = 0; + Result rc = read_from_nand(t->tid, &buf, &size); + if (R_FAILED(rc) && t->optional) return false; // nicht installiert (andere Region) + if (R_FAILED(rc) && !read_from_sd(t->tid, &buf, &size)) { + snprintf(msg, msglen, + "%s-Modul nicht lesbar (Fehler %08lX).\n" + "Lege einen Dump als /3ds/mbmnet/%016llX.bin\nab (siehe Anleitung).", + t->label, (unsigned long)rc, t->tid); + return false; + } + + if (blz_looks_compressed(buf, size)) { + u32 full = blz_decompressed_size(buf, size); + u8 *big = realloc(buf, full); + if (!big) { free(buf); snprintf(msg, msglen, "Zu wenig Speicher."); return false; } + buf = big; + if (!blz_decompress(buf, size)) { + free(buf); + snprintf(msg, msglen, "%s-Modul konnte nicht entpackt werden.", t->label); + return false; + } + size = full; + } + + *out = buf; + *outSize = size; + return true; +} + +// --- Zwischenspeicher ------------------------------------------------------------ + +// Fingerabdruck des Moduls ohne es ganz zu lesen: Größe und die letzten 16 Bytes der .code +// (bei komprimierten Modulen stehen dort die Entpack-Angaben). Leer, wenn nicht lesbar. +static void fingerprint(u64 tid, char *out, size_t len) +{ + u32 archPath[4] = { (u32)tid, (u32)(tid >> 32), MEDIATYPE_NAND, 0 }; + static const u32 filePath[5] = { 0, 0, 2, 0x646F632E, 0x00000065 }; + out[0] = 0; + Handle h; + if (R_FAILED(FSUSER_OpenFileDirectly(&h, ARCHIVE_SAVEDATA_AND_CONTENT, (FS_Path){ PATH_BINARY, sizeof(archPath), archPath }, + (FS_Path){ PATH_BINARY, sizeof(filePath), filePath }, FS_OPEN_READ, 0))) return; + u64 size = 0; + static u8 block[0x400]; + u32 got = 0; + // Nur ab einer 0x200-Grenze lesen: Ein Lesen mitten im Block (Ende - 16) scheitert bei diesen Dateien + u64 start = size; + if (R_SUCCEEDED(FSFILE_GetSize(h, &size)) && size >= 16) { + start = (size - 16) & ~0x1FFULL; + if (R_SUCCEEDED(FSFILE_Read(h, &got, start, block, (u32)(size - start))) && got == size - start) { + const u8 *tail = block + got - 16; + int n = snprintf(out, len, "%llX-", size); + for (int i = 0; i < 16 && n + 2 < (int)len; i++) n += snprintf(out + n, len - n, "%02X", tail[i]); + } + } + FSFILE_Close(h); +} + +static void cache_key(const Target *t, const char *server, char *out, size_t len) +{ + char fp[64]; + fingerprint(t->tid, fp, sizeof(fp)); + if (fp[0]) snprintf(out, len, "%s|%s|" RULES_VERSION, fp, server); + else out[0] = 0; +} + +static u32 cache_load(const Target *t, const char *key, u8 *data, u32 cap) +{ + char path[96], stored[160] = ""; + if (!key[0]) return 0; + snprintf(path, sizeof(path), CACHE_DIR "/%016llX.key", t->tid); + FILE *f = fopen(path, "r"); + if (!f) return 0; + if (!fgets(stored, sizeof(stored), f)) stored[0] = 0; + fclose(f); + stored[strcspn(stored, "\r\n")] = 0; + if (strcmp(stored, key)) return 0; + + snprintf(path, sizeof(path), CACHE_DIR "/%016llX.ips", t->tid); + f = fopen(path, "rb"); + u32 n = f ? fread(data, 1, cap, f) : 0; + if (f) fclose(f); + return n > 8 && !memcmp(data, "PATCH", 5) && !memcmp(data + n - 3, "EOF", 3) ? n : 0; +} + +static void cache_store(const Target *t, const char *key, const u8 *data, u32 n) +{ + char path[96]; + if (!key[0]) return; + mkdir(APP_DIR, 0777); + mkdir(CACHE_DIR, 0777); + snprintf(path, sizeof(path), CACHE_DIR "/%016llX.ips", t->tid); + FILE *f = fopen(path, "wb"); + bool ok = f && fwrite(data, 1, n, f) == n; + if (f) fclose(f); + snprintf(path, sizeof(path), CACHE_DIR "/%016llX.key", t->tid); + f = ok ? fopen(path, "w") : NULL; + if (f) { fprintf(f, "%s\n", key); fclose(f); } +} + +// --- Patch berechnen und schreiben ---------------------------------------------- + +static bool build_patch(const Target *t, const char *server, Patch *p, char *msg, size_t msglen) +{ + u8 *code; + u32 size; + if (!load_code(t, &code, &size, msg, msglen)) return false; + + p->count = 0; + + for (u32 i = 0; i < size && p->count < MAX_HITS; i++) { + for (int r = 0; r < MAX_RULES && t->rules[r].needle; r++) { + const Rule *rule = &t->rules[r]; + size_t needleLen = strlen(rule->needle); + if (i + needleLen >= size || memcmp(code + i, rule->needle, needleLen) != 0) continue; + u32 len = strnlen((const char *)code + i, size - i); + + Hit *h = &p->hits[p->count]; + memset(h, 0, sizeof(*h)); + + if (rule->type == RULE_EXACT && len != needleLen) continue; // Vorlage muss genau passen + { + char repl[128]; + if (rule->type == RULE_EXACT) + snprintf(repl, sizeof(repl), "http://%s%s", server, rule->suffix); + else + snprintf(repl, sizeof(repl), "http://%s%.*s", + server, (int)(len - needleLen), (const char *)code + i + needleLen); + if (len + 1 > sizeof(h->data) || strlen(repl) > len) { + free(code); + snprintf(msg, msglen, "Server-Adresse passt nicht in das %s-Modul\n(zu lang).", t->label); + return false; + } + // Ersatz + Nullbytes bis zur Originallänge (inkl. Terminator) + h->offset = i; + h->size = len + 1; + memcpy(h->data, repl, strlen(repl)); + } + p->count++; + i += len; + break; + } + } + free(code); + + if (p->count == 0 && t->optional) return false; + if (p->count == 0) { + char diag[64]; + patch_diagnose(diag, sizeof(diag)); + snprintf(msg, msglen, "%s-Modul: Nintendo-Adresse nicht gefunden.\n" + "Diagnose gespeichert: /3ds/mbmnet/diagnose.txt\nBitte an den Entwickler schicken.", t->label); + return false; + } + return true; +} + +// Baut den IPS-Patch im Speicher. Gibt die Länge zurück. +static u32 build_ips(const Patch *p, u8 *out, u32 cap) +{ + u32 n = 0; + memcpy(out, "PATCH", 5); + n = 5; + for (int i = 0; i < p->count && n + 5 + p->hits[i].size + 3 <= cap; i++) { + const Hit *h = &p->hits[i]; + u8 rec[5] = { h->offset >> 16, h->offset >> 8, h->offset, h->size >> 8, h->size }; + memcpy(out + n, rec, 5); + memcpy(out + n + 5, h->data, h->size); + n += 5 + h->size; + } + memcpy(out + n, "EOF", 3); + return n + 3; +} + +// Schreibt den Patch. *changed wird true, wenn sich die Datei dadurch geändert hat +// (nur dann muss der 3DS neu starten, denn Luma patcht beim Laden der Module). +#define IPS_CAP 2048 // Miiverse-Patch mit CA: ca. 1100 Bytes + +static bool write_ips(const char *path, const u8 *data, u32 n, bool *changed) +{ + static u8 old[IPS_CAP]; + FILE *f = fopen(path, "rb"); + size_t oldLen = f ? fread(old, 1, sizeof(old), f) : 0; + if (f) fclose(f); + if (oldLen == n && memcmp(old, data, n) == 0) return true; // schon genau so vorhanden + + f = fopen(path, "wb"); + bool ok = f && fwrite(data, 1, n, f) == n; + if (f) fclose(f); + if (ok) *changed = true; + return ok; +} + +// Miiverse-Patch (olvpatch.c): eigene Code-Änderungen + MBMNET-CA statt einfacher Text-Regeln. +// 0 = nicht installiert, andere Version oder CA nicht vom Server zu holen (dann bleibt ein alter Patch stehen). +static u32 build_miiverse(const Target *t, const char *server, u8 *out, u32 cap) +{ + static u8 der[1024]; + static u32 derLen; + static int caState; // 0 = noch nicht geholt, 1 = da, -1 = nicht zu holen + char fp[64]; + fingerprint(t->tid, fp, sizeof(fp)); // leer = kein Zwischenspeicher, gebaut wird trotzdem + if (caState == 0) caState = olvpatch_fetch_ca(server, der, &derLen) ? 1 : -1; + if (caState < 0) return 0; + + u32 sum = 2166136261u; // FNV-1a über die CA: neue CA -> neuer Patch + for (u32 i = 0; i < derLen; i++) sum = (sum ^ der[i]) * 16777619u; + char key[160]; + if (fp[0]) snprintf(key, sizeof(key), "%s|%s|olv1|%08lX", fp, server, (unsigned long)sum); + else key[0] = 0; + u32 n = cache_load(t, key, out, cap); + if (n) return n; + + u8 *code; + u32 size; + char ignore[8]; + if (!load_code(t, &code, &size, ignore, sizeof(ignore))) return 0; + bool supported = olvpatch_supported(code, size); + free(code); + if (!supported) return 0; + n = olvpatch_build(server, der, derLen, out, cap); + if (n) cache_store(t, key, out, n); + return n; +} + +// --- Fremde Patches, die MBMNET stören --------------------------------------------- +// Pretendos Patch für das http-Modul fragt bei jeder Verbindung den Freunde-Dienst nach dem +// aktiven Konto. Stellt der Freunde-Dienst selbst die Anfrage, warten beide aufeinander und +// keine Anfrage kommt bei MBMNET an. Er wird beim Aktivieren beiseitegelegt und beim +// Zurücksetzen zurückgeholt. +static const u64 conflicting[] = { + 0x0004013000002902ULL, // http +}; + +static int park_conflicting(void) +{ + int parked = 0; + for (size_t i = 0; i < sizeof(conflicting) / sizeof(conflicting[0]); i++) { + char ips[96], backup[112]; + snprintf(ips, sizeof(ips), SYSMODULE_DIR "/%016llX.ips", conflicting[i]); + snprintf(backup, sizeof(backup), "%s.vor-mbmnet", ips); + // Liegt hier ein Patch, ist er fremd (MBMNET legt hier keinen an): immer den aktuellen sichern + if (file_exists(ips)) { + remove(backup); + if (rename(ips, backup) == 0) parked++; + } + } + return parked; +} + +static void restore_conflicting(void) +{ + for (size_t i = 0; i < sizeof(conflicting) / sizeof(conflicting[0]); i++) { + char ips[96], backup[112]; + snprintf(ips, sizeof(ips), SYSMODULE_DIR "/%016llX.ips", conflicting[i]); + snprintf(backup, sizeof(backup), "%s.vor-mbmnet", ips); + if (file_exists(backup) && !file_exists(ips)) rename(backup, ips); + } +} + +// --- Boot-Splash -------------------------------------------------------------------- + +static bool install_splash(bool alreadyOurs) +{ + // Eigenen Splash des Nutzers sichern (nur beim ersten Aktivieren) + if (!alreadyOurs && file_exists(SPLASH_FILE) && !file_exists(SPLASH_BACKUP)) rename(SPLASH_FILE, SPLASH_BACKUP); + if (alreadyOurs && file_exists(SPLASH_FILE)) return true; + // Beim Deaktivieren geparkt: nur zurückschieben + if (!file_exists(SPLASH_FILE) && file_exists(SPLASH_CACHE) && rename(SPLASH_CACHE, SPLASH_FILE) == 0) return true; + + u8 *buf = malloc(SPLASH_SIZE); + if (!buf) return false; + u32 out = 0; + for (u32 i = 0; i + 3 < splash_rle_size && out < SPLASH_SIZE; i += 4) { + for (u8 n = splash_rle[i]; n > 0 && out + 3 <= SPLASH_SIZE; n--) { + memcpy(buf + out, &splash_rle[i + 1], 3); + out += 3; + } + } + FILE *f = out == SPLASH_SIZE ? fopen(SPLASH_FILE, "wb") : NULL; + bool ok = f && fwrite(buf, 1, SPLASH_SIZE, f) == SPLASH_SIZE; + if (f) fclose(f); + free(buf); + return ok; +} + +static void remove_splash(void) +{ + // Parken statt löschen, damit das nächste Aktivieren ihn nicht neu schreiben muss + mkdir(APP_DIR, 0777); + mkdir(CACHE_DIR, 0777); + remove(SPLASH_CACHE); + if (rename(SPLASH_FILE, SPLASH_CACHE) != 0) remove(SPLASH_FILE); + if (file_exists(SPLASH_BACKUP)) rename(SPLASH_BACKUP, SPLASH_FILE); +} + +// --- Aktivieren / Deaktivieren ----------------------------------------------- + +bool patch_enable(const char *server, bool *changed, char *msg, size_t msglen) +{ + *changed = false; + if (!server[0]) { + snprintf(msg, msglen, "Bitte zuerst die Server-Adresse eintragen."); + return false; + } + + bool alreadyOurs = patch_state() == STATE_MBMNET; + + // Erst alle Patches bereitlegen (aus dem Zwischenspeicher oder neu berechnet): + // Klappt eines nicht, wird gar nichts geschrieben. + static u8 ips[TARGET_COUNT][IPS_CAP]; + u32 ipsLen[TARGET_COUNT]; + for (size_t i = 0; i < TARGET_COUNT; i++) { + if (targets[i].optional) { // Miiverse + ipsLen[i] = build_miiverse(&targets[i], server, ips[i], IPS_CAP); + continue; + } + char key[160]; + cache_key(&targets[i], server, key, sizeof(key)); + ipsLen[i] = cache_load(&targets[i], key, ips[i], IPS_CAP); + if (ipsLen[i]) continue; + static Patch patch; + if (!build_patch(&targets[i], server, &patch, msg, msglen)) { + if (targets[i].optional) { ipsLen[i] = 0; continue; } // nicht installiert: auslassen + return false; + } + ipsLen[i] = build_ips(&patch, ips[i], IPS_CAP); + cache_store(&targets[i], key, ips[i], ipsLen[i]); + } + + bool backedUp = false, appPatched = false; + for (size_t i = 0; i < TARGET_COUNT; i++) { + const Target *t = &targets[i]; + if (!ipsLen[i]) continue; + char path[128], marker[128], backup[128], dir[96]; + if (t->optional) { + snprintf(dir, sizeof(dir), "%s/%016llX", t->dir, t->tid); + mkdirs(dir); + appPatched = true; + } + path_in(path, sizeof(path), t, "code.ips"); + path_in(marker, sizeof(marker), t, "mbmnet.txt"); + path_in(backup, sizeof(backup), t, "code.ips.vor-mbmnet"); + + mkdirs(t->dir); + // Fremden Patch (z. B. Pretendo) sichern, nicht überschreiben. Immer den aktuellen: Eine ältere Sicherung + // (z. B. von vor einem Nimbus-Update) würde sonst beim Zurückschalten veraltete Patches herstellen + // (bei Pretendo Fehler 002-0122). + if (file_exists(path) && !file_exists(marker)) { + remove(backup); + rename(path, backup); + backedUp = true; + } + if (!write_ips(path, ips[i], ipsLen[i], changed)) { + snprintf(msg, msglen, "Patch konnte nicht auf die SD-Karte geschrieben werden."); + return false; + } + FILE *m = fopen(marker, "w"); + if (m) { + fprintf(m, "MBMNET-Patch aktiv\nServer: %s\n", server); + fclose(m); + } + } + + if (park_conflicting() > 0) *changed = true; // Neustart nötig, damit das http-Modul neu lädt + bool splash = install_splash(alreadyOurs) && lumaconfig_enable_splash(); + lumaconfig_enable_modules(); + if (appPatched && lumaconfig_enable_game_patching()) *changed = true; + + snprintf(msg, msglen, "Patches geschrieben.%s%s", + backedUp ? "\nAlter Patch wurde gesichert." : "", + splash ? "\nLuma zeigt beim Start \"MBMNET aktiv\"." : ""); + return true; +} + +// --- Diagnose --------------------------------------------------------------------- + +static bool has_ci(const char *s, u32 len, const char *word) +{ + size_t wl = strlen(word); + for (u32 i = 0; i + wl <= len; i++) { + size_t k = 0; + while (k < wl && (s[i + k] | 0x20) == word[k]) k++; + if (k == wl) return true; + } + return false; +} + +static bool interesting(const char *s, u32 len) +{ + return has_ci(s, len, "nintendo") || has_ci(s, len, "http") || has_ci(s, len, "nasc") + || has_ci(s, len, "account") || has_ci(s, len, "%s") || has_ci(s, len, ".net"); +} + +static void dump_strings(FILE *f, const u8 *code, u32 size) +{ + int lines = 0, total = 0; + char buf[256]; + + // ASCII-Texte + for (u32 i = 0; i < size;) { + u32 j = i; + while (j < size && code[j] >= 0x20 && code[j] < 0x7F) j++; + u32 len = j - i; + if (len >= 6) total++; + if (len >= 4 && interesting((const char *)code + i, len) && lines < 400) { + fprintf(f, " %06lX %.*s\n", (unsigned long)i, (int)(len > 200 ? 200 : len), (const char *)code + i); + lines++; + } + i = j + 1; + } + + // UTF-16-Texte (ein Zeichen + Nullbyte) + for (u32 i = 0; i + 1 < size;) { + u32 j = i, n = 0; + while (j + 1 < size && code[j] >= 0x20 && code[j] < 0x7F && code[j + 1] == 0 && n < sizeof(buf) - 1) { + buf[n++] = code[j]; + j += 2; + } + if (n >= 6 && interesting(buf, n) && lines < 500) { + fprintf(f, " %06lX [UTF-16] %.*s\n", (unsigned long)i, (int)n, buf); + lines++; + } + i = (j > i) ? j + 2 : i + 1; + } + fprintf(f, " (%d Texte insgesamt, %d passende gezeigt)\n", total, lines); +} + +// Sucht den laufenden Prozess eines Titels (Luma liefert die Titel-ID über Info-Typ 0x10001) +bool patch_find_process(u64 tid, u32 *pidOut) +{ + static u32 pids[0x60]; + s32 n = 0; + if (R_FAILED(svcGetProcessList(&n, pids, 0x60))) return false; + for (s32 i = 0; i < n; i++) { + Handle h; + if (R_FAILED(svcOpenProcess(&h, pids[i]))) continue; + s64 t = 0; + Result r = svcGetProcessInfo(&t, h, 0x10001); + svcCloseHandle(h); + if (R_SUCCEEDED(r) && (u64)t == tid) { *pidOut = pids[i]; return true; } + } + return false; +} + +// Liest aus dem laufenden Modul, welche Adresse dort wirklich im Speicher steht. +// So sieht man, ob Luma den Patch beim Laden angewendet hat. +static void dump_runtime(FILE *f, const char *label, u64 tid, u32 offset) +{ + u32 pid = 0; + if (!patch_find_process(tid, &pid)) { fprintf(f, " %s: Prozess nicht gefunden\n", label); return; } + Handle dbg; + Result r = svcDebugActiveProcess(&dbg, pid); + if (R_FAILED(r)) { fprintf(f, " %s: kein Zugriff (%08lX)\n", label, (unsigned long)r); return; } + DebugEventInfo info; + while (R_SUCCEEDED(svcGetProcessDebugEvent(&info, dbg))) + if (info.flags & 1) svcContinueDebugEvent(dbg, 0); + char buf[64] = { 0 }; + r = svcReadProcessMemory(buf, dbg, 0x100000 + offset, 48); + svcCloseHandle(dbg); + if (R_FAILED(r)) { fprintf(f, " %s: Lesen fehlgeschlagen (%08lX)\n", label, (unsigned long)r); return; } + for (int i = 0; i < 48 && buf[i]; i++) if (buf[i] < 0x20 || buf[i] > 0x7E) buf[i] = '.'; + fprintf(f, " %s (PID %lu) bei %06lX: %s\n", label, (unsigned long)pid, (unsigned long)offset, buf); +} + +bool patch_diagnose(char *msg, size_t msglen) +{ + mkdirs(APP_DIR); + FILE *f = fopen(DIAG_FILE, "w"); + if (!f) { + snprintf(msg, msglen, "Diagnose konnte nicht gespeichert werden."); + return false; + } + fprintf(f, "MBMNET-Diagnose (App v%s)\n\n", APP_VERSION); + + for (size_t i = 0; i < TARGET_COUNT; i++) { + const Target *t = &targets[i]; + u8 *raw = NULL; + u32 rawSize = 0; + Result rc = read_from_nand(t->tid, &raw, &rawSize); + bool fromSd = false; + if (R_FAILED(rc)) fromSd = read_from_sd(t->tid, &raw, &rawSize); + + fprintf(f, "== %s-Modul %016llX\n", t->label, t->tid); + if (!raw) { + fprintf(f, " nicht lesbar (Fehler %08lX)\n\n", (unsigned long)rc); + continue; + } + bool compressed = blz_looks_compressed(raw, rawSize); + fprintf(f, " Quelle: %s, Größe %lu, komprimiert: %s\n", fromSd ? "SD-Dump" : "NAND", + (unsigned long)rawSize, compressed ? "ja" : "nein"); + free(raw); + + char err[160]; + u8 *code; + u32 size; + if (!load_code(t, &code, &size, err, sizeof(err))) { + fprintf(f, " Fehler: %s\n\n", err); + continue; + } + fprintf(f, " entpackt: %lu Bytes\n", (unsigned long)size); + dump_strings(f, code, size); + fprintf(f, "\n"); + free(code); + } + // Installierte Patches: liegen sie auf der SD, und was steht drin? + fprintf(f, "== Installierte Patches\n"); + for (size_t i = 0; i < TARGET_COUNT; i++) { + char ips[128]; + path_in(ips, sizeof(ips), &targets[i], "code.ips"); + FILE *pf = fopen(ips, "rb"); + if (!pf) { fprintf(f, " %s: kein Patch (%s)\n", targets[i].label, ips + 5); continue; } + static u8 buf[4096]; + size_t n = fread(buf, 1, sizeof(buf), pf); + fclose(pf); + fprintf(f, " %s: %s, %lu Bytes\n", targets[i].label, ips + 5, (unsigned long)n); + for (size_t o = 5; o + 5 <= n && memcmp(buf + o, "EOF", 3) != 0;) { + u32 off = (buf[o] << 16) | (buf[o + 1] << 8) | buf[o + 2]; + u32 len = (buf[o + 3] << 8) | buf[o + 4]; + if (o + 5 + len > n) break; + fprintf(f, " bei %06lX: %.*s\n", (unsigned long)off, (int)strnlen((char *)buf + o + 5, len), (char *)buf + o + 5); + o += 5 + len; + } + } + fprintf(f, "\n"); + + // Alles in /luma/sysmodules (auch fremde Patches, z. B. von Pretendo) + fprintf(f, "== Inhalt von /luma/sysmodules\n"); + DIR *dir = opendir(SYSMODULE_DIR); + if (dir) { + struct dirent *e; + while ((e = readdir(dir))) { + char full[300]; + struct stat est; + snprintf(full, sizeof(full), "%s/%s", SYSMODULE_DIR, e->d_name); + if (stat(full, &est) == 0) fprintf(f, " %-40s %8ld Bytes\n", e->d_name, (long)est.st_size); + } + closedir(dir); + } else { + fprintf(f, " (Ordner fehlt)\n"); + } + fprintf(f, "\n"); + + // Konto-Plätze des Kontodienstes (act) + fprintf(f, "== Konto-Plätze\n"); + nnid_dump(f); + fprintf(f, "\n"); + + // Was steht im ARBEITSSPEICHER der laufenden Module? (zeigt, ob Luma die Patches angewendet hat) + fprintf(f, "== Laufende Module (Arbeitsspeicher)\n"); + dump_runtime(f, "Freunde", 0x0004013000003202ULL, 0x61279); + dump_runtime(f, "Konto ", 0x0004013000003802ULL, 0xE564); + fprintf(f, "\n"); + + // Verbindungstest: so, wie die Systemmodule eine Verbindung aufbauen (mit Nintendo-Zertifikaten) + fprintf(f, "== Verbindungstest (wie Freunde-/Konto-Modul)\n"); + httpcContext c; + Result r = httpcOpenContext(&c, HTTPC_METHOD_GET, "http://mbmnetapi.mbm.wtf:81/app/version", 1); + fprintf(f, " Verbindung öffnen (http) %08lX\n", (unsigned long)r); + if (R_SUCCEEDED(r)) { + fprintf(f, " Nintendo-Root-Zertifikat %08lX\n", (unsigned long)httpcAddDefaultCert(&c, SSLC_DefaultRootCert_Nintendo_CA_G3)); + fprintf(f, " Client-Zertifikat %08lX\n", (unsigned long)httpcSetClientCertDefault(&c, SSLC_DefaultClientCert_ClCertA)); + r = httpcBeginRequest(&c); + u32 status = 0; + if (R_SUCCEEDED(r)) httpcGetResponseStatusCodeTimeout(&c, &status, 10ULL * 1000 * 1000 * 1000); + fprintf(f, " Anfrage senden %08lX HTTP %lu\n", (unsigned long)r, (unsigned long)status); + httpcCloseContext(&c); + } + fprintf(f, "\n"); + + // Boot-Splash und Luma-Einstellungen + fprintf(f, "== Boot-Splash / Luma-Einstellungen\n"); + struct stat st; + if (stat(SPLASH_FILE, &st) == 0) + fprintf(f, " /luma/splash.bin: %ld Bytes%s\n", (long)st.st_size, st.st_size == SPLASH_SIZE ? " (richtig)" : " (FALSCHE GRÖSSE, Luma erwartet 288000)"); + else + fprintf(f, " /luma/splash.bin: fehlt\n"); + FILE *cfg = fopen("sdmc:/luma/config.ini", "r"); + if (cfg) { + char line[160]; + while (fgets(line, sizeof(line), cfg)) { + if (strstr(line, "splash_position") || strstr(line, "splash_duration") || strstr(line, "config_version") + || strstr(line, "enable_external_firm_and_modules =")) + fprintf(f, " config.ini: %s", line); + } + fclose(cfg); + } else { + fprintf(f, " /luma/config.ini: fehlt (ältere Luma-Version? Splash dann im Luma-Menü einschalten)\n"); + } + fprintf(f, "\n"); + + // Kontospeicher: Darf die App Systemspeicher öffnen? Scheitert nur der eines laufenden Dienstes + // (act, frd), ist er belegt; scheitern alle, fehlt eine Berechtigung. + fprintf(f, "== Systemspeicher öffnen (für \"Anmeldung merken\")\n"); + static const struct { u32 id; const char *name; } saves[] = { + { 0x00010038, "act (Kontodienst, läuft)" }, + { 0x00010032, "frd (Freunde-Dienst, läuft)" }, + { 0x00010017, "cfg (Systemeinstellungen-Modul, läuft)" }, + { 0x00020082, "HOME-Menü (System-App)" }, + { 0x00020086, "Systemeinstellungen (System-App, läuft nicht)" }, + }; + for (size_t i = 0; i < sizeof(saves) / sizeof(saves[0]); i++) { + u32 path[2] = { MEDIATYPE_NAND, saves[i].id }; + FS_Archive arch; + Result r = FSUSER_OpenArchive(&arch, ARCHIVE_SYSTEM_SAVEDATA, (FS_Path){ PATH_BINARY, sizeof(path), path }); + int files = -1; + if (R_SUCCEEDED(r)) { + Handle dir; + if (R_SUCCEEDED(FSUSER_OpenDirectory(&dir, arch, fsMakePath(PATH_ASCII, "/")))) { + FS_DirectoryEntry e[16]; + u32 n = 0; + files = R_SUCCEEDED(FSDIR_Read(dir, &n, 16, e)) ? (int)n : -2; + FSDIR_Close(dir); + } + FSUSER_CloseArchive(arch); + } + fprintf(f, " %08lX %-44s %08lX%s", (unsigned long)saves[i].id, saves[i].name, (unsigned long)r, R_SUCCEEDED(r) ? " OK" : ""); + if (files >= 0) fprintf(f, ", %d Einträge", files); + fprintf(f, "\n"); + } + fprintf(f, " Als %s gestartet\n", envIsHomebrew() ? "3dsx (Homebrew Launcher)" : "CIA"); + fprintf(f, "\n"); + + fclose(f); + snprintf(msg, msglen, "Diagnose gespeichert:\n/3ds/mbmnet/diagnose.txt\nBitte an den Entwickler schicken."); + return true; +} + +bool patch_disable(char *msg, size_t msglen) +{ + PatchState st = patch_state(); + if (st != STATE_MBMNET) { + snprintf(msg, msglen, st == STATE_FOREIGN + ? "MBMNET ist nicht aktiv.\nDer vorhandene fremde Patch bleibt unverändert." + : "Schon im Originalzustand."); + return false; + } + + remove_splash(); + restore_conflicting(); + lumaconfig_restore_splash(); + lumaconfig_restore_modules(); + lumaconfig_restore_game_patching(); + + bool restored = false; + for (size_t i = 0; i < TARGET_COUNT; i++) { + const Target *t = &targets[i]; + char ips[128], marker[128], backup[128]; + path_in(ips, sizeof(ips), t, "code.ips"); + path_in(marker, sizeof(marker), t, "mbmnet.txt"); + path_in(backup, sizeof(backup), t, "code.ips.vor-mbmnet"); + + if (!file_exists(marker)) continue; + remove(ips); + remove(marker); + if (file_exists(backup)) { + rename(backup, ips); + restored = true; + } + } + + snprintf(msg, msglen, restored ? "Vorheriger Patch wiederhergestellt." : "Patches entfernt."); + return true; +} diff --git a/source/patcher.h b/source/patcher.h new file mode 100644 index 0000000..f405f2e --- /dev/null +++ b/source/patcher.h @@ -0,0 +1,30 @@ +#pragma once +#include <3ds/types.h> + +// Offizieller MBMNET-Server. Über "Server-Adresse" lässt sich ein anderer eintragen (z. B. zum Testen). +// Fester MBMNET-Server: einfaches HTTP über den NetBird-TCP-Service auf Port 81. +// Höchstens 21 Zeichen passen in den Patch. +#define MBMNET_SERVER "mbmnetapi.mbm.wtf:81" + +#define APP_DIR "sdmc:/3ds/mbmnet" +#define DIAG_FILE APP_DIR "/diagnose.txt" + +typedef enum { + STATE_ORIGINAL, // kein Patch: Nintendo-Originalzustand + STATE_MBMNET, // unser Patch ist aktiv + STATE_FOREIGN, // fremder Patch (z. B. Pretendo/Nimbus) ist aktiv +} PatchState; + +PatchState patch_state(void); +// Räumt Patches alter App-Versionen (/luma/titles/...) weg. true, wenn etwas entfernt wurde. +bool patch_migrate(void); + +// Erzeugt die Patches (Freunde + Konto) und aktiviert MBMNET. msg bekommt eine lesbare Meldung. +// *changed: true, wenn sich Patch-Dateien geändert haben (dann ist ein Neustart nötig). +bool patch_enable(const char *server, bool *changed, char *msg, size_t msglen); +// Schreibt alle Adress-Texte aus den Modulen nach DIAG_FILE (zur Fehlersuche). +bool patch_diagnose(char *msg, size_t msglen); +// Entfernt unsere Patches und stellt eventuell gesicherte fremde Patches wieder her. +bool patch_disable(char *msg, size_t msglen); +// Läuft ein Prozess mit dieser Titel-ID? (über Lumas Prozess-Info), PID in pidOut +bool patch_find_process(u64 tid, u32 *pidOut); diff --git a/source/relaunch.c b/source/relaunch.c new file mode 100644 index 0000000..5d91aee --- /dev/null +++ b/source/relaunch.c @@ -0,0 +1,48 @@ +// Startet die App nach einem Update selbst neu. +// +// CIA: aptSetChainloaderToSelf() - das System startet beim Beenden denselben Titel +// (jetzt die neue Version) wieder. +// 3DSX: Die App läuft im Homebrew-Titel von Luma (Rosalina). Über dessen Dienst "hb:ldr" +// legen wir fest, welche .3dsx beim nächsten Start geladen wird - genau so macht es +// auch der Homebrew Launcher. Danach den Homebrew-Titel neu starten lassen. +#include <3ds.h> +#include + +#include "relaunch.h" + +static Result hbldr_call(Handle h, u32 cmd, const void *buf, u32 size, int staticId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + cmdbuf[0] = IPC_MakeHeader(cmd, 0, 2); + cmdbuf[1] = IPC_Desc_StaticBuffer(size, staticId); + cmdbuf[2] = (u32)buf; + Result rc = svcSendSyncRequest(h); + return R_SUCCEEDED(rc) ? (Result)cmdbuf[1] : rc; +} + +static bool set_homebrew_target(const char *selfPath) +{ + Handle h; + if (R_FAILED(svcConnectToPort(&h, "hb:ldr"))) return false; + + // hb:ldr erwartet den Pfad ohne "sdmc:" + const char *path = strncmp(selfPath, "sdmc:/", 6) == 0 ? selfPath + 5 : selfPath; + Result rc = hbldr_call(h, 2, path, strlen(path) + 1, 0); // SetTarget + + // argv wie beim Homebrew Launcher: u32 Anzahl, dann die Texte + static u32 argBuf[0x400 / 4]; + memset(argBuf, 0, sizeof(argBuf)); + argBuf[0] = 1; + strncpy((char *)&argBuf[1], selfPath, sizeof(argBuf) - 5); + if (R_SUCCEEDED(rc)) rc = hbldr_call(h, 3, argBuf, sizeof(argBuf), 1); // SetArgv + + svcCloseHandle(h); + return R_SUCCEEDED(rc); +} + +bool relaunch_prepare(const char *selfPath) +{ + if (envIsHomebrew() && !set_homebrew_target(selfPath)) return false; + aptSetChainloaderToSelf(); + return true; +} diff --git a/source/relaunch.h b/source/relaunch.h new file mode 100644 index 0000000..de70c35 --- /dev/null +++ b/source/relaunch.h @@ -0,0 +1,6 @@ +#pragma once +#include <3ds/types.h> + +// Bereitet den Neustart der App vor. Danach main() verlassen, dann startet das System +// die (neue) App wieder. false: Neustart nicht möglich, Nutzer muss selbst neu starten. +bool relaunch_prepare(const char *selfPath); diff --git a/source/splash_data.c b/source/splash_data.c new file mode 100644 index 0000000..de00746 --- /dev/null +++ b/source/splash_data.c @@ -0,0 +1,1985 @@ +// Boot-Splash "MBMNET aktiv" für Luma3DS (/luma/splash.bin), erzeugt aus assets/splash.png. +// Format: Lauflängen-kodiert, je Eintrag [Anzahl][B][G][R]; entpackt 400x240 Pixel im +// Framebuffer-Layout (spaltenweise, unten nach oben) = 288000 Bytes. +#include <3ds/types.h> + +const u32 splash_rle_size = 31624; +const u8 splash_rle[] = { + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x45, 0x29, 0x21, 0x1D, + 0x01, 0x34, 0x3F, 0x1D, 0x01, 0x3A, 0x4E, 0x1D, 0x01, 0x34, 0x3F, 0x1D, 0xA3, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x42, 0x29, 0x21, 0x1D, 0x01, 0x2F, 0x30, 0x1C, 0x01, 0x51, 0x85, 0x1E, + 0x01, 0x6B, 0xBE, 0x1A, 0x03, 0x71, 0xCC, 0x1B, 0x01, 0x6B, 0xBE, 0x1A, 0x01, 0x51, 0x85, 0x1E, + 0x01, 0x2F, 0x30, 0x1C, 0xA0, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x41, 0x29, 0x21, 0x1D, + 0x01, 0x38, 0x47, 0x1E, 0x01, 0x69, 0xBA, 0x1B, 0x07, 0x71, 0xCC, 0x1B, 0x01, 0x69, 0xBA, 0x1B, + 0x01, 0x38, 0x47, 0x1E, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x40, 0x29, 0x21, 0x1D, + 0x01, 0x31, 0x38, 0x1D, 0x01, 0x6B, 0xBD, 0x1A, 0x09, 0x71, 0xCC, 0x1B, 0x01, 0x6B, 0xBD, 0x1A, + 0x01, 0x31, 0x38, 0x1D, 0x9E, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x40, 0x29, 0x21, 0x1D, + 0x01, 0x5A, 0x99, 0x1C, 0x0B, 0x71, 0xCC, 0x1B, 0x01, 0x5A, 0x99, 0x1C, 0x9E, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, 0x01, 0x31, 0x37, 0x1D, 0x01, 0x70, 0xCB, 0x19, + 0x0B, 0x71, 0xCC, 0x1B, 0x01, 0x70, 0xCB, 0x19, 0x01, 0x31, 0x37, 0x1D, 0x9D, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, 0x01, 0x45, 0x68, 0x1E, 0x0D, 0x71, 0xCC, 0x1B, + 0x01, 0x45, 0x68, 0x1E, 0x9D, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, + 0x01, 0x4D, 0x7A, 0x1E, 0x0D, 0x71, 0xCC, 0x1B, 0x01, 0x4D, 0x7A, 0x1E, 0x9D, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, 0x01, 0x49, 0x73, 0x1F, 0x0D, 0x71, 0xCC, 0x1B, + 0x01, 0x49, 0x73, 0x1F, 0x9D, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, + 0x01, 0x3C, 0x54, 0x1E, 0x0D, 0x71, 0xCC, 0x1B, 0x01, 0x3C, 0x54, 0x1E, 0x9D, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, 0x01, 0x29, 0x24, 0x1D, 0x01, 0x6A, 0xBD, 0x1A, + 0x0B, 0x71, 0xCC, 0x1B, 0x01, 0x6A, 0xBD, 0x1A, 0x01, 0x29, 0x24, 0x1D, 0x9D, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x40, 0x29, 0x21, 0x1D, 0x01, 0x47, 0x6C, 0x1E, 0x0B, 0x71, 0xCC, 0x1B, + 0x01, 0x46, 0x6B, 0x1E, 0x9E, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x41, 0x29, 0x21, 0x1D, + 0x01, 0x57, 0x90, 0x1E, 0x09, 0x71, 0xCC, 0x1B, 0x01, 0x57, 0x90, 0x1E, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x42, 0x29, 0x21, 0x1D, 0x01, 0x4D, 0x7A, 0x1E, 0x01, 0x6E, 0xC6, 0x1A, + 0x05, 0x71, 0xCC, 0x1B, 0x01, 0x6E, 0xC6, 0x1A, 0x01, 0x4D, 0x7A, 0x1E, 0xA0, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x43, 0x29, 0x21, 0x1D, 0x01, 0x30, 0x35, 0x1D, 0x01, 0x4B, 0x74, 0x1E, + 0x01, 0x5A, 0x99, 0x1C, 0x01, 0x5F, 0xA4, 0x1C, 0x01, 0x5A, 0x99, 0x1C, 0x01, 0x4B, 0x74, 0x1E, + 0x01, 0x30, 0x35, 0x1D, 0xA1, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0x54, 0x4E, 0x4A, 0x14, 0x5C, 0x58, 0x55, 0x01, 0x46, 0x40, 0x3C, 0x9A, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xFE, 0xFE, 0xFE, 0x14, 0xFF, 0xFF, 0xFF, + 0x01, 0xCE, 0xCC, 0xCB, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xD3, 0xD1, 0xD1, 0x9A, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xFD, 0xFD, 0xFD, + 0x14, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x44, 0x3E, 0x3A, 0x08, 0x4C, 0x46, 0x44, 0x01, 0x4F, 0x4A, 0x46, + 0x01, 0x91, 0x8E, 0x8C, 0x01, 0xDE, 0xDD, 0xDC, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x42, 0x29, 0x21, 0x1D, 0x01, 0x4C, 0x45, 0x42, + 0x01, 0xA2, 0x9F, 0x9E, 0x01, 0xEB, 0xEA, 0xEA, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xFD, 0xFD, 0xFD, + 0x01, 0xAC, 0xA9, 0xA8, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, + 0x01, 0x30, 0x28, 0x24, 0x01, 0x7C, 0x78, 0x76, 0x01, 0xCD, 0xCB, 0xCB, 0x01, 0xFE, 0xFE, 0xFE, + 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xE4, 0xE4, 0xE4, 0x01, 0x9B, 0x98, 0x96, 0x01, 0x45, 0x3F, 0x3B, + 0x9B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3D, 0x29, 0x21, 0x1D, 0x01, 0x55, 0x4E, 0x4C, + 0x01, 0xA9, 0xA8, 0xA6, 0x01, 0xF0, 0xF0, 0xEF, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xF7, 0xF7, 0xF6, + 0x01, 0xB8, 0xB7, 0xB6, 0x01, 0x67, 0x63, 0x5F, 0x9E, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x85, 0x81, 0x7F, 0x01, 0xD5, 0xD3, 0xD3, 0x0B, 0xFF, 0xFF, 0xFF, + 0x01, 0xD6, 0xD4, 0xD4, 0x01, 0x88, 0x85, 0x83, 0x01, 0x38, 0x30, 0x2C, 0xA0, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xED, 0xED, 0xED, + 0x01, 0xA8, 0xA6, 0xA5, 0x01, 0x54, 0x4E, 0x4A, 0xA3, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0x81, 0x7D, 0x7B, 0x01, 0x2D, 0x26, 0x21, + 0xA5, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x09, 0xFF, 0xFF, 0xFF, + 0x01, 0xF5, 0xF5, 0xF5, 0x01, 0xB7, 0xB4, 0xB3, 0x01, 0x64, 0x60, 0x5C, 0xA4, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xC5, 0xC4, 0xC3, 0x01, 0xFC, 0xFC, 0xFC, + 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xE2, 0xE1, 0xE1, 0x01, 0x97, 0x94, 0x92, 0x01, 0x44, 0x3D, 0x39, + 0xA1, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3C, 0x29, 0x21, 0x1D, 0x01, 0x44, 0x3E, 0x3A, + 0x01, 0x9B, 0x98, 0x96, 0x01, 0xE6, 0xE5, 0xE5, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xFC, 0xFC, 0xFC, + 0x01, 0xC6, 0xC5, 0xC4, 0x01, 0x77, 0x73, 0x71, 0x01, 0x2D, 0x26, 0x21, 0x9E, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, 0x01, 0x6B, 0x66, 0x64, 0x01, 0xBE, 0xBC, 0xBB, + 0x01, 0xF9, 0xF9, 0xF9, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xEE, 0xEE, 0xED, 0x01, 0xA9, 0xA7, 0xA6, + 0x01, 0x55, 0x4E, 0x4C, 0x9C, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x41, 0x29, 0x21, 0x1D, + 0x01, 0x3C, 0x36, 0x32, 0x01, 0x91, 0x8F, 0x8D, 0x01, 0xDF, 0xDE, 0xDD, 0x0B, 0xFF, 0xFF, 0xFF, + 0x01, 0xD6, 0xD6, 0xD5, 0x01, 0x7A, 0x76, 0x74, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x44, 0x29, 0x21, 0x1D, 0x01, 0x62, 0x5C, 0x5A, 0x01, 0xB6, 0xB3, 0xB2, 0x01, 0xF6, 0xF6, 0xF6, + 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xD6, 0xD4, 0xD4, 0x0A, 0xDE, 0xDD, 0xDC, 0x01, 0xE8, 0xE7, 0xE6, + 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xD1, 0xD1, 0xD0, + 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xD0, 0xCF, 0xCE, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x99, 0x96, 0x94, 0x14, 0xA2, 0x9F, 0x9E, 0x01, 0x7C, 0x78, 0x76, + 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xBF, 0xBD, 0xBC, 0x14, 0xC7, 0xC5, 0xC5, 0x01, 0x9A, 0x97, 0x95, + 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xD0, 0xCF, 0xCE, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x16, 0xFF, 0xFF, 0xFF, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x16, 0xFF, 0xFF, 0xFF, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x16, 0xFF, 0xFF, 0xFF, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xC3, 0xC2, 0xC1, 0x04, 0x70, 0x6C, 0x69, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x7B, 0x77, 0x75, 0x03, 0x70, 0x6C, 0x69, 0x01, 0xF4, 0xF4, 0xF4, + 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xED, 0xED, 0xED, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x8B, 0x88, 0x86, 0x04, 0x29, 0x21, 0x1D, + 0x01, 0xF4, 0xF4, 0xF4, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0x38, 0x30, 0x2C, 0x03, 0x29, 0x21, 0x1D, + 0x01, 0xC0, 0xBF, 0xBE, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x8C, 0x88, 0x87, + 0x04, 0x29, 0x21, 0x1D, 0x01, 0xF5, 0xF5, 0xF5, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0x49, 0x44, 0x40, + 0x03, 0x29, 0x21, 0x1D, 0x01, 0xC3, 0xC1, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xAE, 0xAB, 0xAA, 0x03, 0x29, 0x21, 0x1D, 0x01, 0x3A, 0x33, 0x2F, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0x86, 0x82, 0x80, 0x03, 0x29, 0x21, 0x1D, 0x01, 0xEC, 0xEB, 0xEB, 0x03, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xE1, 0xE0, 0xDF, 0x03, 0x29, 0x21, 0x1D, 0x01, 0x67, 0x63, 0x5F, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xC3, 0xC2, 0xC1, 0x02, 0x29, 0x21, 0x1D, 0x01, 0x61, 0x5B, 0x59, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCE, 0xCC, 0xCB, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xED, 0xED, 0xED, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x6E, 0x6A, 0x68, + 0x01, 0x29, 0x21, 0x1D, 0x01, 0x35, 0x2E, 0x2B, 0x01, 0xDB, 0xDB, 0xDB, 0x05, 0xFF, 0xFF, 0xFF, + 0x01, 0xC6, 0xC5, 0xC4, 0x01, 0xBF, 0xBE, 0xBD, 0x01, 0xFA, 0xFA, 0xFA, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xB4, 0xB2, 0xB0, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0xCA, 0xC9, 0xC8, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xFD, 0xFD, 0xFD, 0x01, 0xE3, 0xE2, 0xE2, + 0x01, 0xF9, 0xF8, 0xF8, 0x0D, 0xFF, 0xFF, 0xFF, 0x01, 0x90, 0x8D, 0x8B, 0x9A, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xA4, 0xA1, 0xA0, 0x14, 0xFF, 0xFF, 0xFF, + 0x01, 0x68, 0x63, 0x61, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0x7B, 0x77, 0x75, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xC1, 0xBF, 0xBF, 0x08, 0xFF, 0xFF, 0xFF, + 0x01, 0xE9, 0xE9, 0xE9, 0x01, 0x36, 0x2F, 0x2B, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x2F, 0x27, 0x22, 0x01, 0xD1, 0xD0, 0xCF, 0x08, 0xFF, 0xFF, 0xFF, + 0x01, 0xFA, 0xFA, 0xFA, 0x01, 0x44, 0x3D, 0x39, 0x01, 0xDB, 0xDB, 0xDB, 0x06, 0xFF, 0xFF, 0xFF, + 0x01, 0xF9, 0xF9, 0xF9, 0x01, 0x5D, 0x59, 0x56, 0x9B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3C, 0x29, 0x21, 0x1D, 0x01, 0x3E, 0x38, 0x34, 0x01, 0xE8, 0xE7, 0xE6, 0x06, 0xFF, 0xFF, 0xFF, + 0x01, 0xFD, 0xFD, 0xFD, 0x01, 0x7B, 0x77, 0x75, 0x01, 0x29, 0x21, 0x1D, 0x01, 0x39, 0x31, 0x2D, + 0x01, 0xD0, 0xCF, 0xCE, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF4, 0xF4, 0x01, 0x7F, 0x7B, 0x79, + 0x9C, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3D, 0x29, 0x21, 0x1D, 0x01, 0x55, 0x4F, 0x4D, + 0x01, 0xD6, 0xD4, 0xD4, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xE9, 0xE9, 0xE9, 0x01, 0x81, 0x7E, 0x7C, + 0x04, 0x29, 0x21, 0x1D, 0x01, 0x4B, 0x44, 0x41, 0x01, 0x84, 0x80, 0x7E, 0x01, 0x91, 0x8E, 0x8C, + 0x01, 0x76, 0x72, 0x70, 0x01, 0x39, 0x31, 0x2D, 0x9D, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3F, 0x29, 0x21, 0x1D, 0x01, 0x54, 0x4E, 0x4A, 0x01, 0x77, 0x73, 0x71, 0x01, 0x84, 0x80, 0x7E, + 0x01, 0x54, 0x4E, 0x4A, 0xA8, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0x54, 0x4E, 0x4A, 0x14, 0x5C, 0x58, 0x55, 0x01, 0x46, 0x40, 0x3C, 0x9A, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xFE, 0xFE, 0xFE, 0x14, 0xFF, 0xFF, 0xFF, + 0x01, 0xCE, 0xCC, 0xCB, 0x1D, 0x29, 0x21, 0x1D, 0x01, 0x29, 0x20, 0x24, 0x01, 0x28, 0x1A, 0x4D, + 0x01, 0x28, 0x15, 0x72, 0x01, 0x26, 0x15, 0x8A, 0x01, 0x27, 0x17, 0x9E, 0x01, 0x2B, 0x1D, 0xB7, + 0x01, 0x30, 0x25, 0xC9, 0x01, 0x33, 0x2C, 0xD3, 0x01, 0x37, 0x31, 0xDA, 0x01, 0x38, 0x35, 0xDF, + 0x01, 0x39, 0x35, 0xE1, 0x01, 0x39, 0x36, 0xE2, 0x02, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, + 0x03, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x02, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x39, 0xE8, + 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x03, 0x40, 0x39, 0xEA, + 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEC, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xEE, + 0x01, 0x45, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3B, 0xF0, 0x01, 0x45, 0x39, 0xEC, 0x01, 0x43, 0x37, 0xE5, + 0x01, 0x3E, 0x30, 0xD4, 0x01, 0x38, 0x2C, 0xB9, 0x01, 0x32, 0x24, 0x81, 0x01, 0x29, 0x22, 0x30, + 0x37, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x1B, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x1A, 0x4E, 0x01, 0x26, 0x14, 0x84, + 0x01, 0x27, 0x17, 0xAC, 0x01, 0x27, 0x18, 0xB0, 0x01, 0x2D, 0x1E, 0xBD, 0x01, 0x32, 0x2A, 0xD0, + 0x01, 0x38, 0x35, 0xDF, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE2, + 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x39, 0x37, 0xE3, + 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x03, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3E, 0x39, 0xE7, 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x38, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x02, 0x42, 0x39, 0xEB, + 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x03, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3B, 0xEF, 0x02, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x46, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x3E, 0x31, 0xD1, 0x01, 0x32, 0x24, 0x83, + 0x35, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xD3, 0xD1, 0xD1, 0x19, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x19, 0x53, 0x01, 0x28, 0x16, 0x98, + 0x02, 0x27, 0x18, 0xB0, 0x01, 0x2B, 0x1F, 0xBF, 0x01, 0x34, 0x2F, 0xD8, 0x02, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE2, + 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x39, 0x37, 0xE3, + 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x03, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3E, 0x39, 0xE7, 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x38, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x02, 0x42, 0x39, 0xEB, + 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x03, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3B, 0xEF, 0x02, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x46, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x42, 0x36, 0xE4, 0x01, 0x32, 0x25, 0x8D, + 0x33, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x17, 0x29, 0x21, 0x1D, 0x01, 0x29, 0x1E, 0x36, 0x01, 0x26, 0x15, 0x8D, + 0x02, 0x27, 0x18, 0xB0, 0x01, 0x2A, 0x1A, 0xB6, 0x01, 0x32, 0x2C, 0xD3, 0x01, 0x37, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x02, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x37, 0xE2, 0x02, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x03, 0x3C, 0x37, 0xE4, + 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, + 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x43, 0x3A, 0xEC, 0x03, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x41, 0x33, 0xDA, 0x01, 0x2D, 0x22, 0x56, 0x31, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xFD, 0xFD, 0xFD, 0x14, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x16, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x18, 0x57, 0x01, 0x27, 0x17, 0xA9, 0x02, 0x27, 0x18, 0xB0, + 0x01, 0x2D, 0x1F, 0xC0, 0x01, 0x35, 0x33, 0xDC, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x39, 0xE6, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x42, 0x3A, 0xEB, + 0x02, 0x42, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, + 0x03, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x02, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3D, 0xF2, + 0x01, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x04, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x48, 0x3B, 0xF2, 0x01, 0x35, 0x26, 0x92, 0x30, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x44, 0x3E, 0x3A, 0x08, 0x4C, 0x46, 0x44, 0x01, 0x4F, 0x4A, 0x46, + 0x01, 0x91, 0x8E, 0x8C, 0x01, 0xDE, 0xDD, 0xDC, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x15, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x15, 0x70, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2E, 0x25, 0xC9, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x02, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x37, 0xE2, 0x02, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x03, 0x3C, 0x37, 0xE4, + 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, + 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x43, 0x3A, 0xEC, 0x03, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x39, 0x2C, 0xB9, 0x2F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x42, 0x29, 0x21, 0x1D, 0x01, 0x4C, 0x45, 0x42, 0x01, 0xA2, 0x9F, 0x9E, + 0x01, 0xEB, 0xEA, 0xEA, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xFD, 0xFD, 0xFD, 0x01, 0xAC, 0xA9, 0xA8, + 0x14, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x14, 0x7A, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2F, 0x27, 0xCB, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE1, + 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE2, 0x02, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, + 0x03, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, + 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, + 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x43, 0x3A, 0xEC, + 0x03, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xEE, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x03, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF3, + 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x3D, 0x2E, 0xC6, 0x2E, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, + 0x01, 0x30, 0x28, 0x24, 0x01, 0x7C, 0x78, 0x76, 0x01, 0xCD, 0xCB, 0xCB, 0x01, 0xFE, 0xFE, 0xFE, + 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xE4, 0xE4, 0xE4, 0x01, 0x9B, 0x98, 0x96, 0x01, 0x45, 0x3F, 0x3B, + 0x14, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x15, 0x70, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2E, 0x25, 0xC8, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x04, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x02, 0x3E, 0x38, 0xE8, 0x04, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, 0x02, 0x42, 0x3A, 0xEB, + 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x39, 0xEC, 0x01, 0x42, 0x3A, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xEF, + 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, + 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3E, 0xF5, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x3B, 0x2C, 0xB9, 0x2D, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3D, 0x29, 0x21, 0x1D, 0x01, 0x55, 0x4E, 0x4C, 0x01, 0xA9, 0xA8, 0xA6, + 0x01, 0xF0, 0xF0, 0xEF, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xF7, 0xF7, 0xF6, 0x01, 0xB8, 0xB7, 0xB6, + 0x01, 0x67, 0x63, 0x5F, 0x16, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x18, 0x57, 0x03, 0x27, 0x18, 0xB0, + 0x01, 0x2D, 0x1F, 0xC0, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE2, + 0x02, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x03, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x43, 0x3A, 0xEC, 0x03, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, + 0x02, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x35, 0x26, 0x93, 0x2C, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0x85, 0x81, 0x7F, 0x01, 0xD5, 0xD3, 0xD3, 0x0B, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD4, 0xD4, + 0x01, 0x88, 0x85, 0x83, 0x01, 0x38, 0x30, 0x2C, 0x17, 0x29, 0x21, 0x1D, 0x01, 0x29, 0x1E, 0x36, + 0x01, 0x27, 0x17, 0xA9, 0x02, 0x27, 0x18, 0xB0, 0x01, 0x29, 0x1A, 0xB6, 0x01, 0x34, 0x32, 0xDA, + 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x04, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x02, 0x3E, 0x38, 0xE8, 0x04, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, 0x02, 0x42, 0x3A, 0xEB, + 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x39, 0xEC, 0x01, 0x42, 0x3A, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xEF, + 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, + 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3E, 0xF5, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x49, 0x3C, 0xF3, + 0x01, 0x2D, 0x22, 0x56, 0x2B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xED, 0xED, 0xED, 0x01, 0xA8, 0xA6, 0xA5, 0x01, 0x54, 0x4E, 0x4A, + 0x1A, 0x29, 0x21, 0x1D, 0x01, 0x26, 0x15, 0x8D, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x30, 0x2B, 0xD1, + 0x01, 0x34, 0x35, 0xDD, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x38, 0x36, 0xE0, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, 0x02, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE3, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x02, 0x3A, 0x37, 0xE4, + 0x04, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x02, 0x3E, 0x38, 0xE8, 0x04, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, + 0x02, 0x42, 0x3A, 0xEB, 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, + 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x42, 0x3A, 0xED, 0x01, 0x43, 0x3B, 0xED, + 0x02, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, + 0x01, 0x44, 0x3B, 0xEF, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, + 0x01, 0x45, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF5, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x42, 0x33, 0xDC, 0x2B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0x81, 0x7D, 0x7B, 0x01, 0x2D, 0x26, 0x21, + 0x1B, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x19, 0x53, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2B, 0x1F, 0xBE, + 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, 0x03, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, + 0x02, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x02, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x04, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x38, 0xE9, 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, + 0x02, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, + 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x03, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x03, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x33, 0x25, 0x8D, + 0x2A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x09, 0xFF, 0xFF, 0xFF, + 0x01, 0xF5, 0xF5, 0xF5, 0x01, 0xB7, 0xB4, 0xB3, 0x01, 0x64, 0x60, 0x5C, 0x1A, 0x29, 0x21, 0x1D, + 0x01, 0x28, 0x16, 0x98, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x2E, 0xD4, 0x02, 0x34, 0x35, 0xDD, + 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x04, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x02, 0x3E, 0x38, 0xE8, 0x04, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, 0x02, 0x42, 0x3A, 0xEB, + 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x39, 0xEC, 0x01, 0x42, 0x3A, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xEF, + 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, + 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3E, 0xF5, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x44, 0x37, 0xE7, 0x2A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xC5, 0xC4, 0xC3, 0x01, 0xFC, 0xFC, 0xFC, 0x0A, 0xFF, 0xFF, 0xFF, + 0x01, 0xE2, 0xE1, 0xE1, 0x01, 0x97, 0x94, 0x92, 0x01, 0x44, 0x3D, 0x39, 0x16, 0x29, 0x21, 0x1D, + 0x01, 0x28, 0x1A, 0x4E, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2B, 0x1D, 0xBC, 0x01, 0x33, 0x34, 0xDC, + 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, 0x03, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, + 0x02, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x02, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x04, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x38, 0xE9, 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, + 0x02, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, + 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x03, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x03, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x34, 0x24, 0x84, 0x29, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3C, 0x29, 0x21, 0x1D, + 0x01, 0x44, 0x3E, 0x3A, 0x01, 0x9B, 0x98, 0x96, 0x01, 0xE6, 0xE5, 0xE5, 0x0A, 0xFF, 0xFF, 0xFF, + 0x01, 0xFC, 0xFC, 0xFC, 0x01, 0xC6, 0xC5, 0xC4, 0x01, 0x77, 0x73, 0x71, 0x01, 0x2D, 0x26, 0x21, + 0x13, 0x29, 0x21, 0x1D, 0x01, 0x26, 0x14, 0x84, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2F, 0x29, 0xCE, + 0x01, 0x33, 0x34, 0xDC, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x35, 0xDE, + 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, 0x03, 0x38, 0x36, 0xE1, + 0x01, 0x39, 0x37, 0xE2, 0x02, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, + 0x02, 0x3D, 0x38, 0xE6, 0x02, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x04, 0x3E, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE9, 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xE9, 0x02, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, + 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3B, 0xEF, 0x03, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x46, 0x3C, 0xF0, + 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x02, 0x49, 0x3D, 0xF2, 0x03, 0x49, 0x3D, 0xF3, 0x03, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, + 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x41, 0x32, 0xD3, 0x29, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3F, 0x29, 0x21, 0x1D, 0x01, 0x6B, 0x66, 0x64, 0x01, 0xBE, 0xBC, 0xBB, 0x01, 0xF9, 0xF9, 0xF9, + 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xEE, 0xEE, 0xED, 0x01, 0xA9, 0xA7, 0xA6, 0x01, 0x55, 0x4E, 0x4C, + 0x10, 0x29, 0x21, 0x1D, 0x01, 0x29, 0x20, 0x24, 0x01, 0x27, 0x17, 0xAC, 0x02, 0x27, 0x18, 0xB0, + 0x01, 0x29, 0x18, 0xB2, 0x01, 0x33, 0x33, 0xDA, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x75, 0x71, 0xEA, 0x01, 0xB9, 0xB7, 0xF4, 0x01, 0xE4, 0xE3, 0xFB, 0x02, 0xF7, 0xF6, 0xFE, + 0x01, 0xE4, 0xE3, 0xFB, 0x01, 0xB9, 0xB7, 0xF4, 0x01, 0x77, 0x72, 0xEB, 0x01, 0x3A, 0x37, 0xE4, + 0x02, 0x3C, 0x37, 0xE4, 0x01, 0x3D, 0x38, 0xE5, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, + 0x01, 0x3C, 0x38, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x39, 0xE8, + 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x40, 0x39, 0xEB, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x05, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x7D, 0x74, 0xF2, 0x01, 0xBC, 0xB8, 0xF8, 0x01, 0xE6, 0xE4, 0xFC, + 0x02, 0xF7, 0xF6, 0xFE, 0x01, 0xE6, 0xE4, 0xFC, 0x01, 0xBD, 0xB8, 0xF8, 0x01, 0x7D, 0x74, 0xF4, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x45, 0x3C, 0xF0, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4B, 0x3F, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, 0x02, 0x4B, 0x3F, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x2B, 0x22, 0x30, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x41, 0x29, 0x21, 0x1D, + 0x01, 0x3C, 0x36, 0x32, 0x01, 0x91, 0x8F, 0x8D, 0x01, 0xDF, 0xDE, 0xDD, 0x0B, 0xFF, 0xFF, 0xFF, + 0x01, 0xD6, 0xD6, 0xD5, 0x01, 0x7A, 0x76, 0x74, 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x1A, 0x4D, + 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2B, 0x1D, 0xBC, 0x01, 0x33, 0x34, 0xDD, 0x01, 0x33, 0x34, 0xDC, + 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x5B, 0x57, 0xE5, + 0x01, 0xD4, 0xD2, 0xF8, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0xD5, 0xD2, 0xF9, 0x01, 0x5D, 0x57, 0xE8, + 0x02, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x02, 0x3D, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE7, 0x04, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE9, + 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x02, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x64, 0x5B, 0xF0, 0x01, 0xD5, 0xD3, 0xFA, 0x08, 0xFF, 0xFF, 0xFF, + 0x01, 0xD6, 0xD3, 0xFB, 0x01, 0x67, 0x5B, 0xF2, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, + 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF2, 0x03, 0x49, 0x3D, 0xF3, + 0x03, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x01, 0x34, 0x24, 0x82, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x44, 0x29, 0x21, 0x1D, + 0x01, 0x62, 0x5C, 0x5A, 0x01, 0xB6, 0xB3, 0xB2, 0x01, 0xF6, 0xF6, 0xF6, 0x09, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x15, 0x72, 0x03, 0x27, 0x18, 0xB0, + 0x01, 0x2C, 0x24, 0xC8, 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x70, 0x6C, 0xE8, 0x01, 0xF3, 0xF3, 0xFD, + 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFD, 0x01, 0x72, 0x6D, 0xEB, 0x01, 0x3D, 0x38, 0xE5, + 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3F, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x39, 0xE8, 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, + 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x39, 0xEC, 0x03, 0x43, 0x3B, 0xED, 0x01, 0x77, 0x6E, 0xF1, 0x01, 0xF4, 0xF3, 0xFE, + 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFE, 0x01, 0x7A, 0x6F, 0xF4, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x46, 0x3C, 0xF1, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4B, 0x3F, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, + 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x3C, 0x2C, 0xBB, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xD6, 0xD4, 0xD4, 0x0A, 0xDE, 0xDD, 0xDC, 0x01, 0xE8, 0xE7, 0xE6, + 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x26, 0x15, 0x8A, + 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2F, 0x29, 0xCF, 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, + 0x02, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x34, 0x35, 0xDE, + 0x02, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, + 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x5A, 0x57, 0xE4, 0x01, 0xF3, 0xF3, 0xFD, + 0x0C, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFD, 0x01, 0x5F, 0x58, 0xE9, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x39, 0xE8, 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, + 0x02, 0x43, 0x3B, 0xED, 0x01, 0x63, 0x5B, 0xEF, 0x01, 0xF4, 0xF3, 0xFE, 0x0C, 0xFF, 0xFF, 0xFF, + 0x01, 0xF4, 0xF3, 0xFE, 0x01, 0x67, 0x5B, 0xF3, 0x01, 0x46, 0x3C, 0xF1, 0x02, 0x48, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4B, 0x3F, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, + 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x42, 0x33, 0xD8, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x27, 0x16, 0x9C, 0x03, 0x27, 0x18, 0xB0, + 0x01, 0x32, 0x2F, 0xD5, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x34, 0xDD, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xE0, 0x01, 0x38, 0x36, 0xE0, 0x01, 0xD4, 0xD2, 0xF7, 0x0E, 0xFF, 0xFF, 0xFF, + 0x01, 0xD5, 0xD2, 0xF9, 0x01, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3E, 0x39, 0xE8, 0x05, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, + 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0xD5, 0xD3, 0xFA, 0x0E, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD3, 0xFB, + 0x02, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x04, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x02, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x48, 0x39, 0xEA, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xD1, 0xD1, 0xD0, 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x26, 0x17, 0xA7, 0x03, 0x27, 0x18, 0xB0, + 0x01, 0x32, 0x31, 0xD9, 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, + 0x01, 0x75, 0x71, 0xE9, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xBE, 0xBC, 0xF5, 0x05, 0xA7, 0xA3, 0xF3, + 0x01, 0xA7, 0xA4, 0xF4, 0x01, 0xA7, 0xA3, 0xF3, 0x02, 0xA8, 0xA4, 0xF4, 0x01, 0xA7, 0xA4, 0xF4, + 0x02, 0xA8, 0xA4, 0xF4, 0x06, 0xA8, 0xA4, 0xF5, 0x01, 0xA9, 0xA4, 0xF5, 0x01, 0xA8, 0xA4, 0xF5, + 0x03, 0xA9, 0xA4, 0xF5, 0x01, 0xA9, 0xA4, 0xF6, 0x01, 0xC0, 0xBD, 0xF8, 0x10, 0xFF, 0xFF, 0xFF, + 0x01, 0x7E, 0x74, 0xF4, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4B, 0x3F, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, + 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4A, 0x3B, 0xF2, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xD0, 0xCF, 0xCE, 0x0E, 0x29, 0x21, 0x1D, + 0x01, 0x27, 0x17, 0xAD, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDB, 0x01, 0x34, 0x35, 0xDD, + 0x01, 0x33, 0x34, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x35, 0xDE, + 0x01, 0x34, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0xB9, 0xB7, 0xF3, + 0x3A, 0xFF, 0xFF, 0xFF, 0x01, 0xBE, 0xB9, 0xFA, 0x01, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, + 0x04, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3E, 0xF6, 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, + 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x34, 0xDC, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x34, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDE, + 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0xE4, 0xE3, 0xFA, 0x3A, 0xFF, 0xFF, 0xFF, + 0x01, 0xE6, 0xE4, 0xFC, 0x01, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x04, 0x49, 0x3D, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0x99, 0x96, 0x94, 0x14, 0xA2, 0x9F, 0x9E, 0x01, 0x7C, 0x78, 0x76, 0x0E, 0x29, 0x21, 0x1D, + 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x33, 0xDC, + 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x03, 0x37, 0x36, 0xE0, + 0x01, 0xF7, 0xF6, 0xFE, 0x3A, 0xFF, 0xFF, 0xFF, 0x01, 0xF7, 0xF6, 0xFE, 0x01, 0x48, 0x3C, 0xF2, + 0x03, 0x48, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x03, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x5F, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x34, 0xDC, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x34, 0xDD, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xE0, 0x01, 0xF7, 0xF6, 0xFE, 0x3A, 0xFF, 0xFF, 0xFF, 0x01, 0xF7, 0xF6, 0xFE, + 0x01, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x04, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x02, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x5F, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x33, 0xDC, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x33, 0xDC, 0x03, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x03, 0x37, 0x36, 0xE0, 0x01, 0xE4, 0xE3, 0xFA, + 0x3A, 0xFF, 0xFF, 0xFF, 0x01, 0xE6, 0xE4, 0xFC, 0x01, 0x48, 0x3C, 0xF2, 0x03, 0x48, 0x3D, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x03, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x5F, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, + 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x33, 0xDC, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x03, 0x37, 0x36, 0xE0, 0x01, 0xB9, 0xB7, 0xF4, 0x3A, 0xFF, 0xFF, 0xFF, + 0x01, 0xBD, 0xB8, 0xF9, 0x01, 0x48, 0x3C, 0xF2, 0x03, 0x48, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x03, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xBF, 0xBD, 0xBC, 0x14, 0xC7, 0xC5, 0xC5, 0x01, 0x9A, 0x97, 0x95, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDD, + 0x02, 0x34, 0x35, 0xDD, 0x02, 0x35, 0x35, 0xDE, 0x02, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, + 0x01, 0x74, 0x71, 0xE8, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xBE, 0xBC, 0xF5, 0x03, 0xA7, 0xA3, 0xF3, + 0x02, 0xA7, 0xA4, 0xF3, 0x02, 0xA7, 0xA3, 0xF3, 0x01, 0xA7, 0xA4, 0xF4, 0x01, 0xA7, 0xA3, 0xF4, + 0x03, 0xA8, 0xA4, 0xF4, 0x07, 0xA8, 0xA4, 0xF5, 0x05, 0xA9, 0xA4, 0xF5, 0x01, 0xED, 0xEB, 0xFC, + 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0x7F, 0x75, 0xF5, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3C, 0xF3, 0x03, 0x49, 0x3D, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x33, 0xDC, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x33, 0xDC, 0x03, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x03, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, + 0x01, 0xD4, 0xD2, 0xF7, 0x0E, 0xFF, 0xFF, 0xFF, 0x01, 0xD5, 0xD3, 0xF9, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x39, 0xE6, 0x01, 0x3C, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE6, 0x02, 0x3D, 0x38, 0xE7, + 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, 0x02, 0x3F, 0x39, 0xE9, + 0x02, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x03, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3B, 0xED, + 0x01, 0xA0, 0x9A, 0xF5, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD3, 0xFC, 0x01, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3C, 0xF2, 0x03, 0x48, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x03, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDD, 0x02, 0x34, 0x35, 0xDD, 0x02, 0x35, 0x35, 0xDE, + 0x02, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x5A, 0x57, 0xE4, + 0x01, 0xF3, 0xF3, 0xFD, 0x0C, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFD, 0x01, 0x5E, 0x58, 0xE9, + 0x01, 0x3C, 0x38, 0xE5, 0x03, 0x3D, 0x38, 0xE6, 0x02, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, + 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x01, 0xA0, 0x9A, 0xF5, + 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFE, 0x01, 0x67, 0x5B, 0xF3, 0x01, 0x48, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, + 0x01, 0x49, 0x3C, 0xF3, 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDD, + 0x02, 0x34, 0x35, 0xDD, 0x02, 0x35, 0x35, 0xDE, 0x02, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, + 0x02, 0x37, 0x36, 0xE0, 0x01, 0x70, 0x6C, 0xE8, 0x01, 0xF3, 0xF3, 0xFD, 0x0A, 0xFF, 0xFF, 0xFF, + 0x01, 0xF4, 0xF3, 0xFD, 0x01, 0x72, 0x6C, 0xEB, 0x02, 0x3C, 0x38, 0xE5, 0x03, 0x3D, 0x38, 0xE6, + 0x02, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, + 0x01, 0xA0, 0x9A, 0xF5, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFE, 0x01, 0x79, 0x6F, 0xF4, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3C, 0xF3, 0x03, 0x49, 0x3D, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x02, 0x33, 0x34, 0xDC, 0x03, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, + 0x02, 0x38, 0x36, 0xE1, 0x01, 0x5C, 0x58, 0xE6, 0x01, 0xD4, 0xD2, 0xF8, 0x08, 0xFF, 0xFF, 0xFF, + 0x01, 0xD5, 0xD2, 0xF9, 0x01, 0x5D, 0x58, 0xE8, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3D, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x39, 0xE9, 0x04, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x02, 0x40, 0x39, 0xEB, 0x01, 0xA0, 0x9A, 0xF5, + 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD3, 0xFB, 0x01, 0x67, 0x5B, 0xF3, 0x01, 0x46, 0x3C, 0xF1, + 0x02, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, + 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xA7, 0xA4, 0xA3, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, + 0x01, 0x33, 0x34, 0xDD, 0x02, 0x34, 0x35, 0xDD, 0x02, 0x35, 0x35, 0xDE, 0x02, 0x34, 0x35, 0xDE, + 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xE0, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x76, 0x72, 0xEA, 0x01, 0xB9, 0xB7, 0xF4, 0x01, 0xE4, 0xE3, 0xFB, + 0x02, 0xF7, 0xF6, 0xFE, 0x01, 0xE4, 0xE3, 0xFB, 0x01, 0xB9, 0xB7, 0xF4, 0x01, 0x77, 0x72, 0xEB, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3C, 0x38, 0xE5, + 0x03, 0x3D, 0x38, 0xE6, 0x02, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, + 0x01, 0xA0, 0x9A, 0xF5, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xBA, 0xB6, 0xF8, 0x01, 0xBC, 0xB8, 0xF8, + 0x01, 0xE6, 0xE4, 0xFC, 0x02, 0xF7, 0xF6, 0xFE, 0x01, 0xE6, 0xE4, 0xFC, 0x01, 0xBD, 0xB8, 0xF9, + 0x01, 0x7E, 0x74, 0xF4, 0x02, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, + 0x01, 0x49, 0x3C, 0xF3, 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x64, 0x60, 0x5C, 0x09, 0x6E, 0x6A, 0x68, + 0x01, 0x80, 0x7C, 0x7A, 0x01, 0xF4, 0xF4, 0xF4, 0x07, 0xFF, 0xFF, 0xFF, 0x01, 0xF1, 0xF0, 0xF0, + 0x01, 0x7A, 0x75, 0x73, 0x0F, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x02, 0x33, 0x34, 0xDC, + 0x03, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x35, 0x36, 0xDF, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, + 0x01, 0x39, 0x37, 0xE2, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, + 0x01, 0x39, 0x36, 0xE3, 0x04, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, 0x04, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0x9F, 0x9A, 0xF4, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF6, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x02, 0x45, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x02, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, + 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x44, 0x29, 0x21, 0x1D, 0x01, 0x73, 0x6F, 0x6D, + 0x01, 0xED, 0xED, 0xED, 0x07, 0xFF, 0xFF, 0xFF, 0x01, 0xC9, 0xC7, 0xC6, 0x01, 0x44, 0x3D, 0x39, + 0x10, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x02, 0x33, 0x34, 0xDC, 0x03, 0x34, 0x35, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, + 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, + 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x04, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE8, + 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, 0x04, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, + 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x01, 0xA0, 0x9A, 0xF4, 0x09, 0xFF, 0xFF, 0xFF, + 0x01, 0xA1, 0x9A, 0xF6, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x02, 0x45, 0x3B, 0xEF, + 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x02, 0x46, 0x3C, 0xF2, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x03, 0x49, 0x3D, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, + 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x02, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x42, 0x29, 0x21, 0x1D, 0x01, 0x36, 0x2F, 0x2B, 0x01, 0xB5, 0xB2, 0xB1, + 0x07, 0xFF, 0xFF, 0xFF, 0x01, 0xF7, 0xF7, 0xF6, 0x01, 0x8B, 0x88, 0x86, 0x12, 0x29, 0x21, 0x1D, + 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x34, 0xDD, + 0x04, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0x38, 0x36, 0xE1, + 0x01, 0x38, 0x36, 0xE2, 0x04, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x03, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, + 0x02, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x9F, 0x9A, 0xF4, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA1, 0x9B, 0xF6, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, + 0x02, 0x45, 0x3C, 0xEF, 0x04, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x03, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x01, 0x4C, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x41, 0x29, 0x21, 0x1D, + 0x01, 0x66, 0x62, 0x5E, 0x01, 0xE7, 0xE6, 0xE5, 0x07, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD4, 0xD4, + 0x01, 0x4E, 0x48, 0x45, 0x13, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x02, 0x33, 0x34, 0xDC, + 0x03, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x35, 0x36, 0xDF, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, + 0x01, 0x39, 0x37, 0xE2, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, + 0x01, 0x39, 0x36, 0xE3, 0x04, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, 0x04, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x9F, 0x9A, 0xF4, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF5, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x02, 0x45, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x02, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, + 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, 0x01, 0x30, 0x28, 0x24, + 0x01, 0xA8, 0xA5, 0xA4, 0x01, 0xFD, 0xFD, 0xFD, 0x06, 0xFF, 0xFF, 0xFF, 0x01, 0xFB, 0xFB, 0xFB, + 0x01, 0x9C, 0x99, 0x97, 0x01, 0x2C, 0x24, 0x20, 0x14, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x33, 0xDC, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x34, 0xDD, 0x04, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE2, + 0x04, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x03, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x02, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x9E, 0x9A, 0xF3, + 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF5, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, + 0x02, 0x45, 0x3C, 0xEF, 0x04, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x03, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x01, 0x4C, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3E, 0x29, 0x21, 0x1D, + 0x01, 0x5A, 0x55, 0x51, 0x01, 0xDE, 0xDD, 0xDC, 0x07, 0xFF, 0xFF, 0xFF, 0x01, 0xE1, 0xE0, 0xDF, + 0x01, 0x5C, 0x57, 0x54, 0x16, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, + 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x34, 0xDD, 0x04, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE2, 0x04, 0x39, 0x36, 0xE2, + 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x03, 0x3C, 0x38, 0xE5, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x02, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, + 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x9F, 0x9A, 0xF4, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF5, + 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, 0x04, 0x45, 0x3C, 0xF0, + 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, + 0x03, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4C, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3C, 0x29, 0x21, 0x1D, 0x01, 0x2C, 0x24, 0x20, 0x01, 0x9A, 0x97, 0x95, + 0x01, 0xFA, 0xFA, 0xFA, 0x06, 0xFF, 0xFF, 0xFF, 0x01, 0xFE, 0xFE, 0xFE, 0x01, 0xAB, 0xA9, 0xA8, + 0x01, 0x33, 0x2B, 0x27, 0x17, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x02, 0x33, 0x34, 0xDC, + 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDE, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, 0x03, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x37, 0xE4, 0x02, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3C, 0x38, 0xE6, + 0x01, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, + 0x04, 0x3E, 0x39, 0xE8, 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x9F, 0x9A, 0xF3, 0x09, 0xFF, 0xFF, 0xFF, + 0x01, 0xA0, 0x9A, 0xF5, 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x03, 0x44, 0x3B, 0xEE, + 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x02, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, + 0x01, 0x45, 0x3B, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x03, 0x49, 0x3D, 0xF3, + 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, + 0x03, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x4E, 0x48, 0x45, + 0x01, 0xD5, 0xD3, 0xD3, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0xE5, 0xE4, 0xE4, 0x0A, 0xB4, 0xB2, 0xB0, + 0x01, 0x8A, 0x87, 0x85, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, + 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x34, 0xDD, 0x04, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE2, 0x04, 0x39, 0x36, 0xE2, + 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x03, 0x3C, 0x38, 0xE5, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x02, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x9E, 0x9A, 0xF2, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF5, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, + 0x02, 0x45, 0x3C, 0xEF, 0x04, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x03, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x01, 0x4C, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0xF7, 0xF7, 0xF6, 0x14, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, + 0x04, 0x27, 0x18, 0xB0, 0x02, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDE, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, + 0x03, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x02, 0x3A, 0x36, 0xE4, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3C, 0x37, 0xE4, + 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3C, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x01, 0x78, 0x72, 0xEC, + 0x01, 0xBB, 0xB7, 0xF5, 0x01, 0xE5, 0xE3, 0xFB, 0x02, 0xF7, 0xF6, 0xFE, 0x01, 0xE5, 0xE4, 0xFC, + 0x01, 0xBB, 0xB7, 0xF6, 0x01, 0xB8, 0xB6, 0xF5, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF5, + 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x03, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x02, 0x45, 0x3C, 0xF0, + 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3B, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x03, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4C, 0x3F, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x02, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDE, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, 0x03, 0x38, 0x36, 0xE1, + 0x01, 0x39, 0x37, 0xE2, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x02, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, + 0x01, 0x3C, 0x38, 0xE6, 0x01, 0x5E, 0x58, 0xE9, 0x01, 0xD5, 0xD3, 0xF9, 0x10, 0xFF, 0xFF, 0xFF, + 0x01, 0xA0, 0x9A, 0xF4, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, + 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x03, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3B, 0xEF, + 0x01, 0x44, 0x3B, 0xEF, 0x02, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3B, 0xF0, + 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x03, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x04, 0x34, 0x35, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x03, 0x37, 0x36, 0xDF, + 0x02, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x39, 0x36, 0xE2, 0x03, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x39, 0x37, 0xE3, + 0x02, 0x39, 0x36, 0xE3, 0x02, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x37, 0xE4, 0x02, 0x3A, 0x37, 0xE4, + 0x01, 0x3D, 0x38, 0xE5, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x73, 0x6E, 0xEC, 0x01, 0xF4, 0xF3, 0xFD, + 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0x9F, 0x9A, 0xF4, 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, + 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x02, 0x43, 0x3B, 0xED, + 0x04, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x03, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, + 0x01, 0x48, 0x3C, 0xF2, 0x02, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF4, + 0x01, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x04, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x02, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDE, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, 0x03, 0x38, 0x36, 0xE1, + 0x01, 0x39, 0x37, 0xE2, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x02, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x5E, 0x58, 0xE9, 0x01, 0xF4, 0xF3, 0xFD, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0x9F, 0x9A, 0xF4, + 0x02, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, + 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x03, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3B, 0xEF, + 0x01, 0x44, 0x3B, 0xEF, 0x02, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3B, 0xF0, + 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x03, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x04, 0x34, 0x35, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x03, 0x37, 0x36, 0xDF, + 0x02, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x39, 0x36, 0xE2, 0x03, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x39, 0x37, 0xE3, + 0x02, 0x39, 0x36, 0xE3, 0x02, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x37, 0xE4, 0x02, 0x3A, 0x37, 0xE4, + 0x01, 0x3D, 0x38, 0xE5, 0x01, 0xD5, 0xD2, 0xF9, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF4, + 0x01, 0x40, 0x3A, 0xEB, 0x02, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x04, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x03, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x02, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x03, 0x4A, 0x3E, 0xF5, 0x04, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x7A, 0x76, 0x74, + 0x14, 0x85, 0x81, 0x7F, 0x01, 0x64, 0x60, 0x5C, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x33, 0xDC, 0x04, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, + 0x01, 0x34, 0x35, 0xDE, 0x03, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x39, 0x36, 0xE2, 0x03, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE3, 0x01, 0x39, 0x37, 0xE3, 0x02, 0x39, 0x36, 0xE3, 0x02, 0x3A, 0x37, 0xE4, + 0x02, 0x3C, 0x37, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x78, 0x72, 0xEC, 0x05, 0xFF, 0xFF, 0xFF, + 0x01, 0xE5, 0xE1, 0xFC, 0x01, 0x81, 0x6A, 0xF2, 0x02, 0x44, 0x29, 0xED, 0x01, 0x81, 0x6A, 0xF2, + 0x01, 0xE5, 0xE1, 0xFC, 0x05, 0xFF, 0xFF, 0xFF, 0x01, 0xB9, 0xB6, 0xF7, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0x40, 0x3A, 0xEB, 0x02, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x04, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x03, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x02, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x03, 0x4A, 0x3E, 0xF5, 0x04, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x5F, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x02, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x04, 0x34, 0x35, 0xDE, 0x04, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, + 0x03, 0x38, 0x36, 0xE1, 0x04, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, + 0x01, 0xBA, 0xB7, 0xF5, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xE5, 0xE1, 0xFC, 0x01, 0x48, 0x2B, 0xED, + 0x04, 0x38, 0x23, 0xEC, 0x01, 0x48, 0x2B, 0xED, 0x01, 0xE5, 0xE1, 0xFC, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xBB, 0xB8, 0xF7, 0x02, 0x40, 0x39, 0xEA, 0x02, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, + 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x04, 0x43, 0x3B, 0xED, + 0x02, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xED, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, + 0x04, 0x45, 0x3C, 0xF0, 0x04, 0x46, 0x3C, 0xF1, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF5, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, + 0x02, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x5F, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x04, 0x34, 0x35, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x03, 0x37, 0x36, 0xDF, + 0x02, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x39, 0x36, 0xE2, 0x03, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x39, 0x37, 0xE3, + 0x02, 0x39, 0x36, 0xE3, 0x02, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x37, 0xE4, 0x02, 0x3A, 0x37, 0xE4, + 0x01, 0xE5, 0xE3, 0xFB, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x81, 0x6A, 0xF2, 0x06, 0x38, 0x23, 0xEC, + 0x01, 0x81, 0x6A, 0xF2, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xE5, 0xE4, 0xFC, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0x40, 0x3A, 0xEB, 0x02, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x04, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x03, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x02, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x03, 0x4A, 0x3E, 0xF5, 0x04, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x5F, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x02, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x04, 0x34, 0x35, 0xDE, 0x04, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, + 0x03, 0x38, 0x36, 0xE1, 0x04, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, + 0x01, 0xF7, 0xF6, 0xFE, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x44, 0x29, 0xED, 0x06, 0x38, 0x23, 0xEC, + 0x01, 0x44, 0x29, 0xED, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF7, 0xF6, 0xFE, 0x02, 0x40, 0x39, 0xEA, + 0x02, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x3A, 0xEC, 0x04, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xED, + 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x04, 0x45, 0x3C, 0xF0, 0x04, 0x46, 0x3C, 0xF1, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x02, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xBF, 0xBD, 0xBC, + 0x14, 0xC7, 0xC5, 0xC5, 0x01, 0x9A, 0x97, 0x95, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x02, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x04, 0x34, 0x35, 0xDE, 0x04, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, + 0x03, 0x38, 0x36, 0xE1, 0x04, 0x39, 0x36, 0xE2, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, + 0x01, 0xF7, 0xF6, 0xFE, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x44, 0x29, 0xED, 0x06, 0x38, 0x23, 0xEC, + 0x01, 0x44, 0x29, 0xED, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF7, 0xF6, 0xFE, 0x02, 0x40, 0x39, 0xEA, + 0x02, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x3A, 0xEC, 0x04, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xED, + 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x04, 0x45, 0x3C, 0xF0, 0x04, 0x46, 0x3C, 0xF1, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x02, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, + 0x01, 0x33, 0x34, 0xDD, 0x02, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDE, + 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x02, 0x39, 0x36, 0xE3, 0x03, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3C, 0x37, 0xE4, 0x01, 0xE5, 0xE3, 0xFB, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0x81, 0x6A, 0xF2, 0x06, 0x38, 0x23, 0xEC, 0x01, 0x81, 0x6A, 0xF2, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xE5, 0xE4, 0xFC, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x40, 0x39, 0xEB, + 0x01, 0x42, 0x3A, 0xEB, 0x03, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xED, + 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x02, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x02, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, + 0x04, 0x34, 0x35, 0xDE, 0x04, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, + 0x02, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x03, 0x38, 0x36, 0xE1, 0x04, 0x39, 0x36, 0xE2, + 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x02, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x01, 0xBA, 0xB7, 0xF5, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xE5, 0xE1, 0xFC, 0x01, 0x48, 0x2B, 0xED, 0x04, 0x38, 0x23, 0xEC, 0x01, 0x48, 0x2B, 0xED, + 0x01, 0xE5, 0xE1, 0xFC, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xBB, 0xB8, 0xF7, 0x02, 0x40, 0x39, 0xEA, + 0x02, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0x42, 0x3A, 0xEC, 0x04, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xED, + 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x04, 0x45, 0x3C, 0xF0, 0x04, 0x46, 0x3C, 0xF1, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x02, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, + 0x01, 0x33, 0x34, 0xDD, 0x02, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDE, + 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE0, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x02, 0x39, 0x36, 0xE3, 0x03, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3C, 0x37, 0xE4, 0x01, 0x77, 0x72, 0xEC, 0x05, 0xFF, 0xFF, 0xFF, + 0x01, 0xE5, 0xE1, 0xFC, 0x01, 0x81, 0x6A, 0xF2, 0x02, 0x44, 0x29, 0xED, 0x01, 0x81, 0x6A, 0xF2, + 0x01, 0xE5, 0xE1, 0xFC, 0x05, 0xFF, 0xFF, 0xFF, 0x01, 0xB9, 0xB6, 0xF7, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEB, 0x03, 0x42, 0x3A, 0xEC, + 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x49, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4C, 0x3F, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDD, 0x02, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDE, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x02, 0x39, 0x36, 0xE3, + 0x03, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0xD5, 0xD2, 0xF9, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0x9F, 0x9A, 0xF4, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEB, 0x03, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x44, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x01, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x48, 0x3D, 0xF2, + 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3D, 0xF4, + 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, + 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x34, 0xDD, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, + 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3D, 0x38, 0xE5, 0x01, 0x5E, 0x58, 0xE9, 0x01, 0xF4, 0xF3, 0xFD, + 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0x9F, 0x9A, 0xF4, 0x02, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, + 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, + 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x45, 0x3B, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xFE, 0xFE, 0xFE, 0x03, 0x70, 0x6C, 0x69, 0x01, 0xB7, 0xB5, 0xB4, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x9F, 0x9D, 0x9C, 0x02, 0x70, 0x6C, 0x69, 0x01, 0x96, 0x93, 0x91, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDD, 0x02, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDE, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x02, 0x39, 0x36, 0xE3, + 0x03, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, + 0x01, 0x73, 0x6D, 0xEC, 0x01, 0xF4, 0xF3, 0xFD, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0x9F, 0x9A, 0xF4, + 0x01, 0x42, 0x3A, 0xEB, 0x03, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xED, + 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x02, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4C, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF2, 0xF1, 0xF1, + 0x03, 0x29, 0x21, 0x1D, 0x01, 0x8C, 0x88, 0x87, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x68, 0x63, 0x61, + 0x02, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDC, + 0x01, 0x33, 0x34, 0xDD, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, + 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x35, 0xE0, + 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x37, 0xE3, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3D, 0x38, 0xE5, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x5F, 0x58, 0xE9, + 0x01, 0xD5, 0xD3, 0xF9, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF4, 0x01, 0x42, 0x39, 0xEB, + 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, + 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x45, 0x3B, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF2, 0xF1, 0xF1, 0x03, 0x29, 0x21, 0x1D, 0x01, 0x8C, 0x88, 0x87, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x68, 0x63, 0x61, 0x02, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x34, 0xDD, 0x03, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x3A, 0x37, 0xE3, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3D, 0x38, 0xE5, 0x01, 0x3C, 0x38, 0xE5, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x01, 0x78, 0x72, 0xED, 0x01, 0xBA, 0xB7, 0xF5, + 0x01, 0xE5, 0xE4, 0xFC, 0x02, 0xF7, 0xF6, 0xFE, 0x01, 0xE5, 0xE3, 0xFC, 0x01, 0xBB, 0xB7, 0xF6, + 0x01, 0xB8, 0xB6, 0xF5, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF4, 0x01, 0x42, 0x3A, 0xEC, + 0x02, 0x43, 0x3B, 0xED, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, + 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, + 0x01, 0x45, 0x3B, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x02, 0x48, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, + 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xF2, 0xF1, 0xF1, 0x03, 0x29, 0x21, 0x1D, 0x01, 0x8C, 0x88, 0x87, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0x68, 0x63, 0x61, 0x02, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x34, 0xDC, + 0x02, 0x33, 0x33, 0xDC, 0x01, 0x34, 0x35, 0xDD, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xDF, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x04, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x39, 0x37, 0xE2, 0x02, 0x39, 0x36, 0xE2, 0x02, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, + 0x03, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x02, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x9E, 0x9A, 0xF2, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF5, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xEE, + 0x01, 0x45, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x49, 0x3C, 0xF3, 0x01, 0x49, 0x3D, 0xF4, 0x03, 0x4A, 0x3D, 0xF4, + 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x04, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xF2, 0xF1, 0xF1, 0x03, 0x29, 0x21, 0x1D, 0x01, 0x8C, 0x88, 0x87, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0x68, 0x63, 0x61, 0x02, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, + 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x34, 0xDD, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, + 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3D, 0x38, 0xE5, 0x01, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3D, 0x38, 0xE6, 0x03, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x9E, 0x9A, 0xF3, 0x09, 0xFF, 0xFF, 0xFF, + 0x01, 0xA0, 0x9A, 0xF5, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x01, 0x46, 0x3C, 0xF0, + 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x45, 0x3B, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF2, 0xF1, 0xF1, 0x03, 0x29, 0x21, 0x1D, 0x01, 0x8C, 0x88, 0x87, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x68, 0x63, 0x61, 0x02, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x34, 0xDC, 0x02, 0x33, 0x33, 0xDC, 0x01, 0x34, 0x35, 0xDD, 0x03, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x02, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x04, 0x38, 0x36, 0xE1, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE2, 0x02, 0x39, 0x36, 0xE2, 0x02, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x39, 0xE6, 0x03, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, + 0x02, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x39, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x9F, 0x9A, 0xF3, 0x09, 0xFF, 0xFF, 0xFF, + 0x01, 0xA0, 0x9A, 0xF5, 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEE, + 0x02, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, + 0x02, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x46, 0x3C, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x49, 0x3D, 0xF3, + 0x02, 0x49, 0x3C, 0xF3, 0x01, 0x49, 0x3D, 0xF4, 0x03, 0x4A, 0x3D, 0xF4, 0x02, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x04, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF2, 0xF1, 0xF1, + 0x03, 0x29, 0x21, 0x1D, 0x01, 0x8C, 0x88, 0x87, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x68, 0x63, 0x61, + 0x02, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x34, 0xDC, 0x02, 0x33, 0x33, 0xDC, + 0x01, 0x34, 0x35, 0xDD, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x04, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE2, + 0x02, 0x39, 0x36, 0xE2, 0x02, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x03, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x03, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x02, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x39, 0xE8, 0x03, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xE9, 0x01, 0x9F, 0x9A, 0xF4, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF5, + 0x04, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, + 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, + 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF2, + 0x03, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x49, 0x3C, 0xF3, + 0x01, 0x49, 0x3D, 0xF4, 0x03, 0x4A, 0x3D, 0xF4, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x04, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF2, 0xF1, 0xF1, 0x03, 0x29, 0x21, 0x1D, + 0x01, 0x8C, 0x88, 0x87, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x68, 0x63, 0x61, 0x02, 0x29, 0x21, 0x1D, + 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, + 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x34, 0xDC, 0x04, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x36, 0xDE, + 0x01, 0x35, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x39, 0xE6, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x9F, 0x9A, 0xF4, 0x09, 0xFF, 0xFF, 0xFF, + 0x01, 0xA1, 0x9B, 0xF6, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x03, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3B, 0xEF, 0x02, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x46, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x02, 0x49, 0x3D, 0xF3, 0x04, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF2, 0xF1, 0xF1, 0x03, 0x29, 0x21, 0x1D, + 0x01, 0x74, 0x70, 0x6E, 0x03, 0xE4, 0xE3, 0xE3, 0x01, 0xE3, 0xE2, 0xE2, 0x01, 0x55, 0x4F, 0x4D, + 0x02, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x34, 0xDC, 0x02, 0x33, 0x33, 0xDC, + 0x01, 0x34, 0x35, 0xDD, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x04, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE2, + 0x02, 0x39, 0x36, 0xE2, 0x02, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x03, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x03, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x02, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x39, 0xE8, 0x03, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x9F, 0x9A, 0xF4, + 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA0, 0x9A, 0xF6, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xEE, + 0x01, 0x45, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x49, 0x3C, 0xF3, 0x01, 0x49, 0x3D, 0xF4, 0x03, 0x4A, 0x3D, 0xF4, + 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x04, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x7F, 0x7B, 0x79, + 0x03, 0x88, 0x85, 0x83, 0x01, 0x79, 0x75, 0x73, 0x0B, 0x29, 0x21, 0x1D, 0x01, 0x33, 0x2C, 0x28, + 0x01, 0x88, 0x84, 0x82, 0x03, 0x88, 0x85, 0x83, 0x01, 0x68, 0x63, 0x61, 0x0E, 0x29, 0x21, 0x1D, + 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x34, 0xDC, 0x04, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x36, 0xDE, + 0x01, 0x35, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x39, 0xE6, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0xA0, 0x9A, 0xF4, + 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA1, 0x9A, 0xF6, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x03, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x02, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, + 0x04, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x5F, 0x29, 0x21, 0x1D, + 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x34, 0xDC, 0x04, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x36, 0xDE, + 0x01, 0x35, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x03, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x39, 0xE6, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x01, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0xA0, 0x9A, 0xF4, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xA1, 0x9B, 0xF6, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x03, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x02, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, + 0x04, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x5F, 0x29, 0x21, 0x1D, + 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, + 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, + 0x02, 0x38, 0x36, 0xE1, 0x02, 0x38, 0x36, 0xE2, 0x01, 0x76, 0x72, 0xEA, 0x01, 0xB9, 0xB7, 0xF4, + 0x01, 0xE4, 0xE3, 0xFB, 0x02, 0xF7, 0xF6, 0xFE, 0x01, 0xE4, 0xE3, 0xFB, 0x01, 0xB9, 0xB7, 0xF4, + 0x01, 0x77, 0x72, 0xEB, 0x03, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, + 0x01, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, + 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, + 0x01, 0x40, 0x39, 0xEB, 0x01, 0xA0, 0x9A, 0xF5, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xBB, 0xB6, 0xF8, + 0x01, 0xBC, 0xB8, 0xF8, 0x01, 0xE6, 0xE4, 0xFC, 0x02, 0xF7, 0xF6, 0xFE, 0x01, 0xE6, 0xE4, 0xFC, + 0x01, 0xBD, 0xB8, 0xF9, 0x01, 0x7D, 0x74, 0xF4, 0x01, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, + 0x03, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF3, + 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x4B, 0x29, 0x21, 0x1D, 0x01, 0x3F, 0x39, 0x35, 0x01, 0xB8, 0xB6, 0xB5, + 0x03, 0xB8, 0xB7, 0xB6, 0x01, 0x8F, 0x8B, 0x89, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x34, 0xDC, 0x04, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x36, 0xDE, 0x01, 0x35, 0x35, 0xDE, + 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x5C, 0x57, 0xE6, + 0x01, 0xD4, 0xD2, 0xF8, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0xD5, 0xD2, 0xF9, 0x01, 0x5E, 0x58, 0xE8, + 0x01, 0x3C, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3E, 0x39, 0xE7, 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x38, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x02, 0x42, 0x39, 0xEB, + 0x01, 0xA0, 0x9A, 0xF5, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD3, 0xFB, 0x01, 0x67, 0x5B, 0xF3, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, + 0x02, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF3, 0x04, 0x49, 0x3D, 0xF4, + 0x04, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x4B, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, 0x03, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0x38, 0x36, 0xE1, + 0x01, 0x70, 0x6C, 0xE8, 0x01, 0xF3, 0xF3, 0xFD, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFD, + 0x01, 0x72, 0x6D, 0xEB, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, + 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, + 0x02, 0x42, 0x3A, 0xEC, 0x01, 0xA0, 0x9A, 0xF5, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFE, + 0x01, 0x79, 0x6F, 0xF4, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x4B, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, 0x03, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x01, 0x5B, 0x57, 0xE5, + 0x01, 0xF3, 0xF3, 0xFD, 0x0C, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFD, 0x01, 0x5E, 0x58, 0xE9, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, + 0x01, 0xA0, 0x9A, 0xF5, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFE, 0x01, 0x67, 0x5B, 0xF3, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x4B, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x4B, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDC, + 0x03, 0x34, 0x35, 0xDD, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x38, 0x36, 0xE0, + 0x01, 0xD4, 0xD2, 0xF7, 0x0E, 0xFF, 0xFF, 0xFF, 0x01, 0xD5, 0xD2, 0xF9, 0x02, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x02, 0x3E, 0x38, 0xE8, 0x04, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, 0x02, 0x42, 0x3A, 0xEB, + 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, + 0x01, 0xA0, 0x9A, 0xF5, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD3, 0xFB, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3C, 0xF4, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF5, 0x02, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x4B, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, 0x03, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xE0, 0x01, 0x74, 0x71, 0xE8, 0x10, 0xFF, 0xFF, 0xFF, + 0x01, 0xBF, 0xBC, 0xF6, 0x01, 0xA7, 0xA3, 0xF2, 0x02, 0xA7, 0xA3, 0xF3, 0x01, 0xA7, 0xA4, 0xF3, + 0x02, 0xA7, 0xA3, 0xF3, 0x02, 0xA7, 0xA4, 0xF4, 0x01, 0xA8, 0xA4, 0xF4, 0x01, 0xA7, 0xA3, 0xF4, + 0x01, 0xA8, 0xA4, 0xF4, 0x08, 0xA8, 0xA4, 0xF5, 0x03, 0xA9, 0xA4, 0xF5, 0x01, 0xA9, 0xA4, 0xF6, + 0x01, 0xA9, 0xA4, 0xF5, 0x01, 0xED, 0xEB, 0xFD, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0x7E, 0x74, 0xF4, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF3, 0x02, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x01, 0x4B, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x4B, 0x29, 0x21, 0x1D, + 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, + 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDC, 0x03, 0x34, 0x35, 0xDD, + 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, + 0x03, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x38, 0x36, 0xE0, 0x01, 0xB9, 0xB7, 0xF3, + 0x3A, 0xFF, 0xFF, 0xFF, 0x01, 0xBE, 0xB8, 0xFA, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3E, 0xF5, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x02, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xD2, 0xD1, 0xD0, 0x0F, 0xDB, 0xDA, 0xDA, 0x01, 0xE9, 0xE9, 0xE8, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDC, 0x03, 0x34, 0x35, 0xDD, 0x02, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xDF, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x38, 0x36, 0xE0, 0x01, 0xE4, 0xE3, 0xFA, 0x3A, 0xFF, 0xFF, 0xFF, + 0x01, 0xE6, 0xE4, 0xFC, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x02, 0x49, 0x3D, 0xF4, + 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF5, + 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, + 0x02, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, + 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x34, 0xDD, 0x01, 0x33, 0x34, 0xDC, 0x03, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x38, 0x36, 0xE0, + 0x01, 0xF6, 0xF6, 0xFE, 0x3A, 0xFF, 0xFF, 0xFF, 0x01, 0xF7, 0xF6, 0xFE, 0x01, 0x46, 0x3C, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF2, 0x03, 0x49, 0x3D, 0xF3, 0x03, 0x4A, 0x3D, 0xF4, + 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDC, + 0x03, 0x34, 0x35, 0xDD, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x35, 0xDF, 0x03, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x38, 0x36, 0xE0, + 0x01, 0xF7, 0xF6, 0xFE, 0x3A, 0xFF, 0xFF, 0xFF, 0x01, 0xF7, 0xF6, 0xFE, 0x01, 0x48, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x49, 0x3C, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF5, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x02, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x04, 0x27, 0x18, 0xB0, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x33, 0x34, 0xDD, + 0x01, 0x33, 0x34, 0xDC, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x35, 0xDE, + 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x38, 0x36, 0xE0, 0x01, 0xE4, 0xE3, 0xFA, 0x3A, 0xFF, 0xFF, 0xFF, + 0x01, 0xE6, 0xE4, 0xFC, 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x03, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x02, 0x4C, 0x3F, 0xF7, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x27, 0x17, 0xAD, + 0x03, 0x27, 0x18, 0xB0, 0x01, 0x34, 0x33, 0xDC, 0x01, 0x33, 0x34, 0xDD, 0x01, 0x33, 0x34, 0xDC, + 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x38, 0x36, 0xE0, 0x01, 0xB8, 0xB6, 0xF3, 0x3A, 0xFF, 0xFF, 0xFF, 0x01, 0xBE, 0xB9, 0xFA, + 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF2, 0x03, 0x49, 0x3D, 0xF3, + 0x03, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF7, + 0x01, 0x4C, 0x3E, 0xF6, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0xFE, 0xFE, 0xFE, 0x14, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, + 0x01, 0x26, 0x17, 0xA7, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x32, 0x31, 0xD9, 0x01, 0x33, 0x34, 0xDC, + 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, + 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, + 0x01, 0x37, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x75, 0x71, 0xE9, 0x10, 0xFF, 0xFF, 0xFF, + 0x01, 0xBE, 0xBC, 0xF5, 0x05, 0xA7, 0xA3, 0xF3, 0x01, 0xA7, 0xA4, 0xF4, 0x01, 0xA7, 0xA3, 0xF3, + 0x02, 0xA8, 0xA4, 0xF4, 0x01, 0xA7, 0xA4, 0xF4, 0x02, 0xA8, 0xA4, 0xF4, 0x06, 0xA8, 0xA4, 0xF5, + 0x01, 0xA9, 0xA4, 0xF5, 0x01, 0xA8, 0xA4, 0xF5, 0x03, 0xA9, 0xA4, 0xF5, 0x01, 0xA9, 0xA4, 0xF6, + 0x01, 0xC0, 0xBD, 0xF8, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0x7E, 0x74, 0xF4, 0x02, 0x48, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4B, 0x3F, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, + 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4A, 0x3B, 0xF2, + 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x4E, 0x48, 0x45, + 0x0F, 0x58, 0x53, 0x50, 0x01, 0x83, 0x7F, 0x7D, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x27, 0x16, 0x9C, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x33, 0x2F, 0xD6, + 0x01, 0x33, 0x34, 0xDD, 0x01, 0x33, 0x34, 0xDC, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x35, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x38, 0x36, 0xE0, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0xD4, 0xD2, 0xF8, 0x0E, 0xFF, 0xFF, 0xFF, 0x01, 0xD5, 0xD2, 0xF9, 0x01, 0x3D, 0x39, 0xE6, + 0x02, 0x3D, 0x38, 0xE6, 0x02, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x04, 0x3E, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE9, 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xE9, 0x02, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, + 0x02, 0x43, 0x3B, 0xED, 0x01, 0xD6, 0xD3, 0xFA, 0x0E, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD3, 0xFB, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x46, 0x3C, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x02, 0x49, 0x3D, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x03, 0x4A, 0x3D, 0xF4, 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4C, 0x3F, 0xF7, 0x01, 0x48, 0x39, 0xEA, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x4B, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x26, 0x15, 0x8A, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2F, 0x29, 0xCF, + 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, + 0x01, 0x5A, 0x57, 0xE4, 0x01, 0xF3, 0xF3, 0xFD, 0x0C, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFD, + 0x01, 0x5F, 0x58, 0xE9, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE6, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE7, + 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x39, 0xE8, 0x02, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, + 0x02, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, + 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x63, 0x5B, 0xEF, + 0x01, 0xF4, 0xF3, 0xFE, 0x0C, 0xFF, 0xFF, 0xFF, 0x01, 0xF4, 0xF3, 0xFE, 0x01, 0x67, 0x5B, 0xF3, + 0x01, 0x46, 0x3C, 0xF1, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x02, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4B, 0x3F, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, + 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x42, 0x33, 0xD8, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x4B, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x15, 0x72, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2C, 0x24, 0xC8, + 0x01, 0x33, 0x34, 0xDC, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, 0x01, 0x34, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x70, 0x6C, 0xE8, 0x01, 0xF3, 0xF3, 0xFD, 0x0A, 0xFF, 0xFF, 0xFF, + 0x01, 0xF4, 0xF3, 0xFD, 0x01, 0x72, 0x6D, 0xEB, 0x01, 0x3D, 0x38, 0xE5, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x3E, 0x39, 0xE8, 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, + 0x01, 0x40, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, + 0x03, 0x43, 0x3B, 0xED, 0x01, 0x77, 0x6E, 0xF1, 0x01, 0xF4, 0xF3, 0xFE, 0x0A, 0xFF, 0xFF, 0xFF, + 0x01, 0xF4, 0xF3, 0xFE, 0x01, 0x7A, 0x6F, 0xF4, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4B, 0x3F, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, 0x02, 0x4B, 0x3F, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x3C, 0x2C, 0xBB, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x4B, 0x29, 0x21, 0x1D, + 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x0E, 0x29, 0x21, 0x1D, + 0x01, 0x28, 0x1A, 0x4D, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2B, 0x1D, 0xBC, 0x01, 0x34, 0x35, 0xDD, + 0x01, 0x33, 0x34, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x35, 0xDE, + 0x01, 0x34, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x5B, 0x57, 0xE5, 0x01, 0xD4, 0xD2, 0xF8, 0x08, 0xFF, 0xFF, 0xFF, + 0x01, 0xD5, 0xD2, 0xF9, 0x01, 0x5E, 0x58, 0xE8, 0x01, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3E, 0x39, 0xE8, + 0x05, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, + 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, + 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, + 0x01, 0x63, 0x5B, 0xF0, 0x01, 0xD6, 0xD3, 0xFA, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD3, 0xFB, + 0x01, 0x67, 0x5B, 0xF3, 0x02, 0x46, 0x3C, 0xF1, 0x02, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, + 0x04, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3E, 0xF6, 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x34, 0x24, 0x82, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x4B, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x0E, 0x29, 0x21, 0x1D, 0x01, 0x29, 0x20, 0x24, 0x01, 0x27, 0x17, 0xAC, 0x02, 0x27, 0x18, 0xB0, + 0x01, 0x29, 0x18, 0xB2, 0x01, 0x33, 0x33, 0xDA, 0x01, 0x33, 0x33, 0xDC, 0x02, 0x34, 0x35, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x35, 0xDF, 0x02, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x75, 0x71, 0xEA, 0x01, 0xB9, 0xB7, 0xF4, 0x01, 0xE4, 0xE3, 0xFB, 0x02, 0xF7, 0xF6, 0xFE, + 0x01, 0xE4, 0xE3, 0xFB, 0x01, 0xB9, 0xB7, 0xF4, 0x01, 0x77, 0x72, 0xEB, 0x01, 0x3A, 0x37, 0xE4, + 0x02, 0x3C, 0x37, 0xE4, 0x01, 0x3D, 0x38, 0xE5, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x38, 0xE6, + 0x01, 0x3C, 0x38, 0xE6, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x39, 0xE8, + 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x40, 0x39, 0xEB, + 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, 0x05, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x7D, 0x74, 0xF2, 0x01, 0xBC, 0xB8, 0xF8, 0x01, 0xE6, 0xE4, 0xFC, + 0x02, 0xF7, 0xF6, 0xFE, 0x01, 0xE6, 0xE4, 0xFC, 0x01, 0xBD, 0xB8, 0xF8, 0x01, 0x7D, 0x74, 0xF4, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x45, 0x3C, 0xF0, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x02, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4B, 0x3F, 0xF5, 0x01, 0x4A, 0x3E, 0xF5, 0x02, 0x4B, 0x3F, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x02, 0x4B, 0x3E, 0xF6, 0x01, 0x4C, 0x3F, 0xF6, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x2B, 0x22, 0x30, 0x28, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x4B, 0x29, 0x21, 0x1D, + 0x01, 0x51, 0x4C, 0x48, 0x01, 0xFE, 0xFE, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xC6, 0xC5, 0xC4, + 0x0F, 0x29, 0x21, 0x1D, 0x01, 0x26, 0x14, 0x84, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x30, 0x29, 0xCE, + 0x01, 0x33, 0x34, 0xDD, 0x01, 0x34, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x35, 0xDE, + 0x01, 0x34, 0x35, 0xDE, 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE0, + 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x02, 0x3A, 0x37, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, + 0x02, 0x3C, 0x38, 0xE5, 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE6, + 0x01, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, + 0x01, 0x3E, 0x39, 0xE8, 0x05, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, + 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xEE, + 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x46, 0x3C, 0xF0, + 0x01, 0x45, 0x3C, 0xF0, 0x03, 0x46, 0x3C, 0xF1, 0x02, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, + 0x04, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3E, 0xF6, 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x3F, 0x31, 0xD3, 0x29, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x60, 0x29, 0x21, 0x1D, + 0x01, 0x28, 0x1A, 0x4E, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2B, 0x1D, 0xBC, 0x01, 0x33, 0x34, 0xDD, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDE, + 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, + 0x01, 0x39, 0x37, 0xE2, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3E, 0x39, 0xE8, + 0x05, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, + 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, + 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, + 0x03, 0x46, 0x3C, 0xF1, 0x02, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x04, 0x49, 0x3D, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x34, 0x24, 0x84, + 0x29, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x61, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x16, 0x98, + 0x03, 0x27, 0x18, 0xB0, 0x01, 0x32, 0x2E, 0xD4, 0x03, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x03, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE2, 0x01, 0x38, 0x36, 0xE1, 0x03, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x37, 0xE3, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3D, 0x39, 0xE6, + 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x01, 0x3C, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE6, + 0x02, 0x3D, 0x38, 0xE7, 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, + 0x02, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, + 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, 0x03, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, + 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, + 0x01, 0x45, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, + 0x03, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x03, 0x48, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x45, 0x37, 0xE7, 0x2A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x61, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x19, 0x53, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2B, 0x1F, 0xBF, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDD, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x34, 0x35, 0xDE, + 0x03, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x02, 0x38, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, + 0x01, 0x39, 0x37, 0xE2, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x02, 0x3C, 0x38, 0xE5, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3E, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3E, 0x39, 0xE8, + 0x05, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, + 0x01, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x01, 0x42, 0x39, 0xEC, + 0x01, 0x43, 0x3A, 0xEC, 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, + 0x01, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x46, 0x3C, 0xF0, 0x01, 0x45, 0x3C, 0xF0, + 0x03, 0x46, 0x3C, 0xF1, 0x02, 0x48, 0x3D, 0xF2, 0x03, 0x48, 0x3C, 0xF2, 0x04, 0x49, 0x3D, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x04, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3E, 0xF6, + 0x02, 0x4B, 0x3F, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x33, 0x25, 0x8D, 0x2A, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x62, 0x29, 0x21, 0x1D, 0x01, 0x26, 0x15, 0x8D, 0x03, 0x27, 0x18, 0xB0, + 0x01, 0x30, 0x2C, 0xD2, 0x02, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, + 0x01, 0x35, 0x35, 0xDF, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, + 0x03, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x38, 0x36, 0xE1, 0x03, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE3, + 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3D, 0x39, 0xE6, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x39, 0xE6, 0x01, 0x3C, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE6, 0x02, 0x3D, 0x38, 0xE7, + 0x03, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, 0x02, 0x3F, 0x39, 0xE9, + 0x02, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x03, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x05, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEE, + 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x03, 0x45, 0x3C, 0xF0, + 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3C, 0xF2, 0x03, 0x48, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x4B, 0x3E, 0xF6, 0x01, 0x42, 0x34, 0xDC, + 0x2B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x62, 0x29, 0x21, 0x1D, 0x01, 0x29, 0x1E, 0x36, + 0x01, 0x27, 0x17, 0xA9, 0x02, 0x27, 0x18, 0xB0, 0x01, 0x29, 0x1A, 0xB6, 0x01, 0x34, 0x32, 0xDB, + 0x01, 0x34, 0x35, 0xDE, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x03, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x38, 0x36, 0xE1, + 0x03, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE3, 0x02, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3D, 0x39, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, + 0x01, 0x3C, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE6, 0x02, 0x3D, 0x38, 0xE7, 0x03, 0x3E, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, 0x02, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xE9, + 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, + 0x03, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, + 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x03, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, + 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x03, 0x48, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x4A, 0x3E, 0xF6, 0x01, 0x49, 0x3B, 0xF2, 0x01, 0x2D, 0x22, 0x56, 0x2B, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x63, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x18, 0x57, 0x03, 0x27, 0x18, 0xB0, + 0x01, 0x2D, 0x1F, 0xC0, 0x01, 0x35, 0x35, 0xDE, 0x02, 0x34, 0x35, 0xDE, 0x02, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, + 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x38, 0x36, 0xE1, + 0x02, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE2, 0x02, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x36, 0xE4, + 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x02, 0x3C, 0x38, 0xE5, 0x03, 0x3D, 0x38, 0xE6, 0x02, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, + 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, + 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, 0x02, 0x42, 0x39, 0xEC, 0x02, 0x42, 0x3A, 0xEC, + 0x01, 0x44, 0x3B, 0xED, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x43, 0x3B, 0xED, + 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, 0x02, 0x46, 0x3C, 0xF0, + 0x02, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3C, 0xF3, + 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3D, 0xF4, + 0x03, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x35, 0x26, 0x93, 0x2C, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x64, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x15, 0x70, 0x03, 0x27, 0x18, 0xB0, + 0x01, 0x2E, 0x25, 0xC8, 0x01, 0x35, 0x35, 0xDE, 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x35, 0x36, 0xDF, 0x01, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x03, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE1, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE2, 0x01, 0x38, 0x36, 0xE1, + 0x03, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE3, 0x02, 0x3A, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3D, 0x39, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, + 0x01, 0x3C, 0x38, 0xE6, 0x01, 0x3D, 0x38, 0xE6, 0x02, 0x3D, 0x38, 0xE7, 0x03, 0x3E, 0x39, 0xE8, + 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, 0x02, 0x3F, 0x39, 0xE9, 0x02, 0x40, 0x39, 0xE9, + 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x01, 0x40, 0x39, 0xEA, + 0x03, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x3A, 0xEC, 0x05, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, 0x01, 0x45, 0x3C, 0xEE, 0x01, 0x44, 0x3B, 0xEE, + 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x03, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, + 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, + 0x03, 0x48, 0x3D, 0xF2, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF3, + 0x01, 0x49, 0x3C, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF4, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4B, 0x3F, 0xF6, + 0x01, 0x39, 0x2C, 0xB9, 0x2D, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x65, 0x29, 0x21, 0x1D, + 0x01, 0x28, 0x14, 0x7A, 0x03, 0x27, 0x18, 0xB0, 0x01, 0x2F, 0x27, 0xCB, 0x01, 0x34, 0x35, 0xDE, + 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xE0, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x38, 0x36, 0xE1, 0x02, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE2, 0x02, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x03, 0x3D, 0x38, 0xE6, 0x02, 0x3E, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, + 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, 0x02, 0x42, 0x39, 0xEC, + 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x44, 0x3B, 0xED, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x02, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, + 0x01, 0x49, 0x3C, 0xF3, 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, + 0x01, 0x4A, 0x3D, 0xF4, 0x02, 0x4A, 0x3E, 0xF5, 0x01, 0x3C, 0x2D, 0xC6, 0x2E, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x66, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x15, 0x70, 0x03, 0x27, 0x18, 0xB0, + 0x01, 0x2E, 0x25, 0xC8, 0x02, 0x35, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xDF, 0x02, 0x37, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xE0, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, + 0x01, 0x38, 0x36, 0xE2, 0x01, 0x38, 0x36, 0xE1, 0x02, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE2, + 0x02, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x03, 0x3D, 0x38, 0xE6, + 0x02, 0x3E, 0x39, 0xE7, 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x38, 0xE8, 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, + 0x01, 0x40, 0x39, 0xE9, 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, + 0x02, 0x42, 0x39, 0xEC, 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x44, 0x3B, 0xED, 0x02, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, + 0x01, 0x45, 0x3B, 0xEF, 0x02, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF2, 0x01, 0x49, 0x3C, 0xF3, 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, + 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x4A, 0x3E, 0xF5, 0x01, 0x39, 0x2C, 0xB9, + 0x2F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3D, 0x29, 0x21, 0x1D, 0x01, 0x40, 0x39, 0x36, + 0x01, 0x80, 0x7C, 0x7A, 0x01, 0xB5, 0xB2, 0xB1, 0x01, 0xAD, 0xAA, 0xA9, 0x01, 0x6F, 0x6B, 0x68, + 0x01, 0x31, 0x2A, 0x25, 0x24, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x18, 0x57, 0x01, 0x27, 0x17, 0xA9, + 0x02, 0x27, 0x18, 0xB0, 0x01, 0x2D, 0x20, 0xC0, 0x01, 0x35, 0x33, 0xDC, 0x01, 0x35, 0x35, 0xDF, + 0x01, 0x37, 0x36, 0xDF, 0x01, 0x37, 0x36, 0xE0, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, 0x02, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x04, 0x3A, 0x37, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3D, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x39, 0xE9, 0x04, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x02, 0x40, 0x39, 0xEB, 0x03, 0x42, 0x3A, 0xEC, + 0x04, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x02, 0x45, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x02, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x49, 0x3C, 0xF3, + 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x48, 0x3B, 0xF2, 0x01, 0x35, 0x26, 0x92, 0x30, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3C, 0x29, 0x21, 0x1D, 0x01, 0x79, 0x75, 0x73, 0x01, 0xFD, 0xFD, 0xFD, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF2, 0xF1, 0xF1, 0x01, 0x4E, 0x48, 0x45, 0x01, 0x29, 0x21, 0x1D, + 0x01, 0x3E, 0x38, 0x34, 0x01, 0xDA, 0xD9, 0xD8, 0x01, 0xA9, 0xA8, 0xA6, 0x01, 0x58, 0x53, 0x50, + 0x1F, 0x29, 0x21, 0x1D, 0x01, 0x29, 0x1E, 0x36, 0x01, 0x26, 0x15, 0x8D, 0x02, 0x27, 0x18, 0xB0, + 0x01, 0x2A, 0x1A, 0xB6, 0x01, 0x33, 0x2D, 0xD3, 0x02, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x37, 0x35, 0xE0, 0x02, 0x37, 0x36, 0xE0, 0x01, 0x38, 0x36, 0xE1, 0x01, 0x38, 0x36, 0xE2, + 0x01, 0x38, 0x36, 0xE1, 0x02, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE2, 0x02, 0x39, 0x36, 0xE3, + 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, 0x01, 0x3C, 0x37, 0xE4, + 0x01, 0x3A, 0x36, 0xE4, 0x02, 0x3C, 0x38, 0xE5, 0x03, 0x3D, 0x38, 0xE6, 0x02, 0x3E, 0x39, 0xE7, + 0x01, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, + 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xE9, + 0x03, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x39, 0xEB, 0x02, 0x42, 0x3A, 0xEC, 0x02, 0x42, 0x39, 0xEC, + 0x02, 0x42, 0x3A, 0xEC, 0x01, 0x44, 0x3B, 0xED, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, + 0x01, 0x43, 0x3B, 0xED, 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, 0x01, 0x45, 0x3B, 0xEF, + 0x02, 0x46, 0x3C, 0xF0, 0x02, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3D, 0xF2, + 0x02, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x49, 0x3D, 0xF2, + 0x01, 0x49, 0x3C, 0xF3, 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x41, 0x33, 0xDA, + 0x01, 0x2D, 0x22, 0x56, 0x31, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0x68, 0x63, 0x61, 0x01, 0xF9, 0xF9, 0xF9, 0x06, 0xFF, 0xFF, 0xFF, 0x01, 0xDB, 0xDB, 0xDB, + 0x01, 0x33, 0x2B, 0x27, 0x01, 0x4C, 0x45, 0x42, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xB8, 0xB7, 0xB6, + 0x20, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x19, 0x53, 0x01, 0x28, 0x16, 0x98, 0x02, 0x27, 0x18, 0xB0, + 0x01, 0x2D, 0x1F, 0xBF, 0x01, 0x34, 0x2F, 0xD8, 0x01, 0x37, 0x35, 0xDF, 0x01, 0x37, 0x36, 0xE0, + 0x01, 0x38, 0x36, 0xE0, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, 0x02, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x04, 0x3A, 0x37, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3D, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x39, 0xE9, 0x04, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x02, 0x40, 0x39, 0xEB, 0x03, 0x42, 0x3A, 0xEC, + 0x04, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x02, 0x45, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x02, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x03, 0x49, 0x3D, 0xF3, 0x01, 0x4A, 0x3D, 0xF4, 0x01, 0x42, 0x36, 0xE4, 0x01, 0x32, 0x24, 0x8C, + 0x33, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xCC, 0xCB, 0xCB, + 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0x97, 0x94, 0x92, 0x01, 0x4C, 0x45, 0x42, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0x87, 0x83, 0x81, 0x21, 0x29, 0x21, 0x1D, 0x01, 0x28, 0x1A, 0x4E, 0x01, 0x26, 0x14, 0x84, + 0x01, 0x27, 0x17, 0xAC, 0x01, 0x27, 0x18, 0xB0, 0x01, 0x2D, 0x1D, 0xBD, 0x01, 0x32, 0x2A, 0xD0, + 0x01, 0x38, 0x35, 0xDF, 0x02, 0x38, 0x36, 0xE1, 0x01, 0x39, 0x37, 0xE2, 0x02, 0x38, 0x36, 0xE2, + 0x01, 0x39, 0x36, 0xE2, 0x01, 0x39, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x04, 0x3A, 0x37, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3C, 0x38, 0xE5, + 0x01, 0x3D, 0x38, 0xE6, 0x01, 0x3C, 0x38, 0xE5, 0x01, 0x3D, 0x39, 0xE6, 0x02, 0x3D, 0x38, 0xE6, + 0x01, 0x3D, 0x38, 0xE7, 0x02, 0x3E, 0x39, 0xE8, 0x01, 0x3F, 0x39, 0xE8, 0x01, 0x3E, 0x39, 0xE8, + 0x01, 0x3E, 0x39, 0xE9, 0x04, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x39, 0xEA, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x01, 0x42, 0x3A, 0xEB, 0x02, 0x40, 0x39, 0xEB, 0x03, 0x42, 0x3A, 0xEC, + 0x04, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, 0x01, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3B, 0xED, + 0x01, 0x44, 0x3C, 0xEE, 0x01, 0x45, 0x3C, 0xEF, 0x01, 0x44, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, + 0x02, 0x45, 0x3B, 0xEF, 0x01, 0x45, 0x3C, 0xF0, 0x01, 0x46, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, + 0x02, 0x46, 0x3C, 0xF2, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x48, 0x3D, 0xF2, 0x02, 0x48, 0x3C, 0xF2, + 0x01, 0x49, 0x3D, 0xF3, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x3E, 0x31, 0xD0, 0x01, 0x32, 0x24, 0x83, + 0x35, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3A, 0x29, 0x21, 0x1D, 0x01, 0x2B, 0x23, 0x1E, + 0x01, 0xF4, 0xF4, 0xF4, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0xC6, 0xC5, 0xC4, 0x01, 0x4C, 0x45, 0x42, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF8, 0xF7, 0xF7, 0x01, 0x4C, 0x45, 0x42, 0x22, 0x29, 0x21, 0x1D, + 0x01, 0x29, 0x20, 0x24, 0x01, 0x28, 0x1A, 0x4D, 0x01, 0x28, 0x15, 0x72, 0x01, 0x26, 0x15, 0x8A, + 0x01, 0x27, 0x17, 0x9E, 0x01, 0x2B, 0x1D, 0xB7, 0x01, 0x30, 0x25, 0xC9, 0x01, 0x33, 0x2C, 0xD4, + 0x01, 0x37, 0x31, 0xDA, 0x01, 0x38, 0x34, 0xDF, 0x01, 0x39, 0x35, 0xE1, 0x01, 0x39, 0x36, 0xE2, + 0x01, 0x3A, 0x37, 0xE3, 0x01, 0x39, 0x36, 0xE3, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3A, 0x36, 0xE4, + 0x01, 0x3C, 0x37, 0xE4, 0x01, 0x3A, 0x37, 0xE4, 0x01, 0x3C, 0x37, 0xE4, 0x03, 0x3C, 0x38, 0xE5, + 0x02, 0x3D, 0x38, 0xE6, 0x01, 0x3D, 0x39, 0xE7, 0x02, 0x3D, 0x38, 0xE7, 0x01, 0x3E, 0x38, 0xE7, + 0x01, 0x3E, 0x39, 0xE8, 0x01, 0x3E, 0x38, 0xE8, 0x01, 0x3F, 0x39, 0xE9, 0x01, 0x3E, 0x38, 0xE8, + 0x03, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, 0x02, 0x3F, 0x39, 0xE9, 0x01, 0x40, 0x3A, 0xEA, + 0x01, 0x40, 0x39, 0xEA, 0x03, 0x42, 0x3A, 0xEB, 0x01, 0x42, 0x39, 0xEC, 0x01, 0x43, 0x3B, 0xED, + 0x01, 0x42, 0x3A, 0xEC, 0x02, 0x43, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xED, 0x01, 0x43, 0x3B, 0xED, + 0x01, 0x44, 0x3B, 0xED, 0x01, 0x44, 0x3C, 0xEE, 0x02, 0x44, 0x3B, 0xEE, 0x02, 0x45, 0x3C, 0xEF, + 0x04, 0x45, 0x3C, 0xF0, 0x02, 0x46, 0x3C, 0xF1, 0x01, 0x48, 0x3C, 0xF2, 0x01, 0x46, 0x3B, 0xEF, + 0x01, 0x45, 0x3A, 0xED, 0x01, 0x43, 0x37, 0xE5, 0x01, 0x3E, 0x30, 0xD4, 0x01, 0x39, 0x2C, 0xB9, + 0x01, 0x32, 0x24, 0x81, 0x01, 0x29, 0x22, 0x30, 0x37, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3A, 0x29, 0x21, 0x1D, 0x01, 0x4C, 0x46, 0x44, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xEE, 0xEE, 0xED, + 0x01, 0x4C, 0x45, 0x42, 0x05, 0xFF, 0xFF, 0xFF, 0x01, 0x86, 0x82, 0x80, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3A, 0x29, 0x21, 0x1D, 0x01, 0x4F, 0x4A, 0x46, 0x01, 0xFE, 0xFE, 0xFE, + 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xBF, 0xBE, 0xBD, 0x01, 0x86, 0x82, 0x80, 0x01, 0xF3, 0xF2, 0xF2, + 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0x56, 0x50, 0x4E, 0x01, 0xD4, 0xD2, 0xD2, 0x04, 0xFF, 0xFF, 0xFF, + 0x01, 0xA9, 0xA8, 0xA6, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3A, 0x29, 0x21, 0x1D, + 0x01, 0x36, 0x2F, 0x2B, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x55, 0x4F, 0x4D, 0x01, 0x29, 0x21, 0x1D, + 0x01, 0xB9, 0xB8, 0xB7, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0x64, 0x5F, 0x5C, 0x01, 0x2B, 0x23, 0x1E, + 0x01, 0xE7, 0xE6, 0xE5, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xCB, 0xCA, 0xCA, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xD6, 0xD5, 0xD4, 0x03, 0xFF, 0xFF, 0xFF, + 0x01, 0x57, 0x52, 0x4F, 0x01, 0x29, 0x21, 0x1D, 0x01, 0x8A, 0x87, 0x85, 0x03, 0xFF, 0xFF, 0xFF, + 0x01, 0x73, 0x6E, 0x6C, 0x01, 0x29, 0x21, 0x1D, 0x01, 0xC9, 0xC7, 0xC6, 0x03, 0xFF, 0xFF, 0xFF, + 0x01, 0xE8, 0xE7, 0xE6, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0x65, 0x61, 0x5D, 0x01, 0xFD, 0xFD, 0xFD, 0x02, 0xFF, 0xFF, 0xFF, 0x01, 0xC1, 0xBF, 0xBF, + 0x01, 0x29, 0x21, 0x1D, 0x01, 0x7A, 0x75, 0x73, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0x81, 0x7D, 0x7B, + 0x01, 0x33, 0x2B, 0x27, 0x01, 0xEF, 0xEF, 0xEE, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xDD, 0xDC, 0xDC, + 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xAA, 0xA9, 0xA7, + 0x01, 0xE8, 0xE8, 0xE7, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xE3, 0xE2, 0xE2, 0x01, 0xE7, 0xE6, 0xE5, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF1, 0xF1, 0xF1, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xBB, 0xB9, 0xB8, + 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x10, 0xFF, 0xFF, 0xFF, + 0x01, 0x96, 0x93, 0x91, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0x6D, 0x69, 0x67, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x0F, 0xFF, 0xFF, 0xFF, 0x01, 0xC8, 0xC6, 0xC5, 0xA0, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x0E, 0xFF, 0xFF, 0xFF, 0x01, 0xE8, 0xE8, 0xE7, + 0x01, 0x3B, 0x35, 0x31, 0xA0, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0xFE, 0xFE, 0xFE, 0x0C, 0xFF, 0xFF, 0xFF, 0x01, 0xCE, 0xCC, 0xCB, 0x01, 0x55, 0x4F, 0x4D, + 0xA1, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x55, 0x4E, 0x4C, + 0x0A, 0x5D, 0x59, 0x56, 0x01, 0x5A, 0x55, 0x51, 0x01, 0x39, 0x31, 0x2D, 0xA3, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x8B, 0x88, 0x86, 0x14, 0x94, 0x91, 0x90, + 0x01, 0x71, 0x6C, 0x6A, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, + 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x15, 0xFF, 0xFF, 0xFF, + 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x15, 0xFF, 0xFF, 0xFF, 0x01, 0xCF, 0xCD, 0xCC, 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x77, 0x73, 0x71, 0x03, 0x81, 0x7D, 0x7B, 0x01, 0x99, 0x96, 0x94, + 0x06, 0xFF, 0xFF, 0xFF, 0x01, 0xD0, 0xCF, 0xCE, 0x09, 0x81, 0x7D, 0x7B, 0x01, 0x62, 0x5C, 0x5A, + 0x9A, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, 0x01, 0x7A, 0x75, 0x73, + 0x01, 0xF5, 0xF5, 0xF5, 0x06, 0xFF, 0xFF, 0xFF, 0x01, 0xBB, 0xB9, 0xB8, 0x01, 0x35, 0x2E, 0x2B, + 0xA2, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3D, 0x29, 0x21, 0x1D, 0x01, 0x44, 0x3E, 0x3A, + 0x01, 0xC3, 0xC2, 0xC1, 0x09, 0xFF, 0xFF, 0xFF, 0x01, 0xE1, 0xE0, 0xDF, 0x01, 0x55, 0x4F, 0x4D, + 0xA1, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3C, 0x29, 0x21, 0x1D, 0x01, 0x89, 0x86, 0x84, + 0x01, 0xF3, 0xF3, 0xF3, 0x0B, 0xFF, 0xFF, 0xFF, 0x01, 0xF8, 0xF7, 0xF7, 0x01, 0x84, 0x80, 0x7E, + 0xA0, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xD0, 0xCF, 0xCE, + 0x0F, 0xFF, 0xFF, 0xFF, 0x01, 0x91, 0x8F, 0x8D, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0xF1, 0xF0, 0xF0, 0x01, 0xE2, 0xE1, 0xE1, + 0x01, 0xFE, 0xFE, 0xFE, 0x05, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x07, 0xFF, 0xFF, 0xFF, 0x01, 0xBD, 0xBB, 0xBA, + 0x01, 0x3E, 0x38, 0x34, 0x01, 0x29, 0x21, 0x1D, 0x01, 0x7B, 0x77, 0x75, 0x01, 0xF8, 0xF7, 0xF7, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x05, 0xFF, 0xFF, 0xFF, 0x01, 0xEC, 0xEB, 0xEB, 0x01, 0x74, 0x70, 0x6E, + 0x04, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, 0x01, 0xE9, 0xE9, 0xE9, 0x03, 0xFF, 0xFF, 0xFF, + 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xB5, 0xB2, 0xB1, 0x01, 0x3A, 0x33, 0x2F, 0x06, 0x29, 0x21, 0x1D, + 0x01, 0x41, 0x3A, 0x37, 0x01, 0xD5, 0xD3, 0xD3, 0x02, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, + 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x02, 0xFF, 0xFF, 0xFF, + 0x01, 0xE8, 0xE7, 0xE6, 0x01, 0x6B, 0x67, 0x65, 0x09, 0x29, 0x21, 0x1D, 0x01, 0x30, 0x28, 0x24, + 0x01, 0xB7, 0xB5, 0xB4, 0x01, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xF9, 0xF9, 0xF9, 0x01, 0xAD, 0xAA, 0xA9, + 0x01, 0x35, 0x2E, 0x2B, 0x0C, 0x29, 0x21, 0x1D, 0x01, 0x92, 0x90, 0x8E, 0x01, 0x82, 0x7E, 0x7D, + 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x34, 0x2D, 0x29, + 0xAF, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x47, 0x29, 0x21, 0x1D, 0x01, 0xD0, 0xCF, 0xCE, + 0x03, 0xF0, 0xF0, 0xEF, 0x01, 0x98, 0x95, 0x93, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x47, 0x29, 0x21, 0x1D, 0x01, 0xE6, 0xE5, 0xE5, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, + 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3C, 0x29, 0x21, 0x1D, 0x01, 0x30, 0x28, 0x24, + 0x01, 0x8C, 0x88, 0x87, 0x01, 0xB1, 0xAF, 0xAE, 0x01, 0xCC, 0xCB, 0xCB, 0x07, 0xD2, 0xD1, 0xD0, + 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xF3, 0xF3, 0xF3, 0x02, 0xD2, 0xD1, 0xD0, 0x01, 0xD1, 0xD1, 0xD0, + 0x01, 0x4C, 0x46, 0x44, 0x9B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0x4B, 0x44, 0x41, 0x01, 0xDF, 0xDE, 0xDD, 0x12, 0xFF, 0xFF, 0xFF, 0x01, 0x65, 0x61, 0x5D, + 0x9B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xB8, 0xB7, 0xB6, + 0x13, 0xFF, 0xFF, 0xFF, 0x01, 0x65, 0x61, 0x5D, 0x9B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3A, 0x29, 0x21, 0x1D, 0x01, 0x39, 0x31, 0x2D, 0x01, 0xFC, 0xFC, 0xFC, 0x13, 0xFF, 0xFF, 0xFF, + 0x01, 0x65, 0x61, 0x5D, 0x9B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3A, 0x29, 0x21, 0x1D, + 0x01, 0x59, 0x54, 0x51, 0x14, 0xFF, 0xFF, 0xFF, 0x01, 0x65, 0x61, 0x5D, 0x9B, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3A, 0x29, 0x21, 0x1D, 0x01, 0x72, 0x6D, 0x6B, 0x14, 0xFF, 0xFF, 0xFF, + 0x01, 0x5F, 0x59, 0x57, 0x9B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3A, 0x29, 0x21, 0x1D, + 0x01, 0x69, 0x64, 0x62, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xC6, 0xC5, 0xC4, 0x01, 0x61, 0x5B, 0x59, + 0x06, 0x3B, 0x34, 0x30, 0x01, 0xEB, 0xEA, 0xEA, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xB4, 0xB2, 0xB0, + 0x02, 0x3B, 0x34, 0x30, 0x01, 0x3A, 0x33, 0x2F, 0x9C, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3A, 0x29, 0x21, 0x1D, 0x01, 0x73, 0x6F, 0x6D, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0x63, 0x5E, 0x5B, + 0x07, 0x29, 0x21, 0x1D, 0x01, 0xE6, 0xE5, 0xE5, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, + 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3A, 0x29, 0x21, 0x1D, 0x01, 0x5B, 0x56, 0x52, + 0x03, 0xF1, 0xF0, 0xF0, 0x01, 0xED, 0xEC, 0xEC, 0x01, 0x3B, 0x34, 0x30, 0x07, 0x29, 0x21, 0x1D, + 0x01, 0xD1, 0xD0, 0xCF, 0x03, 0xF1, 0xF0, 0xF0, 0x01, 0x98, 0x95, 0x93, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x10, 0x2B, 0x23, 0x1E, 0x04, 0x29, 0x21, 0x1D, + 0x01, 0x36, 0x2F, 0x2B, 0x9B, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x01, 0xF8, 0xF7, 0xF7, 0x0F, 0xFF, 0xFF, 0xFF, 0x01, 0xA2, 0x9F, 0x9E, 0x01, 0x29, 0x21, 0x1D, + 0x01, 0x6B, 0x67, 0x65, 0x01, 0xD2, 0xD1, 0xD0, 0x01, 0xFF, 0xFF, 0xFF, 0x01, 0xD6, 0xD6, 0xD5, + 0x01, 0x73, 0x6F, 0x6D, 0x99, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x01, 0x2C, 0x24, 0x20, 0x01, 0xEA, 0xE9, 0xE9, + 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xF2, 0xF1, 0xF1, 0x01, 0x31, 0x2A, 0x25, 0x98, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, + 0x01, 0x5C, 0x57, 0x54, 0x05, 0xFF, 0xFF, 0xFF, 0x01, 0x7A, 0x75, 0x73, 0x98, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, + 0x01, 0x59, 0x54, 0x51, 0x05, 0xFF, 0xFF, 0xFF, 0x01, 0x6B, 0x67, 0x65, 0x98, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, + 0x01, 0x29, 0x21, 0x1D, 0x01, 0xDB, 0xDB, 0xDB, 0x03, 0xFF, 0xFF, 0xFF, 0x01, 0xE6, 0xE5, 0xE5, + 0x99, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xD0, 0xCF, 0xCE, + 0x0F, 0xD8, 0xD7, 0xD6, 0x01, 0x89, 0x86, 0x84, 0x01, 0x29, 0x21, 0x1D, 0x01, 0x48, 0x43, 0x3F, + 0x01, 0xA6, 0xA3, 0xA2, 0x01, 0xDF, 0xDE, 0xDD, 0x01, 0xAB, 0xA9, 0xA8, 0x01, 0x4D, 0x47, 0x45, + 0x99, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x4A, 0x29, 0x21, 0x1D, 0x01, 0x59, 0x54, 0x51, 0x01, 0x44, 0x3D, 0x39, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x47, 0x29, 0x21, 0x1D, 0x01, 0x58, 0x53, 0x50, 0x01, 0xA3, 0xA0, 0x9E, + 0x01, 0xE3, 0xE2, 0xE2, 0x01, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x44, 0x29, 0x21, 0x1D, 0x01, 0x57, 0x52, 0x4F, 0x01, 0xA2, 0x9F, 0x9E, + 0x01, 0xE2, 0xE1, 0xE1, 0x04, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x41, 0x29, 0x21, 0x1D, 0x01, 0x56, 0x50, 0x4E, 0x01, 0xA1, 0x9F, 0x9D, + 0x01, 0xE1, 0xE1, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3E, 0x29, 0x21, 0x1D, 0x01, 0x55, 0x4F, 0x4D, 0x01, 0x9F, 0x9D, 0x9C, + 0x01, 0xE1, 0xE0, 0xDF, 0x0A, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x01, 0x55, 0x4E, 0x4C, 0x01, 0x9E, 0x9C, 0x9B, + 0x01, 0xE0, 0xE0, 0xDF, 0x0D, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x10, 0xFF, 0xFF, 0xFF, 0x01, 0xA2, 0x9F, 0x9E, + 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, 0x0B, 0xFF, 0xFF, 0xFF, + 0x01, 0xFE, 0xFE, 0xFE, 0x01, 0xE0, 0xDF, 0xDE, 0x01, 0xB1, 0xB0, 0xAF, 0x01, 0x80, 0x7C, 0x7A, + 0x01, 0x46, 0x40, 0x3C, 0xA0, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x07, 0xFF, 0xFF, 0xFF, 0x01, 0xFB, 0xFB, 0xFB, 0x01, 0xD7, 0xD6, 0xD6, 0x01, 0xA9, 0xA7, 0xA6, + 0x01, 0x76, 0x72, 0x70, 0x01, 0x3C, 0x36, 0x32, 0xA4, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x06, 0xFF, 0xFF, 0xFF, 0x01, 0xD3, 0xD1, 0xD1, 0x01, 0x76, 0x72, 0x70, + 0x01, 0x35, 0x2E, 0x2B, 0xA7, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3B, 0x29, 0x21, 0x1D, + 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0xFC, 0xFC, 0xFC, 0x01, 0xDA, 0xD9, 0xD8, 0x01, 0xAC, 0xA9, 0xA8, + 0x01, 0x7A, 0x76, 0x74, 0x01, 0x42, 0x3B, 0x39, 0xA3, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x0D, 0xFF, 0xFF, 0xFF, 0x01, 0xE5, 0xE4, 0xE4, 0x01, 0xB8, 0xB7, 0xB6, + 0x01, 0x88, 0x84, 0x82, 0x01, 0x47, 0x41, 0x3E, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x3B, 0x29, 0x21, 0x1D, 0x01, 0xD7, 0xD6, 0xD6, 0x0F, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, + 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3C, 0x29, 0x21, 0x1D, 0x01, 0x49, 0x44, 0x40, + 0x01, 0x95, 0x92, 0x91, 0x01, 0xD6, 0xD5, 0xD4, 0x01, 0xFE, 0xFE, 0xFE, 0x0B, 0xFF, 0xFF, 0xFF, + 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x3F, 0x29, 0x21, 0x1D, + 0x01, 0x47, 0x41, 0x3E, 0x01, 0x93, 0x91, 0x8F, 0x01, 0xD5, 0xD3, 0xD3, 0x01, 0xFE, 0xFE, 0xFE, + 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, + 0x42, 0x29, 0x21, 0x1D, 0x01, 0x46, 0x40, 0x3C, 0x01, 0x91, 0x8F, 0x8D, 0x01, 0xD4, 0xD2, 0xD2, + 0x01, 0xFD, 0xFD, 0xFD, 0x05, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0x45, 0x29, 0x21, 0x1D, 0x01, 0x44, 0x3E, 0x3A, 0x01, 0x90, 0x8D, 0x8B, + 0x01, 0xD2, 0xD1, 0xD0, 0x01, 0xFD, 0xFD, 0xFD, 0x02, 0xFF, 0xFF, 0xFF, 0x01, 0xAA, 0xA9, 0xA7, + 0x9F, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0x48, 0x29, 0x21, 0x1D, 0x01, 0x44, 0x3D, 0x39, + 0x01, 0x8F, 0x8B, 0x89, 0x01, 0xD1, 0xD0, 0xCF, 0x01, 0x8D, 0x89, 0x88, 0x9F, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D, + 0x05, 0x38, 0x23, 0xEC, 0xEB, 0x29, 0x21, 0x1D +}; diff --git a/source/spotpass.c b/source/spotpass.c new file mode 100644 index 0000000..8514d52 --- /dev/null +++ b/source/spotpass.c @@ -0,0 +1,249 @@ +// SpotPass (BOSS) für MBMNET-Mitteilungen, siehe spotpass.h. +// +// Wie in der libctru-Vorlage (examples/network/boss): eigene Aufgabe mit HTTP-URL. Der Server liefert einen +// BOSS-Container, dessen Inhalt an das News-Modul (0004013000003502) geht. Die Nintendo-Signatur darin ist +// leer, Luma schaltet ihre Prüfung ab. +#include <3ds.h> +#include +#include + +#include "spotpass.h" + +#define TASK_NEWS "mbmnews" +#define TASK_TEST "mbmtest" +#define NEWS_INTERVAL (2 * 60) // Sekunden zwischen zwei Abrufen + +// SpotPass braucht für jede Anwendung mit Aufgaben einen angemeldeten Speicher (Extdata), wie bei Spielen. +// Die Mitteilungen selbst landen im News-Modul, der Speicher bleibt praktisch leer. +#define EXTDATA_ID 0xFB4E0ULL // = Unique ID der App (cia.rsf: ExtSaveDataId) +#define BOSS_STORAGE 0x100000 // 1 MB + +// Policy-Liste: SpotPass lädt sie vor jeder Aufgabe von Nintendo (nppl.c.app.nintendowifi.net). Der Server +// antwortet nicht mehr, ohne Liste bricht jede Aufgabe ab. Darum auf MBMNET umstellen (wie Pretendo). +// boss:P-Befehl 0x0427 SetPolicyListUrl, leerer Text = wieder Nintendos Adresse. Klappt nur mit boss:P. +static Result set_policy_url(const char *url) +{ + u32 size = strlen(url) + 1; + u32 *cmdbuf = getThreadCommandBuffer(); + cmdbuf[0] = IPC_MakeHeader(0x427, 1, 2); // 0x04270042 + cmdbuf[1] = size; + cmdbuf[2] = IPC_Desc_Buffer(size, IPC_BUFFER_R); + cmdbuf[3] = (u32)url; + Result rc = svcSendSyncRequest(bossGetSessionHandle()); + return R_SUCCEEDED(rc) ? (Result)cmdbuf[1] : rc; +} + +static Result use_mbmnet_policy(const char *server) +{ + char url[128]; + snprintf(url, sizeof(url), "http://%s/p01/policylist", server); + return set_policy_url(url); +} + +// Gibt es die Extdata? Sonst anlegen (mit Ordner /boss, in den SpotPass schreibt). bossSetStorageInfo +// prüft das nicht - ohne Extdata scheitert erst die Aufgabe (Fehler 004-6006). +static Result ensure_extdata(void) +{ + u32 lowHigh[3] = { MEDIATYPE_SD, (u32)EXTDATA_ID, (u32)(EXTDATA_ID >> 32) }; + FS_Path path = { PATH_BINARY, sizeof(lowHigh), lowHigh }; + FS_Archive arch; + Result rc = fsInit(); + if (R_FAILED(rc)) return rc; + rc = FSUSER_OpenArchive(&arch, ARCHIVE_EXTDATA, path); + if (R_FAILED(rc)) { + FS_ExtSaveDataInfo info = { .mediaType = MEDIATYPE_SD, .saveId = EXTDATA_ID }; + rc = FSUSER_CreateExtSaveData(info, 32, 256, 0, 0, NULL); + if (R_FAILED(rc)) { + // Manche Systemversionen wollen ein Icon (SMDH) dazu: leeres mit Kennung reicht + static u8 smdh[0x36C0]; + memcpy(smdh, "SMDH", 4); + rc = FSUSER_CreateExtSaveData(info, 32, 256, 0, sizeof(smdh), smdh); + } + if (R_SUCCEEDED(rc)) rc = FSUSER_OpenArchive(&arch, ARCHIVE_EXTDATA, path); + } + if (R_SUCCEEDED(rc)) { + FSUSER_CreateDirectory(arch, fsMakePath(PATH_ASCII, "/boss"), 0); // gibt es ihn schon: egal + FSUSER_CloseArchive(arch); + } + fsExit(); + return rc; +} + +static Result ensure_storage(void) +{ + return bossSetStorageInfo(EXTDATA_ID, BOSS_STORAGE, MEDIATYPE_SD); +} + +static bool url_for(const char *server, const char *file, char *url, size_t len) +{ + u32 device = 0; + bool ok = R_SUCCEEDED(amInit()); + if (ok) { + s32 internal = 0; + ok = R_SUCCEEDED(AM_GetDeviceId(&internal, &device)) && internal >= 0 && device; + amExit(); + } + if (ok) snprintf(url, len, "http://%s/spotpass/%lu/%s", server, (unsigned long)device, file); + return ok; +} + +// step bekommt den Namen des Schritts, der fehlschlug +static Result setup_task(const char *server, const char *task, const char *url, u32 interval, const char **step) +{ + bool once = strcmp(task, TASK_TEST) == 0; + *step = "Policy-Liste umstellen"; + Result rc = use_mbmnet_policy(server); + if (R_FAILED(rc)) return rc; + *step = "Speicher anlegen"; + rc = ensure_extdata(); + if (R_FAILED(rc)) return rc; + *step = "Speicher anmelden"; + rc = ensure_storage(); + if (R_FAILED(rc)) return rc; + bossDeleteTask(task, 0); + bossContext ctx; + bossSetupContextDefault(&ctx, interval, url); + ctx.property[0x4] = once ? 1 : 0; // Count: 0 = dauerhaft (Standard wären 100 Läufe), Test nur einmal + *step = "Einstellungen senden"; + rc = bossSendContextConfig(&ctx); + if (R_FAILED(rc)) return rc; + *step = "Aufgabe anmelden"; + return bossRegisterTask(task, 0, 0); +} + +bool spotpass_register(const char *server, char *msg, size_t msglen) +{ + char url[256]; + if (!url_for(server, "news.boss", url, sizeof(url))) { + snprintf(msg, msglen, "SpotPass: Geräte-ID nicht lesbar"); + return false; + } + const char *step = "BOSS starten"; + Result rc = bossInit(0, false); + if (R_SUCCEEDED(rc)) { + rc = setup_task(server, TASK_NEWS, url, NEWS_INTERVAL, &step); + if (R_SUCCEEDED(rc)) bossStartBgImmediate(TASK_NEWS); // gleich einmal abholen + bossExit(); + } + if (R_FAILED(rc)) snprintf(msg, msglen, "SpotPass anmelden fehlgeschlagen bei: %s (%08lX)", step, (unsigned long)rc); + return R_SUCCEEDED(rc); +} + +void spotpass_unregister(void) +{ + if (R_FAILED(bossInit(0, false))) return; + bossDeleteTask(TASK_NEWS, 0); + set_policy_url(""); // wieder Nintendos Policy-Liste + bossExit(); +} + +// --- Fehlerauswertung (BOSSU-Befehle, die libctru nicht hat) --------------------------------------- +static Result boss_send(u32 *cmdbuf) +{ + Result rc = svcSendSyncRequest(bossGetSessionHandle()); + return R_SUCCEEDED(rc) ? (Result)cmdbuf[1] : rc; +} + +// Befehl mit Task-ID-Puffer; extra = Werte zwischen Größe und Puffer +static Result boss_task_cmd(u16 id, const char *task, int nextra, u32 e1, u32 e2, u32 *out) +{ + u32 size = strlen(task) + 1; + u32 *cmd = getThreadCommandBuffer(); + cmd[0] = IPC_MakeHeader(id, 1 + nextra, 2); + cmd[1] = size; + if (nextra > 0) cmd[2] = e1; + if (nextra > 1) cmd[3] = e2; + cmd[2 + nextra] = IPC_Desc_Buffer(size, IPC_BUFFER_R); + cmd[3 + nextra] = (u32)task; + Result rc = boss_send(cmd); + if (out) *out = cmd[2]; + return rc; +} + +static Result boss_receive_property(u16 property, void *buf, u32 size) +{ + u32 *cmd = getThreadCommandBuffer(); + cmd[0] = IPC_MakeHeader(0x16, 2, 2); // ReceiveProperty + cmd[1] = property; + cmd[2] = size; + cmd[3] = IPC_Desc_Buffer(size, IPC_BUFFER_W); + cmd[4] = (u32)buf; + return boss_send(cmd); +} + +// Fehler einer Aufgabe als Text: Nintendo-Fehlercode 004-XXXX, Ergebnis, Dienststatus, HTTP-Code +static void task_error_text(const char *task, char *out, size_t len) +{ + u8 result = 0, service = 0, taskErr = 0; + u32 http = 0, code = 0; + boss_task_cmd(0x23, task, 2, 0, 0, NULL); // GetTaskStatus: lädt die Status-Eigenschaften + boss_receive_property(0x20, &result, 1); // TaskResultCode + boss_receive_property(0x21, &service, 1); // TaskServiceStatus + boss_task_cmd(0x24, task, 1, 0, 0, NULL); // GetTaskError: lädt Eigenschaft 0x30 + boss_receive_property(0x30, &taskErr, 1); + boss_task_cmd(0x22, task, 0, 0, 0, &http); // GetTaskCommErrorCode (HTTP-Status) + u32 *cmd = getThreadCommandBuffer(); + cmd[0] = IPC_MakeHeader(0x2E, 1, 0); // GetErrorCode: Ergebnis -> 004-XXXX + cmd[1] = result; + if (R_SUCCEEDED(boss_send(cmd))) code = cmd[2]; + snprintf(out, len, "Fehler %03lu-%04lu (Ergebnis 0x%02X, Dienst 0x%02X, Aufgabe 0x%02X, HTTP %lu)", + (unsigned long)(code / 10000), (unsigned long)(code % 10000), result, service, taskErr, (unsigned long)http); +} + +static char testUrl[256]; +static bool testSeenRunning; + +bool spotpass_test_start(const char *server, char *msg, size_t msglen) +{ + if (!url_for(server, "test.boss", testUrl, sizeof(testUrl))) { + snprintf(msg, msglen, "SpotPass-Test: Geräte-ID nicht lesbar"); + return false; + } + Result rc = bossInit(0, false); + if (R_FAILED(rc)) { + snprintf(msg, msglen, "SpotPass-Test: BOSS nicht verfügbar (%08lX)", (unsigned long)rc); + return false; + } + const char *step = ""; + rc = setup_task(server, TASK_TEST, testUrl, 60, &step); + if (R_SUCCEEDED(rc)) { step = "Aufgabe starten"; rc = bossStartTaskImmediate(TASK_TEST); } + bossExit(); + if (R_FAILED(rc)) { + snprintf(msg, msglen, "SpotPass-Test fehlgeschlagen bei: %s (%08lX)", step, (unsigned long)rc); + return false; + } + testSeenRunning = false; + snprintf(msg, msglen, "SpotPass-Test gestartet ..."); + return true; +} + +bool spotpass_test_poll(int seconds, char *msg, size_t msglen) +{ + if (R_FAILED(bossInit(0, false))) return true; + u8 status = 0, out2 = 0; + u32 out1 = 0; + Result rc = bossGetTaskState(TASK_TEST, 0, &status, &out1, &out2); + bool running = R_SUCCEEDED(rc) && status != BOSSTASKSTATUS_ERROR && !(testSeenRunning && status != BOSSTASKSTATUS_STARTED); + if (status == BOSSTASKSTATUS_STARTED) testSeenRunning = true; + if (running && seconds < 180) { + snprintf(msg, msglen, "SpotPass-Test läuft ... %d s (Status %u)", seconds, status); + bossExit(); + return true; + } + if (R_FAILED(rc)) + snprintf(msg, msglen, "SpotPass-Test: Status nicht lesbar (%08lX)", (unsigned long)rc); + else if (running) + snprintf(msg, msglen, "SpotPass-Test nach 3 Min. noch nicht fertig (Status %u).\n" + "Er läuft im Hintergrund weiter. Später in die Mitteilungen schauen.", status); + else if (status == BOSSTASKSTATUS_ERROR) { + char why[128]; + task_error_text(TASK_TEST, why, sizeof(why)); + snprintf(msg, msglen, "SpotPass-Test: Abruf fehlgeschlagen.\n%s\n%s", why, testUrl); + } + else + snprintf(msg, msglen, "SpotPass-Test abgeholt (Status %u, %lu, %u).\nSteht \"MBMNET SpotPass-Test\" in den Mitteilungen?", + status, (unsigned long)out1, out2); + if (!running) bossDeleteTask(TASK_TEST, 0); // nur löschen, wenn wirklich fertig + bossExit(); + return false; +} diff --git a/source/spotpass.h b/source/spotpass.h new file mode 100644 index 0000000..e58e6ad --- /dev/null +++ b/source/spotpass.h @@ -0,0 +1,17 @@ +#pragma once +#include <3ds/types.h> +#include + +// SpotPass (BOSS): Der 3DS holt MBMNET-Nachrichten und Ankündigungen selbst im Hintergrund ab (auch im +// Standby, ohne App) und zeigt sie als Mitteilung im HOME-Menü. Die Aufgabe ruft alle 2 Minuten +// http:///spotpass//news.boss ab (MBMNET Accounting, spotpass.js). + +// Hintergrund-Aufgabe anmelden (bei aktivem MBMNET). false + msg bei Fehler. +bool spotpass_register(const char *server, char *msg, size_t msglen); +// Hintergrund-Aufgabe abmelden (beim Wechsel zu Nintendo) +void spotpass_unregister(void); +// Test für die Werkzeuge: startet den sofortigen Abruf einer Test-Mitteilung. true = läuft, +// danach jede Sekunde spotpass_test_poll aufrufen. +bool spotpass_test_start(const char *server, char *msg, size_t msglen); +// true = Test noch nicht fertig. msg bekommt den Stand bzw. das Ergebnis. +bool spotpass_test_poll(int seconds, char *msg, size_t msglen); diff --git a/source/update.c b/source/update.c new file mode 100644 index 0000000..e940586 --- /dev/null +++ b/source/update.c @@ -0,0 +1,277 @@ +// Auto-Update. Die App fragt den MBMNET-Server (per HTTP, das kann der 3DS zuverlässig): +// GET /app/version -> z. B. "1.2.0" +// GET /app/mbmnet.3dsx -> die neue App (Homebrew-Launcher-Version) +// GET /app/mbmnet.cia -> die neue App (installierte CIA-Version) +// Der Server holt beides von deinem Git-Server (siehe config.json / README). +#include <3ds.h> +#include +#include +#include +#include +#include + +#include "update.h" + +#define MAX_DOWNLOAD (8 * 1024 * 1024) + +static volatile UpdateState state = UPD_IDLE; +static char server[64]; +static char selfPath[256]; +static char newVersion[32]; +static Thread thread; +static bool runningAsCia; + +// Fehlersuche: Schritt und Code des letzten Fehlers, dazu ein Protokoll auf der SD +#define LOG_FILE "sdmc:/3ds/mbmnet/update.log" +static char errStep[48]; +static Result errCode; +static volatile int downloadAttempt; // laufender Versuch (für die Anzeige) + +static void ulog(const char *fmt, ...) +{ + FILE *f = fopen(LOG_FILE, "a"); + if (!f) return; + va_list ap; + va_start(ap, fmt); + vfprintf(f, fmt, ap); + va_end(ap); + fputc('\n', f); + fclose(f); +} + +// Merkt sich den Fehler. Den Zustand setzt erst der Worker, wenn alle Versuche erfolglos waren. +static void fail(const char *stepName, Result rc) +{ + snprintf(errStep, sizeof(errStep), "%s", stepName); + errCode = rc; + ulog("FEHLER bei %s: %08lX", stepName, (unsigned long)rc); +} + +#define ATTEMPTS 3 +static void pause_seconds(int s) { svcSleepThread((s64)s * 1000 * 1000 * 1000); } + +int update_attempt(void) { return downloadAttempt; } + +void update_error(char *out, size_t len) +{ + snprintf(out, len, "%s (Fehler %08lX)", errStep[0] ? errStep : "?", (unsigned long)errCode); +} + +UpdateState update_state(void) { return state; } +const char *update_new_version(void) { return newVersion; } + +// Lädt eine URL komplett in den Speicher. Gibt den HTTP-Status zurück (0 bei Netzwerkfehler). +static Result lastHttpRc; // Fehlercode, falls http_get 0 zurückgibt + +static u32 http_get(const char *url, u8 **out, u32 *outSize) +{ + httpcContext ctx; + u32 status = 0; + *out = NULL; + *outSize = 0; + + lastHttpRc = httpcOpenContext(&ctx, HTTPC_METHOD_GET, url, 1); + if (R_FAILED(lastHttpRc)) return 0; + httpcAddRequestHeaderField(&ctx, "User-Agent", "MBMNET-Switcher/" APP_VERSION); + httpcSetKeepAlive(&ctx, HTTPC_KEEPALIVE_DISABLED); + + if (R_SUCCEEDED(lastHttpRc = httpcBeginRequest(&ctx)) && + R_SUCCEEDED(lastHttpRc = httpcGetResponseStatusCodeTimeout(&ctx, &status, 10ULL * 1000 * 1000 * 1000)) && + status == 200) { + u32 cap = 64 * 1024, size = 0, got; + u8 *buf = malloc(cap); + Result rc; + do { + if (!buf) break; + if (size == cap) { + if (cap >= MAX_DOWNLOAD) { free(buf); buf = NULL; break; } + u8 *bigger = realloc(buf, cap * 2); + if (!bigger) { free(buf); buf = NULL; break; } + buf = bigger; + cap *= 2; + } + got = 0; + rc = httpcDownloadData(&ctx, buf + size, cap - size, &got); + size += got; + } while (rc == (Result)HTTPC_RESULTCODE_DOWNLOADPENDING); + + if (buf && R_SUCCEEDED(rc)) { + *out = buf; + *outSize = size; + } else { + lastHttpRc = buf ? rc : -2; // -2 = zu wenig Speicher + *outSize = size; + free(buf); + status = 0; + } + } + httpcCloseContext(&ctx); + return status; +} + +// Installiert eine CIA über den Systemdienst am:net (wie FBI) +static bool install_cia(const u8 *data, u32 size) +{ + Handle h; + Result rc = AM_StartCiaInstall(MEDIATYPE_SD, &h); + ulog("CIA-Installation starten: %08lX", (unsigned long)rc); + if (R_FAILED(rc)) { fail("CIA-Installation starten", rc); return false; } + for (u32 off = 0; off < size;) { + u32 chunk = size - off > 0x10000 ? 0x10000 : size - off; + u32 written = 0; + rc = FSFILE_Write(h, &written, off, data + off, chunk, 0); + if (R_FAILED(rc) || written != chunk) { + ulog("Schreiben bei %lu: %08lX (%lu von %lu Bytes)", (unsigned long)off, (unsigned long)rc, + (unsigned long)written, (unsigned long)chunk); + AM_CancelCIAInstall(h); + fail("CIA schreiben", rc); + return false; + } + off += chunk; + } + rc = AM_FinishCiaInstall(h); + ulog("CIA-Installation abschließen: %08lX", (unsigned long)rc); + if (R_FAILED(rc)) { fail("CIA-Installation abschließen", rc); return false; } + return true; +} + +// Schreibt die neue .3dsx über die laufende +static bool install_3dsx(const u8 *data, u32 size) +{ + char tmpPath[sizeof(selfPath) + 8]; + snprintf(tmpPath, sizeof(tmpPath), "%s.neu", selfPath); + FILE *f = fopen(tmpPath, "wb"); + bool ok = f && fwrite(data, 1, size, f) == size; + if (f) fclose(f); + ulog("3DSX schreiben nach %s: %s", tmpPath, ok ? "OK" : "FEHLER"); + if (!ok) { fail("3DSX schreiben", -1); return false; } + // Erst komplett schreiben, dann austauschen: so bleibt bei einem Abbruch die alte App heil. + remove(selfPath); + ok = rename(tmpPath, selfPath) == 0; + ulog("3DSX austauschen (%s): %s", selfPath, ok ? "OK" : "FEHLER"); + if (!ok) fail("3DSX austauschen", -1); + return ok; +} + +static bool is_newer(const char *remote, const char *local) +{ + int r[3] = { 0 }, l[3] = { 0 }; + sscanf(remote, "%d.%d.%d", &r[0], &r[1], &r[2]); + sscanf(local, "%d.%d.%d", &l[0], &l[1], &l[2]); + for (int i = 0; i < 3; i++) { + if (r[i] != l[i]) return r[i] > l[i]; + } + return false; +} + +// Schritt 1: gibt es eine neuere Version? (bei Netzwerkfehlern bis zu 3 Versuche) +static void check_worker(void *arg) +{ + char url[128]; + u8 *data; + u32 size; + + snprintf(url, sizeof(url), "http://%s/app/version", server); + for (int attempt = 1; attempt <= ATTEMPTS; attempt++) { + u32 status = http_get(url, &data, &size); + if (status == 404) { state = UPD_NONE; return; } + if (status == 200) { + snprintf(newVersion, sizeof(newVersion), "%.*s", (int)(size < 31 ? size : 31), (char *)data); + newVersion[strcspn(newVersion, " \r\n")] = 0; + if (newVersion[0] == 'v') memmove(newVersion, newVersion + 1, strlen(newVersion)); + free(data); + state = is_newer(newVersion, APP_VERSION) ? UPD_AVAILABLE : UPD_LATEST; + return; + } + free(data); + if (attempt < ATTEMPTS) pause_seconds(2); + } + state = UPD_ERROR; +} + +// Ein Versuch: laden, prüfen, installieren +static bool download_and_install(const char *url) +{ + u8 *data; + u32 size; + u32 status = http_get(url, &data, &size); + ulog("Download: HTTP %lu, %lu Bytes", (unsigned long)status, (unsigned long)size); + if (status != 200) { + free(data); + fail(status ? "Herunterladen (HTTP-Status)" : "Herunterladen", status ? (Result)status : lastHttpRc); + return false; + } + + // Nur echte Dateien installieren: CIA beginnt mit Headergröße 0x2020, 3DSX mit "3DSX" + bool valid = size >= 32 && (runningAsCia + ? data[0] == 0x20 && data[1] == 0x20 && data[2] == 0 && data[3] == 0 + : memcmp(data, "3DSX", 4) == 0); + if (!valid) { free(data); fail("Datei prüfen", -1); return false; } + bool ok = runningAsCia ? install_cia(data, size) : install_3dsx(data, size); + free(data); + return ok; +} + +// Schritt 2: neue Version laden und installieren (bei Fehlern bis zu 3 Versuche) +static void download_worker(void *arg) +{ + char url[128]; + mkdir("sdmc:/3ds/mbmnet", 0777); + remove(LOG_FILE); + errStep[0] = 0; + snprintf(url, sizeof(url), "http://%s/app/%s", server, runningAsCia ? "mbmnet.cia" : "mbmnet.3dsx"); + ulog("MBMNET-Update v%s -> v%s (%s)", APP_VERSION, newVersion, runningAsCia ? "CIA" : "3DSX"); + ulog("Lade %s", url); + + for (int attempt = 1; attempt <= ATTEMPTS; attempt++) { + if (attempt > 1) ulog("--- Versuch %d von %d", attempt, ATTEMPTS); + downloadAttempt = attempt; + if (download_and_install(url)) { + ulog("Ergebnis: OK"); + state = UPD_INSTALLED; + return; + } + if (attempt < ATTEMPTS) pause_seconds(3); + } + ulog("Ergebnis: FEHLER nach %d Versuchen", ATTEMPTS); + state = UPD_ERROR; +} + +static void start_thread(ThreadFunc fn) +{ + if (thread) { threadJoin(thread, U64_MAX); threadFree(thread); thread = NULL; } + s32 prio = 0x30; + svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); + thread = threadCreate(fn, NULL, 32 * 1024, prio + 1, -2, false); + if (!thread) state = UPD_ERROR; +} + +void update_start(const char *srv, const char *self) +{ + if (!srv[0] || state == UPD_CHECKING || state == UPD_DOWNLOADING) return; + snprintf(server, sizeof(server), "%s", srv); + snprintf(selfPath, sizeof(selfPath), "%s", self); + runningAsCia = !envIsHomebrew(); + state = UPD_CHECKING; + start_thread(check_worker); +} + +void update_download(void) +{ + if (state != UPD_AVAILABLE) return; + state = UPD_DOWNLOADING; + start_thread(download_worker); +} + +bool update_pending(void) +{ + return state == UPD_AVAILABLE || state == UPD_DOWNLOADING || state == UPD_INSTALLED; +} + +void update_finish(void) +{ + if (!thread) return; + // Läuft der Download noch, nicht freigeben: Die App beendet sich ohnehin. + if (R_SUCCEEDED(threadJoin(thread, 3ULL * 1000 * 1000 * 1000))) threadFree(thread); + thread = NULL; +} diff --git a/source/update.h b/source/update.h new file mode 100644 index 0000000..ae04962 --- /dev/null +++ b/source/update.h @@ -0,0 +1,28 @@ +#pragma once +#include <3ds/types.h> +#include + +typedef enum { + UPD_IDLE, // noch nicht geprüft + UPD_CHECKING, // fragt den Server + UPD_LATEST, // schon die neueste Version + UPD_AVAILABLE, // neue Version gefunden, wartet auf update_download() + UPD_DOWNLOADING, // lädt neue Version + UPD_INSTALLED, // neue Version liegt auf der SD, App neu starten + UPD_NONE, // Server bietet keine Updates an + UPD_ERROR, // Server nicht erreichbar o. Ä. +} UpdateState; + +// Startet die Prüfung im Hintergrund. selfPath = Pfad der laufenden .3dsx. +void update_start(const char *server, const char *selfPath); +// Lädt und installiert die gefundene neue Version (nur im Zustand UPD_AVAILABLE). +void update_download(void); +// true, solange ein Update ansteht, lädt oder auf den Neustart wartet +bool update_pending(void); +UpdateState update_state(void); +const char *update_new_version(void); +void update_finish(void); +// Laufender Download-Versuch (1-3) +int update_attempt(void); +// Beschreibung des letzten Fehlers (Schritt und Code) +void update_error(char *out, size_t len); diff --git a/tools/Dockerfile b/tools/Dockerfile new file mode 100644 index 0000000..730a230 --- /dev/null +++ b/tools/Dockerfile @@ -0,0 +1,20 @@ +# Build-Umgebung für die MBMNET-App: devkitARM + makerom + bannertool (für die CIA) +FROM devkitpro/devkitarm + +# makerom (Project_CTR) aus dem Quellcode bauen +RUN git clone --depth 1 https://github.com/3DSGuy/Project_CTR.git /tmp/ctr \ + && make -C /tmp/ctr/makerom deps \ + && make -C /tmp/ctr/makerom \ + && find /tmp/ctr/makerom -type f -name makerom -perm -u+x -exec cp {} /usr/local/bin/makerom \; \ + && rm -rf /tmp/ctr + +# bannertool aus dem Quellcode bauen (direkt kompiliert, die mitgelieferten +# Build-Skripte kennen ARM-Rechner wie Apple Silicon nicht) +RUN git clone --depth 1 https://github.com/diasurgical/bannertool.git /tmp/bt \ + && cd /tmp/bt && mkdir o \ + && for f in $(find source -name '*.c'); do gcc -O2 -Isource -c "$f" -o "o/$(basename $f).o"; done \ + && for f in $(find source -name '*.cpp'); do g++ -std=gnu++11 -O2 -Isource -DVERSION_MAJOR=1 -DVERSION_MINOR=2 -DVERSION_MICRO=0 -c "$f" -o "o/$(basename $f).o"; done \ + && g++ o/*.o -o /usr/local/bin/bannertool \ + && rm -rf /tmp/bt + +RUN makerom -version || true; bannertool 2>&1 | head -1 || true