From 83ae093b21ba472bcecb6c9826fa69aff526f569 Mon Sep 17 00:00:00 2001 From: krob <70478163+krob64@users.noreply.github.com> Date: Mon, 1 Dec 2025 19:29:12 +0100 Subject: [PATCH 01/25] created license --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /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 +. From 7b8a4c5821b1d46021e1b86fa21210325765f261 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Mon, 13 Apr 2026 17:42:36 -0700 Subject: [PATCH 02/25] feat: add AUR support with GitHub Actions CI/CD - Add .github/workflows/pr.yml for PR builds on Ubuntu - Add .github/workflows/release.yml for semantic versioning and releases - Add root PKGBUILD for building from source - Add aur/ directory with AUR PKGBUILD, install script, and .SRCINFO - Add proper .gitignore --- .github/workflows/pr.yml | 45 ++++++++++ .github/workflows/release.yml | 165 ++++++++++++++++++++++++++++++++++ PKGBUILD | 27 ++++++ aur/.SRCINFO | 13 +++ aur/PKGBUILD | 30 +++++++ aur/krosshair.install | 28 ++++++ 6 files changed, 308 insertions(+) create mode 100644 .github/workflows/pr.yml create mode 100644 .github/workflows/release.yml create mode 100644 PKGBUILD create mode 100644 aur/.SRCINFO create mode 100644 aur/PKGBUILD create mode 100644 aur/krosshair.install diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..07452fd --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,45 @@ +name: Build to test PR + +on: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libvulkan-dev libgl-dev libx11-dev gcc make + - name: Build binary + run: make + - name: Create tarball + run: | + ARCH=$(uname -m) + if [ "$ARCH" = "x86_64" ]; then + ARCH_NAME="x86_64" + elif [ "$ARCH" = "aarch64" ]; then + ARCH_NAME="aarch64" + fi + mkdir -p krosshair-linux-${ARCH_NAME} + cp lib/krosshair.so krosshair-linux-${ARCH_NAME}/ + cp krosshair.json krosshair-linux-${ARCH_NAME}/ + cp LICENSE krosshair-linux-${ARCH_NAME}/ 2>/dev/null || true + tar -czf krosshair-linux-${ARCH_NAME}.tar.gz -C krosshair-linux-${ARCH_NAME} . + - name: Generate checksum + run: | + ARCH=$(uname -m) + if [ "$ARCH" = "x86_64" ]; then + ARCH_NAME="x86_64" + elif [ "$ARCH" = "aarch64" ]; then + ARCH_NAME="aarch64" + fi + sha256sum krosshair-linux-${ARCH_NAME}.tar.gz > krosshair-linux-${ARCH_NAME}.sha256 + - name: Upload artifacts + uses: actions/upload-artifact@v6 + with: + name: krosshair-linux + path: | + krosshair-linux-*.tar.gz + krosshair-linux-*.sha256 \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..80ff46e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,165 @@ +name: Semantic Versioning and Release + +on: + push: + branches: [main] + +jobs: + version: + runs-on: ubuntu-latest + outputs: + new_version: ${{ steps.bump.outputs.new_version }} + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - name: Install tools + run: | + sudo apt-get update + sudo apt-get install -y python python-pip + pip install --user bumpver + - name: Calculate version bump + id: bump + run: | + LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + if [ -n "$LAST_TAG" ]; then + COMMITS=$(git log $LAST_TAG..HEAD --pretty=%s) + else + COMMITS=$(git log HEAD --pretty=%s) + fi + if echo "$COMMITS" | grep -q "^BREAKING CHANGE:"; then + bumpver update --major + elif echo "$COMMITS" | grep -q "^feat:"; then + bumpver update --minor + else + bumpver update --patch + fi + NEW_VERSION=$(bumpver show | grep -E "^[0-9]+\.[0-9]+\.[0-9]+" | head -1) + echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT + - name: Bump PKGBUILD versions + run: | + sed -i "s/pkgver=.*/pkgver=${{ steps.bump.outputs.new_version }}/" PKGBUILD + sed -i "s/pkgver=.*/pkgver=${{ steps.bump.outputs.new_version }}/" aur/PKGBUILD + cd aur && makepkg --printsrcinfo > .SRCINFO + - name: Upload version files (uncommitted) + uses: actions/upload-artifact@v6 + with: + name: version-files + path: | + PKGBUILD + aur/ + + build: + needs: [version] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - uses: actions/download-artifact@v7 + with: + name: version-files + path: . + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libvulkan-dev libgl-dev libx11-dev gcc make + - name: Build binary + run: make + - name: Determine architecture + id: arch + run: | + ARCH=$(uname -m) + echo "arch=$ARCH" >> $GITHUB_OUTPUT + if [ "$ARCH" = "x86_64" ]; then + echo "arch_name=x86_64" >> $GITHUB_OUTPUT + elif [ "$ARCH" = "aarch64" ]; then + echo "arch_name=aarch64" >> $GITHUB_OUTPUT + fi + - name: Create tarball + run: | + mkdir -p krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }} + cp lib/krosshair.so krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}/ + cp krosshair.json krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}/ + cp LICENSE krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}/ 2>/dev/null || true + tar -czf krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}.tar.gz -C krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }} . + - name: Generate checksum + run: sha256sum krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}.tar.gz > krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}.sha256 + - name: Upload artifacts + uses: actions/upload-artifact@v6 + with: + name: krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }} + path: | + krosshair-*.tar.gz + krosshair-*.sha256 + + commit-and-release: + needs: [version, build] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + ref: main + fetch-depth: 0 + - uses: actions/download-artifact@v7 + with: + path: artifacts + - name: Restore version files from successful build + run: | + mkdir -p aur + cp artifacts/version-files/PKGBUILD . + cp -r artifacts/version-files/aur/* aur/ + - name: Commit version bump and create tag + run: | + git config user.name "GitHub Action" + git config user.email "action@github.com" + git add PKGBUILD aur/ + git commit -m "chore: bump version to v${{ needs.version.outputs.new_version }}" || echo "No changes to commit" + git tag "v${{ needs.version.outputs.new_version }}" -f + git push origin main + git push origin "v${{ needs.version.outputs.new_version }}" -f + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Push to AUR + run: | + mkdir -p ~/.ssh + echo "$AUR_SSH_KEY" > ~/.ssh/aur + chmod 600 ~/.ssh/aur + ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts + rm -rf aur + if git clone ssh://aur@aur.archlinux.org/krosshair.git aur 2>&1; then + echo "Cloned existing AUR repo" + cp -r artifacts/version-files/aur/* aur/ + cd aur + else + echo "Creating new AUR repo" + mkdir aur + cp -r artifacts/version-files/aur/* aur/ + cd aur + git init + git remote add origin ssh://aur@aur.archlinux.org/krosshair.git + fi + makepkg --printsrcinfo > .SRCINFO + git config user.name "GitHub Action" + git config user.email "action@github.com" + git add PKGBUILD .SRCINFO krosshair.install + git commit -m "Update to v${{ needs.version.outputs.new_version }}" || echo "No changes to commit" + git push origin master + env: + AUR_SSH_KEY: ${{ secrets.AUR_SSH_KEY }} + - name: Create release with assets + run: | + ARCH=$(uname -m) + if [ "$ARCH" = "x86_64" ]; then + ARCH_NAME="x86_64" + elif [ "$ARCH" = "aarch64" ]; then + ARCH_NAME="aarch64" + fi + gh release delete "v${{ needs.version.outputs.new_version }}" --yes 2>/dev/null || true + gh release create "v${{ needs.version.outputs.new_version }}" \ + --title "v${{ needs.version.outputs.new_version }}" \ + --notes "Release v${{ needs.version.outputs.new_version }}" \ + artifacts/krosshair-${{ needs.version.outputs.new_version }}-${ARCH_NAME}/krosshair-${{ needs.version.outputs.new_version }}-${ARCH_NAME}.tar.gz \ + artifacts/krosshair-${{ needs.version.outputs.new_version }}-${ARCH_NAME}/krosshair-${{ needs.version.outputs.new_version }}-${ARCH_NAME}.sha256 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..1f0f5ff --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,27 @@ +# Maintainer: fibsussy +pkgname=krosshair +pkgver=0.1.0 +pkgrel=1 +pkgdesc="Crosshair overlay for games on linux using Vulkan" +arch=('x86_64' 'aarch64') +url="https://github.com/fibsussy/krosshair" +license=('GPL3') +depends=('vulkan-icd-loader' 'libgl' 'libx11') +makedepends=('gcc' 'make' 'vulkan-headers') +options=('!debug') + +build() { + cd "$startdir" + make +} + +package() { + cd "$startdir" + + install -Dm755 lib/krosshair.so "$pkgdir/usr/lib/krosshair/krosshair.so" + install -Dm644 krosshair.json "$pkgdir/usr/share/vulkan/implicit_layer.d/krosshair.json" + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + + install -dm755 "$pkgdir/usr/share/krosshair/crosshairs" + cp -r crosshairs/* "$pkgdir/usr/share/krosshair/crosshairs/" || true +} \ No newline at end of file diff --git a/aur/.SRCINFO b/aur/.SRCINFO new file mode 100644 index 0000000..106faa8 --- /dev/null +++ b/aur/.SRCINFO @@ -0,0 +1,13 @@ +pkgbase = krosshair +pkgdesc = Crosshair overlay for games on linux using Vulkan +pkgver = 0.1.0 +pkgrel = 1 +url = https://github.com/fibsussy/krosshair +arch = x86_64 +arch = aarch64 +license = GPL3 +depends = libvulkan-driver +depends = libgl +depends = libx11 + +pkgname = krosshair \ No newline at end of file diff --git a/aur/PKGBUILD b/aur/PKGBUILD new file mode 100644 index 0000000..5ae5096 --- /dev/null +++ b/aur/PKGBUILD @@ -0,0 +1,30 @@ +# Maintainer: fibsussy +pkgname=krosshair +pkgver=0.1.0 +pkgrel=1 +pkgdesc="Crosshair overlay for games on linux using Vulkan" +arch=('x86_64' 'aarch64') +url="https://github.com/fibsussy/krosshair" +license=('GPL3') +depends=('vulkan-icd-loader' 'libgl' 'libx11') +makedepends=() +options=('!debug') + +_arch="$CARCH" +if [ "$_arch" = "x86_64" ]; then + _arch="x86_64" +elif [ "$_arch" = "aarch64" ]; then + _arch="aarch64" +fi + +source=( + "https://github.com/fibsussy/krosshair/releases/download/v${pkgver}/krosshair-linux-${_arch}.tar.gz" + "LICENSE::https://raw.githubusercontent.com/fibsussy/krosshair/v${pkgver}/LICENSE" +) +sha256sums=('SKIP' 'SKIP') + +package() { + install -Dm755 "$srcdir/krosshair.so" "$pkgdir/usr/lib/krosshair/krosshair.so" + install -Dm644 "$srcdir/krosshair.json" "$pkgdir/usr/share/vulkan/implicit_layer.d/krosshair.json" + install -Dm644 "$srcdir/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} \ No newline at end of file diff --git a/aur/krosshair.install b/aur/krosshair.install new file mode 100644 index 0000000..69a628a --- /dev/null +++ b/aur/krosshair.install @@ -0,0 +1,28 @@ +post_install() { + echo "" + echo "==> krosshair installed successfully!" + echo "" + echo "==> Getting Started:" + echo "" + echo " 1. Run your game with KROSSHAIR=1 set" + echo " Example: KROSSHAIR=1 your-game" + echo "" + echo " 2. For Steam games, add to launch options:" + echo " KROSSHAIR=1 %command%" + echo "" + echo "==> Customization:" + echo " KROSSHAIR_IMG=/path/to/crosshair.png" + echo " KROSSHAIR_SCALE=1.0" + echo "" + echo "==> Sample crosshairs installed at:" + echo " /usr/share/krosshair/crosshairs/" + echo "" + echo "==> For more info: https://github.com/fibsussy/krosshair" + echo "" +} + +post_upgrade() { + echo "" + echo "==> krosshair upgraded successfully!" + echo "" +} \ No newline at end of file From 7f2278a647781c943422a921e89280a0f014b06a Mon Sep 17 00:00:00 2001 From: fibsussy Date: Sun, 19 Apr 2026 01:54:38 -0700 Subject: [PATCH 03/25] feat: added hot reload on crosshair image file change --- src/layer.c | 120 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 104 insertions(+), 16 deletions(-) diff --git a/src/layer.c b/src/layer.c index e1bd290..bf31d47 100644 --- a/src/layer.c +++ b/src/layer.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,15 @@ (const struct VkBaseInStructure*)(__start); \ __iter; __iter = __iter->pNext) +#define KROSSHAIR_LOG(fmt, ...) \ + do { \ + FILE* _kf = fopen("/tmp/krosshair.log", "a"); \ + if (_kf) { \ + fprintf(_kf, fmt, ##__VA_ARGS__); \ + fclose(_kf); \ + } \ + } while (0) + #define VK_CHECK(expr) \ do { \ VkResult __result = (expr); \ @@ -383,6 +393,9 @@ typedef struct swapchain_data { VkBuffer crosshair_upload_buffer; VkDeviceMemory crosshair_upload_buffer_mem; + char* crosshair_path; + struct timespec crosshair_mtime; + krosshair_draw_t* draw; } swapchain_data_t; @@ -591,17 +604,40 @@ static void create_or_resize_buffer(device_data_t* device_data, static void shutdown_krosshair_image(swapchain_data_t* data) { device_data_t* device_data = data->device_data; - device_data->vtable.DestroyImageView(device_data->device, - data->crosshair_image_view, NULL); - device_data->vtable.DestroyImage(device_data->device, - data->crosshair_image, NULL); - device_data->vtable.FreeMemory(device_data->device, data->crosshair_mem, - NULL); - - device_data->vtable.DestroyBuffer(device_data->device, - data->crosshair_upload_buffer, NULL); - device_data->vtable.FreeMemory(device_data->device, - data->crosshair_upload_buffer_mem, NULL); + + if (data->crosshair_image_view) { + device_data->vtable.DestroyImageView(device_data->device, + data->crosshair_image_view, NULL); + data->crosshair_image_view = VK_NULL_HANDLE; + } + if (data->crosshair_image) { + device_data->vtable.DestroyImage(device_data->device, + data->crosshair_image, NULL); + data->crosshair_image = VK_NULL_HANDLE; + } + if (data->crosshair_mem) { + device_data->vtable.FreeMemory(device_data->device, data->crosshair_mem, + NULL); + data->crosshair_mem = VK_NULL_HANDLE; + } + + if (data->crosshair_upload_buffer) { + device_data->vtable.DestroyBuffer(device_data->device, + data->crosshair_upload_buffer, NULL); + data->crosshair_upload_buffer = VK_NULL_HANDLE; + } + if (data->crosshair_upload_buffer_mem) { + device_data->vtable.FreeMemory(device_data->device, + data->crosshair_upload_buffer_mem, NULL); + data->crosshair_upload_buffer_mem = VK_NULL_HANDLE; + } + + if (data->descriptor_set) { + device_data->vtable.FreeDescriptorSets(device_data->device, + data->descriptor_pool, + 1, &data->descriptor_set); + data->descriptor_set = VK_NULL_HANDLE; + } } static void update_image_descriptor(swapchain_data_t* data, @@ -811,11 +847,57 @@ static char* get_crosshair_file(const char* path) return expanded_str; } +static int get_file_mtime(const char* path, struct timespec* mtime) +{ + struct stat st; + if (stat(path, &st) != 0) return -1; + *mtime = st.st_mtim; + return 0; +} + static void ensure_swapchain_crosshair(swapchain_data_t* data, VkCommandBuffer cmd_buffer) { device_data_t* device_data = data->device_data; - if (data->crosshair_uploaded) return; + + char* crosshair_path = get_crosshair_file(getenv("KROSSHAIR_IMG")); + int using_file = (crosshair_path != NULL); + + if (data->crosshair_uploaded) { + int needs_reload = 0; + + if (using_file && data->crosshair_path) { + if (strcmp(data->crosshair_path, crosshair_path) != 0) { + KROSSHAIR_LOG("[KROSSHAIR] path changed, reloading\n"); + needs_reload = 1; + } else { + struct timespec new_mtime; + if (get_file_mtime(crosshair_path, &new_mtime) == 0) { + if (new_mtime.tv_sec != data->crosshair_mtime.tv_sec || + new_mtime.tv_nsec != data->crosshair_mtime.tv_nsec) { + KROSSHAIR_LOG("[KROSSHAIR] mtime changed (%ld.%ld -> %ld.%ld), reloading\n", + data->crosshair_mtime.tv_sec, + data->crosshair_mtime.tv_nsec, + new_mtime.tv_sec, + new_mtime.tv_nsec); + needs_reload = 1; + } + } + } + } + + if (!needs_reload) { + free(crosshair_path); + return; + } + + KROSSHAIR_LOG("[KROSSHAIR] shutting down old crosshair image\n"); + + shutdown_krosshair_image(data); + data->crosshair_uploaded = 0; + free(data->crosshair_path); + data->crosshair_path = NULL; + } int tex_width; int tex_height; @@ -823,18 +905,16 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, VkDeviceSize image_size; stbi_uc* pixels; - char* crosshair_path = get_crosshair_file(getenv("KROSSHAIR_IMG")); - - if (crosshair_path) { + if (using_file) { pixels = stbi_load(crosshair_path, &tex_width, &tex_height, &tex_channels, STBI_rgb_alpha); - free(crosshair_path); image_size = tex_width * tex_height * 4; if (!pixels) { printf( "[KROSSHAIR_ERROR] failed to load crosshair " "image.\n"); + free(crosshair_path); return; } @@ -848,7 +928,15 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, tex_height, &data->crosshair_upload_buffer, &data->crosshair_upload_buffer_mem, data->crosshair_image); stbi_image_free(pixels); + + data->crosshair_path = crosshair_path; + get_file_mtime(crosshair_path, &data->crosshair_mtime); + KROSSHAIR_LOG("[KROSSHAIR] loaded crosshair from: %s (mtime %ld.%ld)\n", + crosshair_path, + data->crosshair_mtime.tv_sec, + data->crosshair_mtime.tv_nsec); } else { + free(crosshair_path); tex_width = default_crosshair_width; tex_height = default_crosshair_height; image_size = tex_width * tex_height * 4; From ad5e62ec28302f3ceb967975c62743e4fad08801 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Mon, 20 Apr 2026 02:32:28 -0700 Subject: [PATCH 04/25] feat: enable alpha blending for transparency support Remove alpha discard from fragment shader and enable Vulkan alpha blending so crosshairs with transparency render correctly. --- shaders/shader.frag | 4 ---- src/layer.c | 22 ++++------------------ 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/shaders/shader.frag b/shaders/shader.frag index 261bf45..805e415 100644 --- a/shaders/shader.frag +++ b/shaders/shader.frag @@ -7,8 +7,4 @@ layout(binding = 0) uniform sampler2D tex_sampler; void main() { out_color = texture(tex_sampler, frag_tex_coord); - - if (out_color.a < 0.1) { - discard; - } } diff --git a/src/layer.c b/src/layer.c index bf31d47..4990caa 100644 --- a/src/layer.c +++ b/src/layer.c @@ -50,7 +50,7 @@ VkPhysicalDeviceDriverProperties driver_properties = {}; unsigned char frag_spv[] = { 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00, - 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -94,12 +94,6 @@ unsigned char frag_spv[] = { 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, - 0xcd, 0xcc, 0xcc, 0x3d, 0x14, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, @@ -107,16 +101,8 @@ unsigned char frag_spv[] = { 0x0f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, - 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x1d, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, - 0x1c, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x02, 0x00, - 0x1d, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; + 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, + 0x38, 0x00, 0x01, 0x00}; unsigned char vert_spv[] = { 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00, @@ -1381,7 +1367,7 @@ static void setup_swapchain_data_pipeline(swapchain_data_t* data) ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; VkPipelineColorBlendAttachmentState color_attachment = {}; - color_attachment.blendEnable = VK_FALSE; + color_attachment.blendEnable = VK_TRUE; color_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; From c54d565572a991083f61770f900b3ea4a84592ff Mon Sep 17 00:00:00 2001 From: fibsussy Date: Mon, 20 Apr 2026 02:32:59 -0700 Subject: [PATCH 05/25] feat: auto-detect crosshair-maker for default crosshair path When crosshair-maker is installed, automatically use the currently selected crosshair from ~/.config/crosshair-maker/projects/current.png as the default overlay image. Users can still override with KROSSHAIR_IMG. --- README.md | 4 ++++ src/layer.c | 25 ++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 04ecd04..75ba8f8 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ On nixos-unstable: Add `krosshair` (or clone and add `(callPackage device_data; - char* crosshair_path = get_crosshair_file(getenv("KROSSHAIR_IMG")); + char* crosshair_path = get_crosshair_path(); int using_file = (crosshair_path != NULL); if (data->crosshair_uploaded) { From f34d7fe58bea3e9d827b3e378baf466a57b0b270 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Mon, 20 Apr 2026 02:58:29 -0700 Subject: [PATCH 06/25] chore: remove KROSSHAIR_SCALE, clean up README and install messages Drop the KROSSHAIR_SCALE env var (hardcode scale to 1). Rewrite README to focus on crosshair-maker integration, remove nixos/requirements sections, and update AUR install messages to match. --- .github/workflows/release.yml | 231 ++++++++++++++++++++-------------- README.md | 34 +++-- aur/krosshair.install | 19 ++- src/layer.c | 20 +-- 4 files changed, 170 insertions(+), 134 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 80ff46e..057fdd8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,49 +5,58 @@ on: branches: [main] jobs: + check-skip: + runs-on: ubuntu-latest + outputs: + should_skip: ${{ steps.check.outputs.skip }} + steps: + - name: Check if this is a version bump commit + id: check + run: | + MSG="${{ github.event.head_commit.message }}" + if echo "$MSG" | grep -q "^chore: bump version"; then + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "skip=false" >> $GITHUB_OUTPUT + fi + version: + needs: [check-skip] + if: needs.check-skip.outputs.should_skip == 'false' runs-on: ubuntu-latest outputs: new_version: ${{ steps.bump.outputs.new_version }} + old_version: ${{ steps.bump.outputs.old_version }} steps: - uses: actions/checkout@v5 with: fetch-depth: 0 - - name: Install tools - run: | - sudo apt-get update - sudo apt-get install -y python python-pip - pip install --user bumpver - - name: Calculate version bump + - name: Determine version bump id: bump run: | - LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - if [ -n "$LAST_TAG" ]; then - COMMITS=$(git log $LAST_TAG..HEAD --pretty=%s) - else - COMMITS=$(git log HEAD --pretty=%s) + LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + OLD_VERSION=${LAST_TAG#v} + IFS='.' read -r MAJOR MINOR PATCH <<< "$OLD_VERSION" + + COMMITS=$(git log ${LAST_TAG}..HEAD --pretty=%s 2>/dev/null || git log HEAD --pretty=%s) + + if echo "$COMMITS" | grep -q "^feat:"; then + MINOR=$((MINOR + 1)) + PATCH=0 + elif echo "$COMMITS" | grep -q "^chore:\|^fix:\|^docs:"; then + PATCH=$((PATCH + 1)) fi + if echo "$COMMITS" | grep -q "^BREAKING CHANGE:"; then - bumpver update --major - elif echo "$COMMITS" | grep -q "^feat:"; then - bumpver update --minor - else - bumpver update --patch + MAJOR=$((MAJOR + 1)) + MINOR=0 + PATCH=0 fi - NEW_VERSION=$(bumpver show | grep -E "^[0-9]+\.[0-9]+\.[0-9]+" | head -1) + + NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}" echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT - - name: Bump PKGBUILD versions - run: | - sed -i "s/pkgver=.*/pkgver=${{ steps.bump.outputs.new_version }}/" PKGBUILD - sed -i "s/pkgver=.*/pkgver=${{ steps.bump.outputs.new_version }}/" aur/PKGBUILD - cd aur && makepkg --printsrcinfo > .SRCINFO - - name: Upload version files (uncommitted) - uses: actions/upload-artifact@v6 - with: - name: version-files - path: | - PKGBUILD - aur/ + echo "old_version=$OLD_VERSION" >> $GITHUB_OUTPUT + echo "Bumping $OLD_VERSION -> $NEW_VERSION" build: needs: [version] @@ -56,10 +65,6 @@ jobs: - uses: actions/checkout@v5 with: fetch-depth: 0 - - uses: actions/download-artifact@v7 - with: - name: version-files - path: . - name: Install system dependencies run: | sudo apt-get update @@ -76,26 +81,36 @@ jobs: elif [ "$ARCH" = "aarch64" ]; then echo "arch_name=aarch64" >> $GITHUB_OUTPUT fi + - name: Update PKGBUILD versions + run: | + VERSION=${{ needs.version.outputs.new_version }} + sed -i "s/pkgver=.*/pkgver=$VERSION/" PKGBUILD + sed -i "s/pkgver=.*/pkgver=$VERSION/" aur/PKGBUILD - name: Create tarball run: | - mkdir -p krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }} - cp lib/krosshair.so krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}/ - cp krosshair.json krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}/ - cp LICENSE krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}/ 2>/dev/null || true - tar -czf krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}.tar.gz -C krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }} . - - name: Generate checksum - run: sha256sum krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}.tar.gz > krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }}.sha256 - - name: Upload artifacts + ARCH_NAME=${{ steps.arch.outputs.arch_name }} + VERSION=${{ needs.version.outputs.new_version }} + mkdir -p krosshair-linux-${ARCH_NAME} + cp lib/krosshair.so krosshair-linux-${ARCH_NAME}/ + cp krosshair.json krosshair-linux-${ARCH_NAME}/ + cp LICENSE krosshair-linux-${ARCH_NAME}/ 2>/dev/null || true + tar -czf krosshair-linux-${ARCH_NAME}.tar.gz -C krosshair-linux-${ARCH_NAME} . + sha256sum krosshair-linux-${ARCH_NAME}.tar.gz > krosshair-linux-${ARCH_NAME}.sha256 + - name: Upload build artifacts uses: actions/upload-artifact@v6 with: - name: krosshair-${{ needs.version.outputs.new_version }}-${{ steps.arch.outputs.arch_name }} + name: build-output path: | - krosshair-*.tar.gz - krosshair-*.sha256 + PKGBUILD + aur/ + krosshair-linux-*.tar.gz + krosshair-linux-*.sha256 - commit-and-release: + release: needs: [version, build] runs-on: ubuntu-latest + permissions: + contents: write steps: - uses: actions/checkout@v5 with: @@ -103,63 +118,93 @@ jobs: fetch-depth: 0 - uses: actions/download-artifact@v7 with: - path: artifacts - - name: Restore version files from successful build - run: | - mkdir -p aur - cp artifacts/version-files/PKGBUILD . - cp -r artifacts/version-files/aur/* aur/ - - name: Commit version bump and create tag + name: build-output + path: . + - name: Configure git run: | git config user.name "GitHub Action" git config user.email "action@github.com" - git add PKGBUILD aur/ - git commit -m "chore: bump version to v${{ needs.version.outputs.new_version }}" || echo "No changes to commit" - git tag "v${{ needs.version.outputs.new_version }}" -f - git push origin main - git push origin "v${{ needs.version.outputs.new_version }}" -f + gh auth setup-git env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Push to AUR + - name: Commit version bump and tag run: | - mkdir -p ~/.ssh - echo "$AUR_SSH_KEY" > ~/.ssh/aur - chmod 600 ~/.ssh/aur - ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts - rm -rf aur - if git clone ssh://aur@aur.archlinux.org/krosshair.git aur 2>&1; then - echo "Cloned existing AUR repo" - cp -r artifacts/version-files/aur/* aur/ - cd aur - else - echo "Creating new AUR repo" - mkdir aur - cp -r artifacts/version-files/aur/* aur/ - cd aur - git init - git remote add origin ssh://aur@aur.archlinux.org/krosshair.git - fi - makepkg --printsrcinfo > .SRCINFO - git config user.name "GitHub Action" - git config user.email "action@github.com" - git add PKGBUILD .SRCINFO krosshair.install - git commit -m "Update to v${{ needs.version.outputs.new_version }}" || echo "No changes to commit" - git push origin master + VERSION=${{ needs.version.outputs.new_version }} + git add PKGBUILD aur/ + git commit -m "chore: bump version to v${VERSION}" || echo "No changes to commit" + git tag "v${VERSION}" -f + git push origin main + git push origin "v${VERSION}" -f env: - AUR_SSH_KEY: ${{ secrets.AUR_SSH_KEY }} - - name: Create release with assets + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Create GitHub release run: | - ARCH=$(uname -m) - if [ "$ARCH" = "x86_64" ]; then + VERSION=${{ needs.version.outputs.new_version }} + ARCH_NAME=$(uname -m) + if [ "$ARCH_NAME" = "x86_64" ]; then ARCH_NAME="x86_64" - elif [ "$ARCH" = "aarch64" ]; then + elif [ "$ARCH_NAME" = "aarch64" ]; then ARCH_NAME="aarch64" fi - gh release delete "v${{ needs.version.outputs.new_version }}" --yes 2>/dev/null || true - gh release create "v${{ needs.version.outputs.new_version }}" \ - --title "v${{ needs.version.outputs.new_version }}" \ - --notes "Release v${{ needs.version.outputs.new_version }}" \ - artifacts/krosshair-${{ needs.version.outputs.new_version }}-${ARCH_NAME}/krosshair-${{ needs.version.outputs.new_version }}-${ARCH_NAME}.tar.gz \ - artifacts/krosshair-${{ needs.version.outputs.new_version }}-${ARCH_NAME}/krosshair-${{ needs.version.outputs.new_version }}-${ARCH_NAME}.sha256 + gh release delete "v${VERSION}" --yes 2>/dev/null || true + gh release create "v${VERSION}" \ + --title "v${VERSION}" \ + --notes "Release v${VERSION}" \ + krosshair-linux-${ARCH_NAME}.tar.gz \ + krosshair-linux-${ARCH_NAME}.sha256 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + aur: + needs: [version, build, release] + runs-on: ubuntu-latest + container: archlinux:latest + steps: + - uses: actions/download-artifact@v7 + with: + name: build-output + path: . + - name: Push to AUR + run: | + VERSION=${{ needs.version.outputs.new_version }} + pacman -Sy --noconfirm openssh git sudo + + useradd -m builduser + echo "builduser ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + + mkdir -p /home/builduser/.ssh + echo "$AUR_SSH_KEY" > /home/builduser/.ssh/aur + chmod 600 /home/builduser/.ssh/aur + chmod 700 /home/builduser/.ssh + chown -R builduser:builduser /home/builduser/.ssh + ssh-keyscan aur.archlinux.org >> /home/builduser/.ssh/known_hosts + + cp -r aur /home/builduser/aur + chown -R builduser:builduser /home/builduser/aur + + sudo -u builduser VERSION="$VERSION" bash -c ' + cd /home/builduser + if git clone ssh://aur@aur.archlinux.org/krosshair.git aur-push 2>&1; then + echo "Cloned existing AUR repo" + else + echo "Creating new AUR repo" + mkdir -p aur-push + cd aur-push + git init + git remote add origin ssh://aur@aur.archlinux.org/krosshair.git + cd .. + fi + + cp aur/PKGBUILD aur-push/ + cp aur/krosshair.install aur-push/ + + cd aur-push + makepkg --printsrcinfo > .SRCINFO + git config user.name "GitHub Action" + git config user.email "action@github.com" + git add PKGBUILD .SRCINFO krosshair.install + git commit -m "Update to v${VERSION}" || echo "No changes to commit" + GIT_SSH_COMMAND="ssh -i /home/builduser/.ssh/aur -o StrictHostKeyChecking=no" git push origin master + ' env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + AUR_SSH_KEY: ${{ secrets.AUR_SSH_KEY }} diff --git a/README.md b/README.md index 75ba8f8..fdf234d 100644 --- a/README.md +++ b/README.md @@ -5,27 +5,39 @@ A crosshair overlay for games on linux using vulkan. ![quake](img/quake-crosshair.png) ## Installation -`make && make install` -On nixos-unstable: Add `krosshair` (or clone and add `(callPackage /derivation.nix { })`) to packages and `nixos-rebuild switch`. +### AUR + +```bash +yay -S krosshair +``` + +### From source + +```bash +git clone https://github.com/fibsussy/krosshair.git +cd krosshair +make +``` ## Usage -Simply start the your game with `KROSSHAIR=1` set. When using steam, put `KROSSHAIR=1 %command%` into the launch options of your game. Additionally you can use the following variables to customize your crosshair. -- `KROSSHAIR_IMG=/path/to/crosshair-image.png` (i've provided some crosshairs in [here](https://github.com/krob64/krosshair/tree/main/crosshairs), copy them wherever you like) - - alternatively you can use a [crosshair generator site](https://crosshair.themeta.gg/) (or [this one](https://guywiddacaptain.github.io/aimX/)) + +```bash +export KROSSHAIR=1 +your-game +``` + +For Steam games, add `KROSSHAIR=1 %command%` to launch options. + ## crosshair-maker integration -If you have [crosshair-maker](https://github.com/fibsussy/crosshair-maker) installed, krosshair automatically uses your currently selected crosshair — no configuration needed. The currently active project's exported PNG (`~/.config/crosshair-maker/projects/current.png`) is loaded as the overlay. You can still override this with `KROSSHAIR_IMG` if you want. +krosshair works out of the box with [crosshair-maker](https://github.com/fibsussy/crosshair-maker), a crosshair overlay creator with SVG rendering and preview. The currently selected crosshair is automatically exported to `~/.config/crosshair-maker/projects/current.png`, which krosshair picks up as its default — just launch your game with `export KROSSHAIR=1` and go. -- `KROSSHAIR_SCALE=1.0` (scaling the scrosshair may make it look blurry, i'd suggest to just create a bigger/smaller crosshair) +You can override the image with `export KROSSHAIR_IMG=/path/to/crosshair.png` if you want to use a custom file. ## Can i get banned for this? I don't know, use at your own risk. I've only used it in Quake Champions and STRAFTAT, both of which don't really have an anticheat. -## Setting up requirements -Needs Vulkan libs to build. -All requirements can be set up with `nix-shell' when nix is installed. - ## Issues As of now, the overlay leaks a bit of memory everytime you alt-tab out of/into the game, as well as everytime the window is being resized and upon resolution changes. It's not a big leak and shouldn't cause any problems, but it's still worth noting. I've tried fixing it multiple times but have always hit a dead-end. If someone more experienced with vulkan wants to help, take a look at [this issue](https://github.com/krob64/krosshair/issues/1). I know it's a bit of a mess, this whole project is based on a morally questionable apex legends project which i'm unsure if i should link to it here, coupled with me jumping into it right after completing the vulkan tutorial. diff --git a/aur/krosshair.install b/aur/krosshair.install index 69a628a..de5c536 100644 --- a/aur/krosshair.install +++ b/aur/krosshair.install @@ -4,20 +4,17 @@ post_install() { echo "" echo "==> Getting Started:" echo "" - echo " 1. Run your game with KROSSHAIR=1 set" - echo " Example: KROSSHAIR=1 your-game" + echo " KROSSHAIR=1 your-game" echo "" - echo " 2. For Steam games, add to launch options:" - echo " KROSSHAIR=1 %command%" + echo " For Steam games, add to launch options:" + echo " KROSSHAIR=1 %command%" echo "" - echo "==> Customization:" - echo " KROSSHAIR_IMG=/path/to/crosshair.png" - echo " KROSSHAIR_SCALE=1.0" + echo "==> crosshair-maker integration:" + echo " If crosshair-maker is installed, your currently selected" + echo " crosshair is used automatically. Override with:" + echo " export KROSSHAIR_IMG=/path/to/crosshair.png" echo "" - echo "==> Sample crosshairs installed at:" - echo " /usr/share/krosshair/crosshairs/" - echo "" - echo "==> For more info: https://github.com/fibsussy/krosshair" + echo "==> For more info: https://github.com/krob64/krosshair" echo "" } diff --git a/src/layer.c b/src/layer.c index 9e86953..d2850a0 100644 --- a/src/layer.c +++ b/src/layer.c @@ -962,26 +962,8 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, &data->crosshair_upload_buffer_mem, data->crosshair_image); } - float scale = 1; - const char* scale_str = getenv("KROSSHAIR_SCALE"); - if (scale_str) { - char* end = NULL; - for (float scale_cvt = strtof(scale_str, &end); scale_str != end; - scale_cvt = strtof(scale_str, &end)) { - printf("got scale: %f\n", scale_cvt); - scale = scale_cvt; - scale_str = end; - if (errno == ERANGE) { - printf("KROSSHAIR_SCALE invalid.\n"); - scale = 1; - } - } - } - - printf("scale: %f\n", scale); - setup_vertices((float)data->width, (float)data->height, - (float)tex_height, (float)tex_width, scale); + (float)tex_height, (float)tex_width, 1.0f); data->crosshair_uploaded = 1; } From da6b54e52dc12a5b4eae84c170a62957f523f39d Mon Sep 17 00:00:00 2001 From: fibsussy Date: Mon, 20 Apr 2026 04:08:24 -0700 Subject: [PATCH 07/25] docs: add vkcube testing example to crosshair-maker integration --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fdf234d..eb2dd17 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,18 @@ For Steam games, add `KROSSHAIR=1 %command%` to launch options. ## crosshair-maker integration -krosshair works out of the box with [crosshair-maker](https://github.com/fibsussy/crosshair-maker), a crosshair overlay creator with SVG rendering and preview. The currently selected crosshair is automatically exported to `~/.config/crosshair-maker/projects/current.png`, which krosshair picks up as its default — just launch your game with `export KROSSHAIR=1` and go. +krosshair works out of the box with [crosshair-maker](https://github.com/fibsussy/crosshair-maker), a crosshair overlay creator with SVG rendering and preview. The currently selected crosshair is automatically exported to `~/.config/crosshair-maker/projects/current.png`, which krosshair picks up as its default — just launch your game with `KROSSHAIR=1` and go. You can override the image with `export KROSSHAIR_IMG=/path/to/crosshair.png` if you want to use a custom file. +To test the full setup together with `vkcube`: + +```sh +$ yay -Sy krosshair crosshair-maker vulkan-tools +$ KROSSHAIR=1 vkcube & +$ crosshair-maker & +``` + ## Can i get banned for this? I don't know, use at your own risk. I've only used it in Quake Champions and STRAFTAT, both of which don't really have an anticheat. From 9d7ccfdfaabbcba310cef5834003e47dca008f8d Mon Sep 17 00:00:00 2001 From: fibsussy Date: Mon, 20 Apr 2026 22:42:35 -0700 Subject: [PATCH 08/25] chore: fix aur push - reset hard to match remote --- .github/workflows/release.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 057fdd8..9c45bd8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -186,6 +186,10 @@ jobs: cd /home/builduser if git clone ssh://aur@aur.archlinux.org/krosshair.git aur-push 2>&1; then echo "Cloned existing AUR repo" + cd aur-push + git fetch origin + git reset --hard origin/master + cd .. else echo "Creating new AUR repo" mkdir -p aur-push @@ -195,6 +199,7 @@ jobs: cd .. fi + rm -rf aur-push/* cp aur/PKGBUILD aur-push/ cp aur/krosshair.install aur-push/ From 08e6e64843f0306142ef24cea26dc8c930adaac7 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Mon, 20 Apr 2026 22:57:50 -0700 Subject: [PATCH 09/25] chore: add verbose SSH debugging for aur push --- .github/workflows/release.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9c45bd8..679440b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -182,16 +182,20 @@ jobs: cp -r aur /home/builduser/aur chown -R builduser:builduser /home/builduser/aur - sudo -u builduser VERSION="$VERSION" bash -c ' + sudo -u builduser VERSION="$VERSION" GIT_SSH_COMMAND="ssh -i /home/builduser/.ssh/aur -o StrictHostKeyChecking=no -v" bash -c ' cd /home/builduser - if git clone ssh://aur@aur.archlinux.org/krosshair.git aur-push 2>&1; then + echo "Testing SSH connection..." + ssh -T aur@aur.archlinux.org 2>&1 || true + echo "Attempting to clone AUR repo..." + GIT_SSH_COMMAND="ssh -i /home/builduser/.ssh/aur -o StrictHostKeyChecking=no" git clone ssh://aur@aur.archlinux.org/krosshair.git aur-push 2>&1 || true + if [ -d "aur-push/.git" ]; then echo "Cloned existing AUR repo" cd aur-push git fetch origin git reset --hard origin/master cd .. else - echo "Creating new AUR repo" + echo "Creating new AUR repo (clone failed)" mkdir -p aur-push cd aur-push git init @@ -209,7 +213,7 @@ jobs: git config user.email "action@github.com" git add PKGBUILD .SRCINFO krosshair.install git commit -m "Update to v${VERSION}" || echo "No changes to commit" - GIT_SSH_COMMAND="ssh -i /home/builduser/.ssh/aur -o StrictHostKeyChecking=no" git push origin master + git push origin master ' env: AUR_SSH_KEY: ${{ secrets.AUR_SSH_KEY }} From 45a6e3eb2efcc5f147a6b423d61ea2d57f7ab313 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Mon, 20 Apr 2026 23:26:28 -0700 Subject: [PATCH 10/25] chore: fix linker order for fmod library --- Makefile | 2 +- PKGBUILD | 2 +- aur/PKGBUILD | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 9f5f80d..4ec4476 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ SOURCES = $(shell find src -type f -name "*.c") all: mkdir -p lib - $(CC) $(LDFLAGS) $(CCFLAGS) $(SOURCES) -o $(LIBRARY) + $(CC) $(CCFLAGS) $(SOURCES) $(LDFLAGS) -o $(LIBRARY) install: sudo mkdir -p /usr/lib/krosshair diff --git a/PKGBUILD b/PKGBUILD index 1f0f5ff..907f25f 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.1.0 +pkgver=0.1.1 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') diff --git a/aur/PKGBUILD b/aur/PKGBUILD index 5ae5096..3f2ddf0 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.1.0 +pkgver=0.1.1 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') From 66bb85662fba853e9168d54e50e4f231a884e298 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Mon, 20 Apr 2026 23:32:54 -0700 Subject: [PATCH 11/25] fix: remove verbose SSH debugging --- .github/workflows/release.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 679440b..1e41968 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -182,12 +182,9 @@ jobs: cp -r aur /home/builduser/aur chown -R builduser:builduser /home/builduser/aur - sudo -u builduser VERSION="$VERSION" GIT_SSH_COMMAND="ssh -i /home/builduser/.ssh/aur -o StrictHostKeyChecking=no -v" bash -c ' + sudo -u builduser VERSION="$VERSION" GIT_SSH_COMMAND="ssh -i /home/builduser/.ssh/aur -o StrictHostKeyChecking=no" bash -c ' cd /home/builduser - echo "Testing SSH connection..." - ssh -T aur@aur.archlinux.org 2>&1 || true - echo "Attempting to clone AUR repo..." - GIT_SSH_COMMAND="ssh -i /home/builduser/.ssh/aur -o StrictHostKeyChecking=no" git clone ssh://aur@aur.archlinux.org/krosshair.git aur-push 2>&1 || true + git clone ssh://aur@aur.archlinux.org/krosshair.git aur-push 2>&1 || true if [ -d "aur-push/.git" ]; then echo "Cloned existing AUR repo" cd aur-push From 5b67ac5719b9d17a66c8b0a4862f8f74f44aec37 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Tue, 21 Apr 2026 06:34:25 +0000 Subject: [PATCH 12/25] chore: bump version to v0.1.2 --- PKGBUILD | 2 +- aur/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 907f25f..5529e9b 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.1.1 +pkgver=0.1.2 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') diff --git a/aur/PKGBUILD b/aur/PKGBUILD index 3f2ddf0..6f179ed 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.1.1 +pkgver=0.1.2 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') From a43a4b4925226715115712c095a0d9597cdeca82 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Tue, 21 Apr 2026 06:40:37 -0700 Subject: [PATCH 13/25] feat: supports .apng animated images now --- src/layer.c | 1076 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 992 insertions(+), 84 deletions(-) diff --git a/src/layer.c b/src/layer.c index d2850a0..62e836a 100644 --- a/src/layer.c +++ b/src/layer.c @@ -6,9 +6,11 @@ #include #include #include +#include #include #include #include +#include #include #include "../include/dispatch.h" @@ -311,6 +313,26 @@ typedef struct queue_data { uint32_t family_index; } queue_data_t; +typedef struct static_vk_resources { + VkSampler crosshair_sampler; + VkDescriptorPool descriptor_pool; + VkDescriptorSetLayout descriptor_layout; + VkPipelineLayout pipeline_layout; + VkPipeline pipeline; + VkRenderPass render_pass; + VkCommandPool cmd_pool; + VkSemaphore crossengine_semaphore; + VkSemaphore semaphore; + VkFence fence; + VkBuffer vertex_buffer; + VkDeviceMemory vertex_buffer_mem; + VkDeviceSize vertex_buffer_size; + VkBuffer index_buffer; + VkDeviceMemory index_buffer_mem; + VkDeviceSize index_buffer_size; + int initialized; +} static_vk_resources_t; + typedef struct device_data { device_dispatch_table_t vtable; instance_data_t* instance; @@ -321,6 +343,7 @@ typedef struct device_data { struct queue_data* graphic_queue; struct queue_data* queues[16]; // 16 should be enough? uint32_t queue_count; + static_vk_resources_t* vk_resources; } device_data_t; typedef struct command_buffer_data { @@ -344,6 +367,9 @@ typedef struct krosshair_draw { VkBuffer index_buffer; VkDeviceMemory index_buffer_mem; VkDeviceSize index_buffer_size; + + int vertex_buffer_initialized; + int index_buffer_initialized; } krosshair_draw_t; typedef struct swapchain_data { @@ -382,6 +408,16 @@ typedef struct swapchain_data { char* crosshair_path; struct timespec crosshair_mtime; + /* crosshair texture dimensions (for vertex setup) */ + int crosshair_tex_width; + + /* GIF animation state */ + int gif_frame_count; + int gif_frame_height; /* height of a single frame */ + int* gif_delays; /* delay per frame in ms */ + int gif_current_frame; + struct timespec gif_last_frame_time; + krosshair_draw_t* draw; } swapchain_data_t; @@ -408,11 +444,17 @@ typedef struct swapchain_data { // vertex_t vertices[4] = {0}; -static void setup_vertices(float canvas_width, float canvas_height, - float tex_width, float tex_height, float scale) +/* + * Set up the quad vertices for rendering. + * uv_top / uv_bottom: vertical UV range (0..1 for full texture, + * or a sub-range for atlas frame selection) + */ +static void setup_vertices_uv(float canvas_width, float canvas_height, + float tex_width, float tex_height, float scale, + float uv_top, float uv_bottom) { float width_ndc = ((tex_width * scale) / canvas_width); - float height_ndc = ((tex_width * scale)/ canvas_height) ; + float height_ndc = ((tex_width * scale) / canvas_height); /* should fix even-length crosshairs */ float pixel_offset_x = @@ -422,16 +464,23 @@ static void setup_vertices(float canvas_width, float canvas_height, vertices[0].pos = (vec2_t){-width_ndc + pixel_offset_x, -height_ndc + pixel_offset_y}; - vertices[0].tex_pos = (vec2_t){0.0f, 0.0f}; + vertices[0].tex_pos = (vec2_t){0.0f, uv_top}; vertices[1].pos = (vec2_t){width_ndc + pixel_offset_x, -height_ndc + pixel_offset_y}; - vertices[1].tex_pos = (vec2_t){1.0f, 0.0f}; + vertices[1].tex_pos = (vec2_t){1.0f, uv_top}; vertices[2].pos = (vec2_t){width_ndc + pixel_offset_x, height_ndc + pixel_offset_y}; - vertices[2].tex_pos = (vec2_t){1.0f, 1.0f}; + vertices[2].tex_pos = (vec2_t){1.0f, uv_bottom}; vertices[3].pos = (vec2_t){-width_ndc + pixel_offset_x, height_ndc + pixel_offset_y}; - vertices[3].tex_pos = (vec2_t){0.0f, 1.0f}; + vertices[3].tex_pos = (vec2_t){0.0f, uv_bottom}; +} + +static void setup_vertices(float canvas_width, float canvas_height, + float tex_width, float tex_height, float scale) +{ + setup_vertices_uv(canvas_width, canvas_height, tex_width, tex_height, + scale, 0.0f, 1.0f); } uint16_t indices[] = {0, 1, 2, 2, 3, 0}; @@ -619,11 +668,93 @@ static void shutdown_krosshair_image(swapchain_data_t* data) } if (data->descriptor_set) { - device_data->vtable.FreeDescriptorSets(device_data->device, - data->descriptor_pool, - 1, &data->descriptor_set); + /* use ResetDescriptorPool instead of FreeDescriptorSets + * because the pool was created without + * VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT */ + device_data->vtable.ResetDescriptorPool(device_data->device, + data->descriptor_pool, 0); data->descriptor_set = VK_NULL_HANDLE; } + + /* clean up GIF animation state */ + if (data->gif_delays) { + free(data->gif_delays); + data->gif_delays = NULL; + } + data->gif_frame_count = 0; + data->gif_frame_height = 0; + data->gif_current_frame = 0; + data->crosshair_tex_width = 0; +} + +static void destroy_draw(swapchain_data_t* data, krosshair_draw_t* draw); + +static void destroy_swapchain_data(swapchain_data_t* data) +{ + if (!data) return; + + device_data_t* device_data = data->device_data; + + if (data->draw) { + destroy_draw(data, data->draw); + data->draw = NULL; + } + + shutdown_krosshair_image(data); + + if (data->descriptor_pool != VK_NULL_HANDLE) { + device_data->vtable.DestroyDescriptorPool(device_data->device, + data->descriptor_pool, NULL); + data->descriptor_pool = VK_NULL_HANDLE; + } + if (data->descriptor_layout != VK_NULL_HANDLE) { + device_data->vtable.DestroyDescriptorSetLayout(device_data->device, + data->descriptor_layout, NULL); + data->descriptor_layout = VK_NULL_HANDLE; + } + if (data->crosshair_sampler != VK_NULL_HANDLE) { + device_data->vtable.DestroySampler(device_data->device, + data->crosshair_sampler, NULL); + data->crosshair_sampler = VK_NULL_HANDLE; + } + if (data->pipeline != VK_NULL_HANDLE) { + device_data->vtable.DestroyPipeline(device_data->device, + data->pipeline, NULL); + data->pipeline = VK_NULL_HANDLE; + } + if (data->pipeline_layout != VK_NULL_HANDLE) { + device_data->vtable.DestroyPipelineLayout(device_data->device, + data->pipeline_layout, NULL); + data->pipeline_layout = VK_NULL_HANDLE; + } + if (data->render_pass != VK_NULL_HANDLE) { + device_data->vtable.DestroyRenderPass(device_data->device, + data->render_pass, NULL); + data->render_pass = VK_NULL_HANDLE; + } + if (data->cmd_pool != VK_NULL_HANDLE) { + device_data->vtable.DestroyCommandPool(device_data->device, + data->cmd_pool, NULL); + data->cmd_pool = VK_NULL_HANDLE; + } + + for (uint32_t i = 0; i < data->n_images; i++) { + if (data->framebuffers[i] != VK_NULL_HANDLE) { + device_data->vtable.DestroyFramebuffer(device_data->device, + data->framebuffers[i], NULL); + data->framebuffers[i] = VK_NULL_HANDLE; + } + if (data->image_views[i] != VK_NULL_HANDLE) { + device_data->vtable.DestroyImageView(device_data->device, + data->image_views[i], NULL); + data->image_views[i] = VK_NULL_HANDLE; + } + } + + if (data->crosshair_path) { + free(data->crosshair_path); + data->crosshair_path = NULL; + } } static void update_image_descriptor(swapchain_data_t* data, @@ -723,15 +854,25 @@ static VkDescriptorSet create_image_with_desc(swapchain_data_t* data, return descriptor_set; } -static void upload_image_data(device_data_t* device_data, - VkCommandBuffer cmd_buffer, void* pixels, - VkDeviceSize upload_size, uint32_t width, - uint32_t height, VkBuffer* upload_buffer, - VkDeviceMemory* upload_buffer_mem, VkImage image) +static void create_or_resize_upload_buffer(device_data_t* device_data, + VkBuffer* upload_buffer, + VkDeviceMemory* upload_buffer_mem, + VkDeviceSize new_size) { + if (*upload_buffer != VK_NULL_HANDLE) { + device_data->vtable.DestroyBuffer(device_data->device, *upload_buffer, + NULL); + *upload_buffer = VK_NULL_HANDLE; + } + if (*upload_buffer_mem) { + device_data->vtable.FreeMemory(device_data->device, *upload_buffer_mem, + NULL); + *upload_buffer_mem = VK_NULL_HANDLE; + } + VkBufferCreateInfo buffer_info = {}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.size = upload_size; + buffer_info.size = new_size; buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VK_CHECK(device_data->vtable.CreateBuffer( @@ -751,6 +892,17 @@ static void upload_image_data(device_data_t* device_data, device_data->device, &upload_alloc_info, NULL, upload_buffer_mem)); VK_CHECK(device_data->vtable.BindBufferMemory( device_data->device, *upload_buffer, *upload_buffer_mem, 0)); +} + +static void upload_image_data(device_data_t* device_data, + VkCommandBuffer cmd_buffer, void* pixels, + VkDeviceSize upload_size, uint32_t width, + uint32_t height, VkBuffer* upload_buffer, + VkDeviceMemory* upload_buffer_mem, VkImage image) +{ + /* always create the upload buffer - each swapchain has its own */ + create_or_resize_upload_buffer(device_data, upload_buffer, + upload_buffer_mem, upload_size); char* map = NULL; VK_CHECK(device_data->vtable.MapMemory(device_data->device, @@ -843,6 +995,7 @@ static int get_file_mtime(const char* path, struct timespec* mtime) // malloc's returned string, free later // returns crosshair-maker default if installed and no explicit KROSSHAIR_IMG set +// tries current.apng first, then current.gif, then current.png static char* get_crosshair_path(void) { const char* explicit = getenv("KROSSHAIR_IMG"); @@ -854,16 +1007,423 @@ static char* get_crosshair_path(void) return NULL; char cm_path[4096]; + struct stat st; + + /* prefer animated formats first, then static PNG */ snprintf(cm_path, sizeof(cm_path), - "%s/.config/crosshair-maker/projects/current.png", home); + "%s/.config/crosshair-maker/projects/current.apng", home); + if (stat(cm_path, &st) == 0) + return strdup(cm_path); - struct stat st; + snprintf(cm_path, sizeof(cm_path), + "%s/.config/crosshair-maker/projects/current.apng", home); + if (stat(cm_path, &st) == 0) + return strdup(cm_path); + + snprintf(cm_path, sizeof(cm_path), + "%s/.config/crosshair-maker/projects/current.png", home); if (stat(cm_path, &st) == 0) return strdup(cm_path); return NULL; } +/* ───────────────────── APNG loader ───────────────────── */ + +static const unsigned char png_signature[8] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a +}; + +static uint32_t apng_read_be32(const unsigned char* p) +{ + return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | + ((uint32_t)p[2] << 8) | (uint32_t)p[3]; +} + +static uint16_t apng_read_be16(const unsigned char* p) +{ + return ((uint16_t)p[0] << 8) | (uint16_t)p[1]; +} + +static void apng_write_be32(unsigned char* p, uint32_t v) +{ + p[0] = (v >> 24) & 0xff; + p[1] = (v >> 16) & 0xff; + p[2] = (v >> 8) & 0xff; + p[3] = v & 0xff; +} + +/* CRC32 used by PNG chunk checksums */ +static uint32_t apng_crc32_table[256]; +static int apng_crc32_table_ready = 0; + +static void apng_crc32_init(void) +{ + if (apng_crc32_table_ready) return; + for (uint32_t i = 0; i < 256; i++) { + uint32_t c = i; + for (int j = 0; j < 8; j++) + c = (c & 1) ? (0xEDB88320u ^ (c >> 1)) : (c >> 1); + apng_crc32_table[i] = c; + } + apng_crc32_table_ready = 1; +} + +static uint32_t apng_crc32(const unsigned char* data, size_t len) +{ + uint32_t crc = 0xFFFFFFFF; + for (size_t i = 0; i < len; i++) + crc = apng_crc32_table[(crc ^ data[i]) & 0xff] ^ (crc >> 8); + return crc ^ 0xFFFFFFFF; +} + +/* write a complete PNG chunk: length + type + data + crc */ +static size_t apng_write_chunk(unsigned char* out, const char* type, + const unsigned char* data, uint32_t data_len) +{ + apng_write_be32(out, data_len); + memcpy(out + 4, type, 4); + if (data && data_len) + memcpy(out + 8, data, data_len); + /* CRC covers type + data */ + uint32_t crc = apng_crc32(out + 4, 4 + data_len); + apng_write_be32(out + 8 + data_len, crc); + return 12 + data_len; /* length(4) + type(4) + data + crc(4) */ +} + +typedef struct apng_frame_info { + uint32_t width, height; + uint32_t x_offset, y_offset; + uint16_t delay_num, delay_den; + uint8_t dispose_op, blend_op; + /* raw compressed data (IDAT content or fdAT content minus seq) */ + unsigned char* idat_data; + size_t idat_size; + size_t idat_capacity; +} apng_frame_info_t; + +static void apng_frame_append_idat(apng_frame_info_t* f, + const unsigned char* data, size_t len) +{ + if (f->idat_size + len > f->idat_capacity) { + size_t new_cap = (f->idat_capacity == 0) ? 4096 : f->idat_capacity; + while (new_cap < f->idat_size + len) + new_cap *= 2; + f->idat_data = realloc(f->idat_data, new_cap); + f->idat_capacity = new_cap; + } + memcpy(f->idat_data + f->idat_size, data, len); + f->idat_size += len; +} + +/* + * Build a minimal valid PNG in memory for a single APNG frame, + * then decode it with stbi. Returns RGBA pixels (caller must + * stbi_image_free), or NULL on failure. + * + * ihdr_raw: the 13 bytes of the original IHDR *data* (no length/type/crc) + */ +static stbi_uc* apng_decode_frame(const apng_frame_info_t* f, + const unsigned char* ihdr_raw, + int* out_w, int* out_h) +{ + /* build a new IHDR with the frame's dimensions */ + unsigned char ihdr[13]; + memcpy(ihdr, ihdr_raw, 13); + apng_write_be32(ihdr + 0, f->width); + apng_write_be32(ihdr + 4, f->height); + + /* total PNG size: sig(8) + IHDR chunk(25) + IDAT chunk(12+data) + IEND(12) */ + size_t png_size = 8 + 25 + (12 + f->idat_size) + 12; + unsigned char* png = malloc(png_size); + if (!png) return NULL; + + size_t off = 0; + memcpy(png, png_signature, 8); + off += 8; + off += apng_write_chunk(png + off, "IHDR", ihdr, 13); + off += apng_write_chunk(png + off, "IDAT", f->idat_data, (uint32_t)f->idat_size); + off += apng_write_chunk(png + off, "IEND", NULL, 0); + + int w, h, c; + stbi_uc* pixels = stbi_load_from_memory(png, (int)off, &w, &h, &c, 4); + free(png); + + if (pixels) { + *out_w = w; + *out_h = h; + } + return pixels; +} + +/* alpha-composite src over dst (premultiply-aware, straight alpha) */ +static void apng_blend_over(unsigned char* dst, const unsigned char* src, + uint32_t canvas_w, uint32_t canvas_h, + uint32_t x_off, uint32_t y_off, + uint32_t fw, uint32_t fh) +{ + for (uint32_t y = 0; y < fh; y++) { + if (y + y_off >= canvas_h) break; + for (uint32_t x = 0; x < fw; x++) { + if (x + x_off >= canvas_w) break; + size_t di = ((y + y_off) * canvas_w + (x + x_off)) * 4; + size_t si = (y * fw + x) * 4; + uint8_t sa = src[si + 3]; + if (sa == 255) { + memcpy(dst + di, src + si, 4); + } else if (sa > 0) { + uint8_t da = dst[di + 3]; + /* standard "over" blend */ + for (int k = 0; k < 3; k++) { + int sv = src[si + k] * sa; + int dv = dst[di + k] * da * (255 - sa) / 255; + int oa = sa + da * (255 - sa) / 255; + dst[di + k] = oa ? (uint8_t)((sv + dv) / oa) : 0; + } + dst[di + 3] = (uint8_t)(sa + da * (255 - sa) / 255); + } + } + } +} + +/* copy src frame pixels into canvas at offset (source replace, no blending) */ +static void apng_blend_source(unsigned char* dst, const unsigned char* src, + uint32_t canvas_w, uint32_t canvas_h, + uint32_t x_off, uint32_t y_off, + uint32_t fw, uint32_t fh) +{ + for (uint32_t y = 0; y < fh; y++) { + if (y + y_off >= canvas_h) break; + size_t di = ((y + y_off) * canvas_w + x_off) * 4; + size_t si = (y * fw) * 4; + uint32_t copy_w = fw; + if (x_off + fw > canvas_w) copy_w = canvas_w - x_off; + memcpy(dst + di, src + si, copy_w * 4); + } +} + +/* clear a region to transparent black */ +static void apng_clear_region(unsigned char* canvas, uint32_t canvas_w, + uint32_t canvas_h, uint32_t x, uint32_t y, + uint32_t w, uint32_t h) +{ + for (uint32_t row = y; row < y + h && row < canvas_h; row++) { + size_t off = (row * canvas_w + x) * 4; + uint32_t cw = w; + if (x + w > canvas_w) cw = canvas_w - x; + memset(canvas + off, 0, cw * 4); + } +} + +/* + * Load an APNG file and return a vertical atlas of fully-composited frames, + * identical in layout to what stbi_load_gif_from_memory produces. + * + * Returns RGBA pixel data (free with free()) or NULL on failure. + * *out_width / *out_height are per-frame dimensions. + * *out_frames is the frame count. + * *out_delays is malloc'd array of per-frame delays in ms (free with free()). + */ +static unsigned char* load_apng(const unsigned char* file_data, size_t file_len, + int* out_width, int* out_height, + int* out_frames, int** out_delays) +{ + apng_crc32_init(); + + if (file_len < 8 + 25 || memcmp(file_data, png_signature, 8) != 0) { + KROSSHAIR_LOG("[APNG] not a PNG file\n"); + return NULL; + } + + /* parse IHDR */ + size_t pos = 8; + uint32_t chunk_len = apng_read_be32(file_data + pos); + if (memcmp(file_data + pos + 4, "IHDR", 4) != 0 || chunk_len != 13) { + KROSSHAIR_LOG("[APNG] missing IHDR\n"); + return NULL; + } + const unsigned char* ihdr_data = file_data + pos + 8; + uint32_t canvas_w = apng_read_be32(ihdr_data); + uint32_t canvas_h = apng_read_be32(ihdr_data + 4); + + /* first pass: find acTL and count frames */ + uint32_t num_frames = 0; + int found_actl = 0; + size_t scan = 8; + while (scan + 12 <= file_len) { + uint32_t clen = apng_read_be32(file_data + scan); + const unsigned char* ctype = file_data + scan + 4; + if (scan + 12 + clen > file_len) break; + if (memcmp(ctype, "acTL", 4) == 0 && clen >= 8) { + num_frames = apng_read_be32(file_data + scan + 8); + found_actl = 1; + } + if (memcmp(ctype, "IEND", 4) == 0) break; + scan += 12 + clen; + } + + if (!found_actl || num_frames < 1) { + KROSSHAIR_LOG("[APNG] no acTL chunk or 0 frames (not an APNG)\n"); + return NULL; + } + + /* allocate frame info array */ + apng_frame_info_t* frames = calloc(num_frames, sizeof(apng_frame_info_t)); + if (!frames) return NULL; + + /* second pass: collect fcTL + IDAT/fdAT data per frame */ + int current_frame = -1; /* index into frames[] */ + int first_frame_is_default = 0; /* fcTL before first IDAT? */ + int seen_idat = 0; + + pos = 8; + while (pos + 12 <= file_len) { + uint32_t clen = apng_read_be32(file_data + pos); + const unsigned char* ctype = file_data + pos + 4; + const unsigned char* cdata = file_data + pos + 8; + if (pos + 12 + clen > file_len) break; + + if (memcmp(ctype, "fcTL", 4) == 0 && clen >= 26) { + current_frame++; + if (current_frame >= (int)num_frames) break; + + if (!seen_idat && current_frame == 0) + first_frame_is_default = 1; + + apng_frame_info_t* f = &frames[current_frame]; + f->width = apng_read_be32(cdata + 4); + f->height = apng_read_be32(cdata + 8); + f->x_offset = apng_read_be32(cdata + 12); + f->y_offset = apng_read_be32(cdata + 16); + f->delay_num = apng_read_be16(cdata + 20); + f->delay_den = apng_read_be16(cdata + 22); + f->dispose_op = cdata[24]; + f->blend_op = cdata[25]; + } else if (memcmp(ctype, "IDAT", 4) == 0) { + seen_idat = 1; + if (first_frame_is_default && current_frame == 0) { + apng_frame_append_idat(&frames[0], cdata, clen); + } + } else if (memcmp(ctype, "fdAT", 4) == 0 && clen > 4) { + /* fdAT: first 4 bytes are sequence number, rest is + * IDAT-equivalent data */ + if (current_frame >= 0 && current_frame < (int)num_frames) { + apng_frame_append_idat(&frames[current_frame], + cdata + 4, clen - 4); + } + } else if (memcmp(ctype, "IEND", 4) == 0) { + break; + } + + pos += 12 + clen; + } + + /* the actual number of frames we collected may be less than num_frames + * (e.g., truncated file) */ + int actual_frames = current_frame + 1; + if (actual_frames < 1) { + KROSSHAIR_LOG("[APNG] no frames found\n"); + for (uint32_t i = 0; i < num_frames; i++) + free(frames[i].idat_data); + free(frames); + return NULL; + } + if (actual_frames < (int)num_frames) { + KROSSHAIR_LOG("[APNG] warning: expected %u frames but found %d\n", + num_frames, actual_frames); + } + + /* build vertical atlas: each row is canvas_w x canvas_h */ + size_t frame_stride = (size_t)canvas_w * canvas_h * 4; + unsigned char* atlas = calloc(actual_frames, frame_stride); + int* delays = malloc(sizeof(int) * actual_frames); + unsigned char* canvas = calloc(1, frame_stride); + unsigned char* prev_canvas = NULL; /* for dispose_op = APNG_DISPOSE_OP_PREVIOUS */ + if (!atlas || !delays || !canvas) { + free(atlas); + free(delays); + free(canvas); + for (uint32_t i = 0; i < num_frames; i++) + free(frames[i].idat_data); + free(frames); + return NULL; + } + + for (int i = 0; i < actual_frames; i++) { + apng_frame_info_t* f = &frames[i]; + + /* compute delay in ms */ + uint16_t den = f->delay_den ? f->delay_den : 100; + int delay_ms = (int)((uint32_t)f->delay_num * 1000 / den); + if (delay_ms <= 0) delay_ms = 100; + delays[i] = delay_ms; + + /* save canvas for APNG_DISPOSE_OP_PREVIOUS before compositing */ + if (f->dispose_op == 2) { /* APNG_DISPOSE_OP_PREVIOUS */ + if (!prev_canvas) prev_canvas = malloc(frame_stride); + if (prev_canvas) memcpy(prev_canvas, canvas, frame_stride); + } + + /* decode this frame's pixels */ + if (f->idat_size == 0) { + KROSSHAIR_LOG("[APNG] frame %d has no image data, skipping\n", i); + memcpy(atlas + i * frame_stride, canvas, frame_stride); + continue; + } + + int fw, fh; + stbi_uc* fpix = apng_decode_frame(f, ihdr_data, &fw, &fh); + if (!fpix) { + KROSSHAIR_LOG("[APNG] failed to decode frame %d\n", i); + memcpy(atlas + i * frame_stride, canvas, frame_stride); + continue; + } + + /* apply blend_op */ + if (f->blend_op == 0) { /* APNG_BLEND_OP_SOURCE */ + apng_blend_source(canvas, fpix, canvas_w, canvas_h, + f->x_offset, f->y_offset, + f->width, f->height); + } else { /* APNG_BLEND_OP_OVER */ + apng_blend_over(canvas, fpix, canvas_w, canvas_h, + f->x_offset, f->y_offset, + f->width, f->height); + } + stbi_image_free(fpix); + + /* copy composited canvas to atlas row */ + memcpy(atlas + i * frame_stride, canvas, frame_stride); + + /* apply dispose_op (affects canvas for NEXT frame) */ + if (f->dispose_op == 1) { /* APNG_DISPOSE_OP_BACKGROUND */ + apng_clear_region(canvas, canvas_w, canvas_h, + f->x_offset, f->y_offset, + f->width, f->height); + } else if (f->dispose_op == 2) { /* APNG_DISPOSE_OP_PREVIOUS */ + if (prev_canvas) memcpy(canvas, prev_canvas, frame_stride); + } + /* dispose_op 0 (APNG_DISPOSE_OP_NONE): leave canvas as-is */ + } + + free(canvas); + free(prev_canvas); + for (uint32_t i = 0; i < num_frames; i++) + free(frames[i].idat_data); + free(frames); + + *out_width = (int)canvas_w; + *out_height = (int)canvas_h; + *out_frames = actual_frames; + *out_delays = delays; + + KROSSHAIR_LOG("[APNG] decoded %d frames, canvas %ux%u\n", + actual_frames, canvas_w, canvas_h); + + return atlas; +} + +/* ────────────────── end APNG loader ─────────────────── */ + static void ensure_swapchain_crosshair(swapchain_data_t* data, VkCommandBuffer cmd_buffer) { @@ -915,9 +1475,189 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, stbi_uc* pixels; if (using_file) { - pixels = stbi_load(crosshair_path, &tex_width, &tex_height, - &tex_channels, STBI_rgb_alpha); - image_size = tex_width * tex_height * 4; + const char* ext = strrchr(crosshair_path, '.'); + int is_gif = ext && (strcasecmp(ext, ".gif") == 0); + int is_apng = ext && (strcasecmp(ext, ".apng") == 0); + + /* .png files might also be APNG -- detect by checking for + * acTL chunk if the extension is .png */ + int is_png = ext && (strcasecmp(ext, ".png") == 0); + + if (is_gif) { + FILE* f = fopen(crosshair_path, "rb"); + if (!f) { + KROSSHAIR_LOG("[KROSSHAIR_ERROR] failed to open GIF: %s\n", + crosshair_path); + free(crosshair_path); + return; + } + + fseek(f, 0, SEEK_END); + long file_len = ftell(f); + fseek(f, 0, SEEK_SET); + + if (file_len <= 0 || file_len > (long)INT_MAX) { + KROSSHAIR_LOG("[KROSSHAIR_ERROR] invalid GIF file size: %ld\n", + file_len); + fclose(f); + free(crosshair_path); + return; + } + + unsigned char* file_buf = malloc((size_t)file_len); + if (!file_buf) { + KROSSHAIR_LOG("[KROSSHAIR_ERROR] failed to allocate GIF read buffer\n"); + fclose(f); + free(crosshair_path); + return; + } + + size_t bytes_read = fread(file_buf, 1, (size_t)file_len, f); + fclose(f); + + if ((long)bytes_read != file_len) { + KROSSHAIR_LOG("[KROSSHAIR_ERROR] short read on GIF: %zu/%ld\n", + bytes_read, file_len); + free(file_buf); + free(crosshair_path); + return; + } + + int* delays = NULL; + int frames = 0; + int gif_len = (int)file_len; + stbi_uc* gif_data = stbi_load_gif_from_memory( + file_buf, gif_len, &delays, &tex_width, &tex_height, + &frames, &tex_channels, STBI_rgb_alpha); + free(file_buf); + + if (!gif_data || frames < 1) { + KROSSHAIR_LOG("[KROSSHAIR_ERROR] failed to decode GIF: %s (%s)\n", + crosshair_path, + gif_data ? "no frames" : "decode error"); + if (gif_data) stbi_image_free(gif_data); + if (delays) free(delays); + free(crosshair_path); + return; + } + + /* + * Build a vertical texture atlas: all frames stacked + * top-to-bottom in a single image. The UV coordinates + * are adjusted per-frame to select the right slice. + * + * gif_data from stbi is already laid out as + * [frame0][frame1]...[frameN] contiguously, each + * frame being (tex_width * tex_height * 4) bytes, + * which is exactly the atlas layout we need. + */ + int frame_height = tex_height; + int atlas_height = tex_height * frames; + image_size = (VkDeviceSize)tex_width * atlas_height * 4; + pixels = gif_data; + /* tex_height now refers to the full atlas */ + tex_height = atlas_height; + + /* store animation state */ + data->gif_frame_count = frames; + data->gif_frame_height = frame_height; + data->gif_current_frame = 0; + clock_gettime(CLOCK_MONOTONIC, &data->gif_last_frame_time); + + if (delays) { + data->gif_delays = malloc(sizeof(int) * frames); + for (int gi = 0; gi < frames; gi++) { + /* stbi already converts GIF centisecond + * delays to milliseconds internally + * (10 * cs). delay 0 means "as fast + * as possible", default to ~100ms */ + data->gif_delays[gi] = + delays[gi] > 0 ? delays[gi] : 100; + } + free(delays); + } else { + data->gif_delays = malloc(sizeof(int) * frames); + for (int gi = 0; gi < frames; gi++) + data->gif_delays[gi] = 100; + } + + KROSSHAIR_LOG("[KROSSHAIR] loaded GIF atlas: %dx%d (%d frames, frame_h=%d)\n", + tex_width, atlas_height, frames, frame_height); + } else if (is_apng || is_png) { + /* try to load as APNG; if it's a plain PNG the + * loader will return NULL (no acTL) and we fall + * through to stbi_load below */ + FILE* f = fopen(crosshair_path, "rb"); + if (!f) { + KROSSHAIR_LOG("[KROSSHAIR_ERROR] failed to open: %s\n", + crosshair_path); + free(crosshair_path); + return; + } + + fseek(f, 0, SEEK_END); + long file_len = ftell(f); + fseek(f, 0, SEEK_SET); + + unsigned char* file_buf = NULL; + if (file_len > 0 && file_len <= (long)INT_MAX) { + file_buf = malloc((size_t)file_len); + if (file_buf) { + size_t bytes_read = fread(file_buf, 1, (size_t)file_len, f); + if ((long)bytes_read != file_len) { + free(file_buf); + file_buf = NULL; + } + } + } + fclose(f); + + int* apng_delays = NULL; + int apng_frames = 0; + int apng_w = 0, apng_h = 0; + unsigned char* apng_data = NULL; + + if (file_buf) { + apng_data = load_apng((const unsigned char*)file_buf, + (size_t)file_len, &apng_w, &apng_h, + &apng_frames, &apng_delays); + free(file_buf); + } + + if (apng_data && apng_frames > 1) { + /* animated APNG -- same atlas approach as GIF */ + tex_width = apng_w; + int frame_height = apng_h; + int atlas_height = apng_h * apng_frames; + tex_height = atlas_height; + image_size = (VkDeviceSize)tex_width * atlas_height * 4; + pixels = (stbi_uc*)apng_data; + + data->gif_frame_count = apng_frames; + data->gif_frame_height = frame_height; + data->gif_current_frame = 0; + clock_gettime(CLOCK_MONOTONIC, &data->gif_last_frame_time); + + data->gif_delays = apng_delays; + + KROSSHAIR_LOG("[KROSSHAIR] loaded APNG atlas: %dx%d (%d frames, frame_h=%d)\n", + tex_width, atlas_height, apng_frames, frame_height); + } else { + /* not animated APNG (or single frame) -- + * fall back to regular stbi_load for + * proper PNG handling */ + if (apng_data) free(apng_data); + if (apng_delays) free(apng_delays); + + pixels = stbi_load(crosshair_path, &tex_width, &tex_height, + &tex_channels, STBI_rgb_alpha); + image_size = tex_width * tex_height * 4; + } + } else { + pixels = stbi_load(crosshair_path, &tex_width, &tex_height, + &tex_channels, STBI_rgb_alpha); + image_size = tex_width * tex_height * 4; + } if (!pixels) { printf( @@ -962,8 +1702,20 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, &data->crosshair_upload_buffer_mem, data->crosshair_image); } - setup_vertices((float)data->width, (float)data->height, - (float)tex_height, (float)tex_width, 1.0f); + data->crosshair_tex_width = tex_width; + + if (data->gif_frame_count > 1) { + /* for GIF, use frame dimensions for quad size, + * UV selects first frame from atlas */ + float uv_step = 1.0f / (float)data->gif_frame_count; + setup_vertices_uv((float)data->width, (float)data->height, + (float)data->gif_frame_height, + (float)tex_width, 1.0f, + 0.0f, uv_step); + } else { + setup_vertices((float)data->width, (float)data->height, + (float)tex_height, (float)tex_width, 1.0f); + } data->crosshair_uploaded = 1; } @@ -977,12 +1729,24 @@ static void create_draw(swapchain_data_t* data) krosshair_draw_t* draw = data->draw; if (draw) { - if (device_data->vtable.GetFenceStatus( - device_data->device, draw->fence) == VK_SUCCESS) { + VkResult fence_status = device_data->vtable.GetFenceStatus( + device_data->device, draw->fence); + if (fence_status == VK_SUCCESS) { VK_CHECK(device_data->vtable.ResetFences( device_data->device, 1, &draw->fence)); return; } + if (fence_status == VK_NOT_READY) { + VkResult wait_result = device_data->vtable.WaitForFences( + device_data->device, 1, &draw->fence, VK_TRUE, 100000000); + if (wait_result == VK_SUCCESS) { + VK_CHECK(device_data->vtable.ResetFences( + device_data->device, 1, &draw->fence)); + return; + } + } + destroy_draw(data, draw); + data->draw = NULL; } VkSemaphoreCreateInfo sem_info = {}; @@ -1015,6 +1779,44 @@ static void create_draw(swapchain_data_t* data) data->draw = draw; } +static void destroy_draw(swapchain_data_t* data, krosshair_draw_t* draw) +{ + if (!draw) return; + + device_data_t* device_data = data->device_data; + + if (draw->vertex_buffer != VK_NULL_HANDLE) { + device_data->vtable.DestroyBuffer(device_data->device, + draw->vertex_buffer, NULL); + } + if (draw->vertex_buffer_mem != VK_NULL_HANDLE) { + device_data->vtable.FreeMemory(device_data->device, + draw->vertex_buffer_mem, NULL); + } + if (draw->index_buffer != VK_NULL_HANDLE) { + device_data->vtable.DestroyBuffer(device_data->device, + draw->index_buffer, NULL); + } + if (draw->index_buffer_mem != VK_NULL_HANDLE) { + device_data->vtable.FreeMemory(device_data->device, + draw->index_buffer_mem, NULL); + } + if (draw->semaphore != VK_NULL_HANDLE) { + device_data->vtable.DestroySemaphore(device_data->device, + draw->semaphore, NULL); + } + if (draw->crossengine_semaphore != VK_NULL_HANDLE) { + device_data->vtable.DestroySemaphore(device_data->device, + draw->crossengine_semaphore, NULL); + } + if (draw->fence != VK_NULL_HANDLE) { + device_data->vtable.DestroyFence(device_data->device, + draw->fence, NULL); + } + + free(draw); +} + static krosshair_draw_t* render_swapchain_display( swapchain_data_t* data, queue_data_t* present_queue, const VkSemaphore* wait_semaphores, unsigned n_wait_semaphores, @@ -1024,6 +1826,10 @@ static krosshair_draw_t* render_swapchain_display( create_draw(data); krosshair_draw_t* draw = data->draw; + if (!draw) { + KROSSHAIR_LOG("[KROSSHAIR] create_draw failed, no draw available\n"); + return NULL; + } device_data->vtable.ResetCommandBuffer(draw->cmd_buffer, 0); VkRenderPassBeginInfo render_pass_info = {}; @@ -1062,10 +1868,55 @@ static krosshair_draw_t* render_swapchain_display( device_data->vtable.CmdBeginRenderPass( draw->cmd_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); - // create vertex & index buffers - // since our contents aren't changing at runtime, might as well do - // creation and upload only once somewhere else? upload vertex & index - // data bind vertex & index buffers + /* advance animation frame if needed (GIF or APNG) */ + if (data->gif_frame_count > 1 && data->gif_delays) { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + long elapsed_ms = + (now.tv_sec - data->gif_last_frame_time.tv_sec) * 1000 + + (now.tv_nsec - data->gif_last_frame_time.tv_nsec) / 1000000; + + int advanced = 0; + int delay = data->gif_delays[data->gif_current_frame]; + + /* consume all elapsed time, advancing multiple frames if + * the present rate is lower than the animation rate */ + while (elapsed_ms >= delay) { + /* accumulate: add delay to last_frame_time instead + * of resetting to now, so leftover time carries + * over and the animation stays in sync */ + data->gif_last_frame_time.tv_nsec += (long)delay * 1000000L; + while (data->gif_last_frame_time.tv_nsec >= 1000000000L) { + data->gif_last_frame_time.tv_sec++; + data->gif_last_frame_time.tv_nsec -= 1000000000L; + } + + data->gif_current_frame = + (data->gif_current_frame + 1) % data->gif_frame_count; + delay = data->gif_delays[data->gif_current_frame]; + advanced = 1; + + /* recalculate elapsed from updated base */ + elapsed_ms = + (now.tv_sec - data->gif_last_frame_time.tv_sec) * 1000 + + (now.tv_nsec - data->gif_last_frame_time.tv_nsec) / 1000000; + } + + if (advanced) { + float uv_step = 1.0f / (float)data->gif_frame_count; + float uv_top = uv_step * (float)data->gif_current_frame; + float uv_bot = uv_top + uv_step; + setup_vertices_uv( + (float)data->width, (float)data->height, + (float)data->gif_frame_height, + (float)data->crosshair_tex_width, 1.0f, + uv_top, uv_bot); + + /* force vertex buffer re-upload with new UVs */ + draw->vertex_buffer_initialized = 0; + } + } size_t vertex_size = sizeof(vertices); size_t index_size = sizeof(indices); @@ -1074,45 +1925,51 @@ static krosshair_draw_t* render_swapchain_display( &draw->vertex_buffer_mem, &draw->vertex_buffer_size, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + draw->vertex_buffer_initialized = 0; } if (draw->index_buffer_size < index_size) { create_or_resize_buffer(device_data, &draw->index_buffer, &draw->index_buffer_mem, &draw->index_buffer_size, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + draw->index_buffer_initialized = 0; } - // upload vertex buffer - void* vtx_dst = NULL; - VK_CHECK(device_data->vtable.MapMemory( - device_data->device, draw->vertex_buffer_mem, 0, - draw->vertex_buffer_size, 0, &vtx_dst)); - memcpy(vtx_dst, vertices, (size_t)draw->vertex_buffer_size); + if (!draw->vertex_buffer_initialized) { + void* vtx_dst = NULL; + VK_CHECK(device_data->vtable.MapMemory( + device_data->device, draw->vertex_buffer_mem, 0, + draw->vertex_buffer_size, 0, &vtx_dst)); + memcpy(vtx_dst, vertices, sizeof(vertices)); + + VkMappedMemoryRange vtx_range = {}; + vtx_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + vtx_range.memory = draw->vertex_buffer_mem; + vtx_range.size = VK_WHOLE_SIZE; + VK_CHECK(device_data->vtable.FlushMappedMemoryRanges( + device_data->device, 1, &vtx_range)); + device_data->vtable.UnmapMemory(device_data->device, + draw->vertex_buffer_mem); + draw->vertex_buffer_initialized = 1; + } - VkMappedMemoryRange vtx_range = {}; - vtx_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - vtx_range.memory = draw->vertex_buffer_mem; - vtx_range.size = VK_WHOLE_SIZE; - VK_CHECK(device_data->vtable.FlushMappedMemoryRanges( - device_data->device, 1, &vtx_range)); - device_data->vtable.UnmapMemory(device_data->device, - draw->vertex_buffer_mem); - - // upload index buffer - void* idx_dst = NULL; - VK_CHECK(device_data->vtable.MapMemory( - device_data->device, draw->index_buffer_mem, 0, - draw->index_buffer_size, 0, &idx_dst)); - memcpy(idx_dst, indices, (size_t)draw->index_buffer_size); - - VkMappedMemoryRange idx_range = {}; - idx_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - idx_range.memory = draw->index_buffer_mem; - idx_range.size = VK_WHOLE_SIZE; - VK_CHECK(device_data->vtable.FlushMappedMemoryRanges( - device_data->device, 1, &idx_range)); - device_data->vtable.UnmapMemory(device_data->device, - draw->index_buffer_mem); + if (!draw->index_buffer_initialized) { + void* idx_dst = NULL; + VK_CHECK(device_data->vtable.MapMemory( + device_data->device, draw->index_buffer_mem, 0, + draw->index_buffer_size, 0, &idx_dst)); + memcpy(idx_dst, indices, sizeof(indices)); + + VkMappedMemoryRange idx_range = {}; + idx_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + idx_range.memory = draw->index_buffer_mem; + idx_range.size = VK_WHOLE_SIZE; + VK_CHECK(device_data->vtable.FlushMappedMemoryRanges( + device_data->device, 1, &idx_range)); + device_data->vtable.UnmapMemory(device_data->device, + draw->index_buffer_mem); + draw->index_buffer_initialized = 1; + } device_data->vtable.CmdBindPipeline( draw->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipeline); @@ -1142,8 +1999,9 @@ static krosshair_draw_t* render_swapchain_display( device_data->vtable.CmdBindDescriptorSets( draw->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipeline_layout, 0, 1, &data->descriptor_set, 0, NULL); - device_data->vtable.CmdDrawIndexed(draw->cmd_buffer, sizeof(indices), 1, - 0, 0, 0); + device_data->vtable.CmdDrawIndexed(draw->cmd_buffer, + sizeof(indices) / sizeof(indices[0]), + 1, 0, 0, 0); device_data->vtable.CmdEndRenderPass(draw->cmd_buffer); @@ -1174,13 +2032,18 @@ static krosshair_draw_t* render_swapchain_display( &imb); } - device_data->vtable.EndCommandBuffer(draw->cmd_buffer); + VkResult end_result = device_data->vtable.EndCommandBuffer(draw->cmd_buffer); + if (end_result != VK_SUCCESS) { + KROSSHAIR_LOG("[KROSSHAIR] EndCommandBuffer failed: %d\n", end_result); + return NULL; + } /* when presenting on a different queue than where we're drawing the * crosshair *AND* when the application does not provide a semaphore to * vkQueuePresent, insert our own cross-engine synchronization * semaphore. * */ + VkResult submit_result = VK_SUCCESS; if (n_wait_semaphores == 0 && device_data->graphic_queue->queue != present_queue->queue) { VkPipelineStageFlags stages_wait = @@ -1193,8 +2056,13 @@ static krosshair_draw_t* render_swapchain_display( submit_info.signalSemaphoreCount = 1; submit_info.pSignalSemaphores = &draw->crossengine_semaphore; - device_data->vtable.QueueSubmit(present_queue->queue, 1, - &submit_info, VK_NULL_HANDLE); + submit_result = device_data->vtable.QueueSubmit( + present_queue->queue, 1, &submit_info, VK_NULL_HANDLE); + if (submit_result != VK_SUCCESS) { + KROSSHAIR_LOG("[KROSSHAIR] crossengine QueueSubmit failed: %d\n", + submit_result); + return NULL; + } submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.commandBufferCount = 1; @@ -1205,16 +2073,21 @@ static krosshair_draw_t* render_swapchain_display( submit_info.signalSemaphoreCount = 1; submit_info.pSignalSemaphores = &draw->semaphore; - device_data->vtable.QueueSubmit( + submit_result = device_data->vtable.QueueSubmit( device_data->graphic_queue->queue, 1, &submit_info, draw->fence); + if (submit_result != VK_SUCCESS) { + KROSSHAIR_LOG("[KROSSHAIR] graphic QueueSubmit failed: %d\n", + submit_result); + return NULL; + } } else { /* wait in the fragment stage until the swapchain image is ready */ VkPipelineStageFlags* stages_wait = - malloc(sizeof(*stages_wait) * n_wait_semaphores); - memset(stages_wait, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - sizeof(*stages_wait) * n_wait_semaphores); + malloc(sizeof(*stages_wait) * (n_wait_semaphores ? n_wait_semaphores : 1)); + for (unsigned s = 0; s < n_wait_semaphores; s++) + stages_wait[s] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submit_info = {}; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; @@ -1226,10 +2099,15 @@ static krosshair_draw_t* render_swapchain_display( submit_info.signalSemaphoreCount = 1; submit_info.pSignalSemaphores = &draw->semaphore; - device_data->vtable.QueueSubmit( + submit_result = device_data->vtable.QueueSubmit( device_data->graphic_queue->queue, 1, &submit_info, draw->fence); free(stages_wait); + if (submit_result != VK_SUCCESS) { + KROSSHAIR_LOG("[KROSSHAIR] QueueSubmit failed: %d (wait_sems=%u)\n", + submit_result, n_wait_semaphores); + return NULL; + } } return draw; @@ -1482,6 +2360,7 @@ static void setup_swapchain_data(swapchain_data_t* data, VK_CHECK(device_data->vtable.GetSwapchainImagesKHR( device_data->device, data->swapchain, &n_images, data->images)); + data->n_images = n_images; VkImageViewCreateInfo view_info = {}; view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -1577,37 +2456,54 @@ static VkResult overlay_CreateSwapchainKHR( device_data_t* device_data = FIND_OBJ(device_data_t, device); - VkResult result = device_data->vtable.CreateSwapchainKHR( + /* save reference to old swapchain data - we must NOT destroy it before + * the create call because the driver needs oldSwapchain to be valid */ + swapchain_data_t* old_swapchain_data = NULL; + if (pCreateInfo->oldSwapchain != VK_NULL_HANDLE) { + old_swapchain_data = + FIND_OBJ(swapchain_data_t, pCreateInfo->oldSwapchain); + } + + VkResult result = device_data->vtable.CreateSwapchainKHR( device, &create_info, pAllocator, pSwapchain); if (result != VK_SUCCESS) return result; + /* now that the new swapchain is created, clean up the old one's + * internal resources (Vulkan retires oldSwapchain automatically) */ + if (old_swapchain_data) { + destroy_swapchain_data(old_swapchain_data); + unmap_object(HKEY(old_swapchain_data->swapchain)); + free(old_swapchain_data); + } + swapchain_data_t* swapchain_data = new_swapchain_data(*pSwapchain, device_data); setup_swapchain_data(swapchain_data, pCreateInfo); + KROSSHAIR_LOG("[KROSSHAIR] CreateSwapchainKHR: created %lu (%ux%u, n_images=%u, old=%lu)\n", + (unsigned long)*pSwapchain, pCreateInfo->imageExtent.width, + pCreateInfo->imageExtent.height, swapchain_data->n_images, + (unsigned long)pCreateInfo->oldSwapchain); + return result; } static void overlay_DestroySwapchainKHR(VkDevice device, - VkSwapchainKHR* swapchain, - VkAllocationCallbacks* pAllocator) + VkSwapchainKHR swapchain, + const VkAllocationCallbacks* pAllocator) { device_data_t* device_data = FIND_OBJ(device_data_t, device); swapchain_data_t* data = FIND_OBJ(swapchain_data_t, swapchain); - for (size_t i = 0; i < data->n_images; i++) { - device_data->vtable.DestroyFramebuffer( - device_data->device, data->framebuffers[i], NULL); - device_data->vtable.DestroyImageView( - device_data->device, data->image_views[i], NULL); + if (data) { + destroy_swapchain_data(data); + unmap_object(HKEY(data->swapchain)); + free(data); } - free(data->draw); - unmap_object(HKEY(data->swapchain)); device_data->vtable.DestroySwapchainKHR(device_data->device, - data->swapchain, NULL); - free(data); + swapchain, pAllocator); } static VkResult overlay_CreateInstance(const VkInstanceCreateInfo* pCreateInfo, @@ -1833,6 +2729,11 @@ static VkResult overlay_QueuePresentKHR(VkQueue queue, { queue_data_t* queue_data = FIND_OBJ(queue_data_t, queue); + if (!queue_data) { + KROSSHAIR_LOG("[KROSSHAIR] QueuePresent: queue_data is NULL!\n"); + return VK_SUCCESS; + } + VkResult result = VK_SUCCESS; for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { VkSwapchainKHR swapchain = pPresentInfo->pSwapchains[i]; @@ -1846,9 +2747,14 @@ static VkResult overlay_QueuePresentKHR(VkQueue queue, present_info.pSwapchains = &swapchain; present_info.pImageIndices = &image_index; - krosshair_draw_t* draw = before_present( - swapchain_data, queue_data, pPresentInfo->pWaitSemaphores, - i == 0 ? pPresentInfo->waitSemaphoreCount : 0, image_index); + krosshair_draw_t* draw = NULL; + if (swapchain_data) { + draw = before_present( + swapchain_data, queue_data, + pPresentInfo->pWaitSemaphores, + i == 0 ? pPresentInfo->waitSemaphoreCount : 0, + image_index); + } if (draw) { present_info.pWaitSemaphores = &draw->semaphore; @@ -1858,6 +2764,7 @@ static VkResult overlay_QueuePresentKHR(VkQueue queue, VkResult chain_result = queue_data->device->vtable.QueuePresentKHR(queue, &present_info); + if (present_info.pResults) { pPresentInfo->pResults[i] = chain_result; } @@ -1865,6 +2772,7 @@ static VkResult overlay_QueuePresentKHR(VkQueue queue, result = chain_result; } } + return result; } From 533cc809b0efbc904addd26727de5ac3b679ecc8 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Tue, 21 Apr 2026 13:41:50 +0000 Subject: [PATCH 14/25] chore: bump version to v0.2.0 --- PKGBUILD | 2 +- aur/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 5529e9b..f0a51cb 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.1.2 +pkgver=0.2.0 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') diff --git a/aur/PKGBUILD b/aur/PKGBUILD index 6f179ed..4f1b2c7 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.1.2 +pkgver=0.2.0 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') From f6e6b1d69afbad8ac64633d8d798bcb7fb9d9a42 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Tue, 21 Apr 2026 19:48:48 -0700 Subject: [PATCH 15/25] fix: per-swapchain vertices, conditional logging, CI builds on Arch, cleanup - Move vertices array from global to per-swapchain (fixes multi-swapchain) - Make debug logging conditional via NDEBUG (add make release target) - Build CI on archlinux:latest instead of Ubuntu for AUR compatibility - Fix duplicate .apng check in get_crosshair_path (was missing .gif) - Fix fmt_phys_device memory leak in instance_data_map_physical_devices - Remove unused static_vk_resources_t struct - Rename gif_* fields to anim_* (used for both GIF and APNG) - Include crosshairs/ and krosshair.install in both PKGBUILDs - Replace all printf with KROSSHAIR_LOG --- .github/workflows/pr.yml | 9 +- .github/workflows/release.yml | 23 ++-- Makefile | 14 ++- PKGBUILD | 3 +- aur/PKGBUILD | 6 +- krosshair.install | 25 +++++ src/layer.c | 203 +++++++++++++++------------------- 7 files changed, 152 insertions(+), 131 deletions(-) create mode 100644 krosshair.install diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 07452fd..9a39d91 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -6,14 +6,13 @@ on: jobs: build: runs-on: ubuntu-latest + container: archlinux:latest steps: - - uses: actions/checkout@v5 - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y libvulkan-dev libgl-dev libx11-dev gcc make + run: pacman -Syu --noconfirm base-devel vulkan-headers vulkan-icd-loader libx11 libgl git + - uses: actions/checkout@v5 - name: Build binary - run: make + run: make release - name: Create tarball run: | ARCH=$(uname -m) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1e41968..74677fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,6 +7,7 @@ on: jobs: check-skip: runs-on: ubuntu-latest + container: archlinux:latest outputs: should_skip: ${{ steps.check.outputs.skip }} steps: @@ -24,16 +25,20 @@ jobs: needs: [check-skip] if: needs.check-skip.outputs.should_skip == 'false' runs-on: ubuntu-latest + container: archlinux:latest outputs: new_version: ${{ steps.bump.outputs.new_version }} old_version: ${{ steps.bump.outputs.old_version }} steps: + - name: Install dependencies + run: pacman -Syu --noconfirm git - uses: actions/checkout@v5 with: fetch-depth: 0 - name: Determine version bump id: bump run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") OLD_VERSION=${LAST_TAG#v} IFS='.' read -r MAJOR MINOR PATCH <<< "$OLD_VERSION" @@ -61,16 +66,15 @@ jobs: build: needs: [version] runs-on: ubuntu-latest + container: archlinux:latest steps: + - name: Install system dependencies + run: pacman -Syu --noconfirm base-devel vulkan-headers vulkan-icd-loader libx11 libgl git - uses: actions/checkout@v5 with: fetch-depth: 0 - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y libvulkan-dev libgl-dev libx11-dev gcc make - name: Build binary - run: make + run: make release - name: Determine architecture id: arch run: | @@ -90,10 +94,11 @@ jobs: run: | ARCH_NAME=${{ steps.arch.outputs.arch_name }} VERSION=${{ needs.version.outputs.new_version }} - mkdir -p krosshair-linux-${ARCH_NAME} + mkdir -p krosshair-linux-${ARCH_NAME}/crosshairs cp lib/krosshair.so krosshair-linux-${ARCH_NAME}/ cp krosshair.json krosshair-linux-${ARCH_NAME}/ cp LICENSE krosshair-linux-${ARCH_NAME}/ 2>/dev/null || true + cp -r crosshairs/* krosshair-linux-${ARCH_NAME}/crosshairs/ 2>/dev/null || true tar -czf krosshair-linux-${ARCH_NAME}.tar.gz -C krosshair-linux-${ARCH_NAME} . sha256sum krosshair-linux-${ARCH_NAME}.tar.gz > krosshair-linux-${ARCH_NAME}.sha256 - name: Upload build artifacts @@ -109,9 +114,12 @@ jobs: release: needs: [version, build] runs-on: ubuntu-latest + container: archlinux:latest permissions: contents: write steps: + - name: Install dependencies + run: pacman -Syu --noconfirm git github-cli - uses: actions/checkout@v5 with: ref: main @@ -122,6 +130,7 @@ jobs: path: . - name: Configure git run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" git config user.name "GitHub Action" git config user.email "action@github.com" gh auth setup-git @@ -167,7 +176,7 @@ jobs: - name: Push to AUR run: | VERSION=${{ needs.version.outputs.new_version }} - pacman -Sy --noconfirm openssh git sudo + pacman -Syu --noconfirm openssh git sudo base-devel useradd -m builduser echo "builduser ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers diff --git a/Makefile b/Makefile index 4ec4476..e1acd25 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,26 @@ LIBRARY = lib/krosshair.so -CCFLAGS = -Wall -std=c99 -ggdb -fPIC -shared -I./include/ +CCFLAGS = -Wall -std=c99 -fPIC -shared -I./include/ LDFLAGS = -ldl -lm +# Debug build by default; use `make release` or `make RELEASE=1` for release +ifdef RELEASE +CCFLAGS += -O2 -DNDEBUG +else +CCFLAGS += -ggdb +endif + SOURCES = $(shell find src -type f -name "*.c") -.PHONY: all clean install +.PHONY: all release clean install all: mkdir -p lib $(CC) $(CCFLAGS) $(SOURCES) $(LDFLAGS) -o $(LIBRARY) +release: + $(MAKE) RELEASE=1 all + install: sudo mkdir -p /usr/lib/krosshair sudo cp $(LIBRARY) /usr/lib/krosshair/krosshair.so diff --git a/PKGBUILD b/PKGBUILD index f0a51cb..776dfc4 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -8,11 +8,12 @@ url="https://github.com/fibsussy/krosshair" license=('GPL3') depends=('vulkan-icd-loader' 'libgl' 'libx11') makedepends=('gcc' 'make' 'vulkan-headers') +install=krosshair.install options=('!debug') build() { cd "$startdir" - make + make release } package() { diff --git a/aur/PKGBUILD b/aur/PKGBUILD index 4f1b2c7..beaaa9d 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -8,6 +8,7 @@ url="https://github.com/fibsussy/krosshair" license=('GPL3') depends=('vulkan-icd-loader' 'libgl' 'libx11') makedepends=() +install=krosshair.install options=('!debug') _arch="$CARCH" @@ -27,4 +28,7 @@ package() { install -Dm755 "$srcdir/krosshair.so" "$pkgdir/usr/lib/krosshair/krosshair.so" install -Dm644 "$srcdir/krosshair.json" "$pkgdir/usr/share/vulkan/implicit_layer.d/krosshair.json" install -Dm644 "$srcdir/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" -} \ No newline at end of file + + install -dm755 "$pkgdir/usr/share/krosshair/crosshairs" + cp -r "$srcdir/crosshairs/"* "$pkgdir/usr/share/krosshair/crosshairs/" 2>/dev/null || true +} diff --git a/krosshair.install b/krosshair.install new file mode 100644 index 0000000..de5c536 --- /dev/null +++ b/krosshair.install @@ -0,0 +1,25 @@ +post_install() { + echo "" + echo "==> krosshair installed successfully!" + echo "" + echo "==> Getting Started:" + echo "" + echo " KROSSHAIR=1 your-game" + echo "" + echo " For Steam games, add to launch options:" + echo " KROSSHAIR=1 %command%" + echo "" + echo "==> crosshair-maker integration:" + echo " If crosshair-maker is installed, your currently selected" + echo " crosshair is used automatically. Override with:" + echo " export KROSSHAIR_IMG=/path/to/crosshair.png" + echo "" + echo "==> For more info: https://github.com/krob64/krosshair" + echo "" +} + +post_upgrade() { + echo "" + echo "==> krosshair upgraded successfully!" + echo "" +} \ No newline at end of file diff --git a/src/layer.c b/src/layer.c index 62e836a..b7ef70b 100644 --- a/src/layer.c +++ b/src/layer.c @@ -30,6 +30,9 @@ (const struct VkBaseInStructure*)(__start); \ __iter; __iter = __iter->pNext) +#ifdef NDEBUG +#define KROSSHAIR_LOG(fmt, ...) ((void)0) +#else #define KROSSHAIR_LOG(fmt, ...) \ do { \ FILE* _kf = fopen("/tmp/krosshair.log", "a"); \ @@ -38,12 +41,13 @@ fclose(_kf); \ } \ } while (0) +#endif #define VK_CHECK(expr) \ do { \ VkResult __result = (expr); \ if (__result != VK_SUCCESS) { \ - printf("error\n"); \ + KROSSHAIR_LOG("[KROSSHAIR_ERROR] VK_CHECK failed: %d\n", __result); \ } \ } while (0) @@ -271,16 +275,16 @@ int vk_map_get(vk_object_map_t* map, uint64_t obj, vk_object_t* obj_out) void vk_map_print(vk_object_map_t* map) { - printf( + KROSSHAIR_LOG( "#################################### [ITERATING MAP] " "######################################\n"); for (size_t i = 0; i < MAX_VK_OBJECTS; i++) { if (map->data[i].obj == 0) continue; - printf("item %lu (%s) has obj: \t\t %lu, data \t\t %p\n", i, + KROSSHAIR_LOG("item %lu (%s) has obj: \t\t %lu, data \t\t %p\n", i, map->data[i].name, map->data[i].obj, map->data[i].data); } - printf( + KROSSHAIR_LOG( "##################################################################" "####" "#####################\n"); @@ -313,26 +317,6 @@ typedef struct queue_data { uint32_t family_index; } queue_data_t; -typedef struct static_vk_resources { - VkSampler crosshair_sampler; - VkDescriptorPool descriptor_pool; - VkDescriptorSetLayout descriptor_layout; - VkPipelineLayout pipeline_layout; - VkPipeline pipeline; - VkRenderPass render_pass; - VkCommandPool cmd_pool; - VkSemaphore crossengine_semaphore; - VkSemaphore semaphore; - VkFence fence; - VkBuffer vertex_buffer; - VkDeviceMemory vertex_buffer_mem; - VkDeviceSize vertex_buffer_size; - VkBuffer index_buffer; - VkDeviceMemory index_buffer_mem; - VkDeviceSize index_buffer_size; - int initialized; -} static_vk_resources_t; - typedef struct device_data { device_dispatch_table_t vtable; instance_data_t* instance; @@ -343,7 +327,6 @@ typedef struct device_data { struct queue_data* graphic_queue; struct queue_data* queues[16]; // 16 should be enough? uint32_t queue_count; - static_vk_resources_t* vk_resources; } device_data_t; typedef struct command_buffer_data { @@ -411,45 +394,27 @@ typedef struct swapchain_data { /* crosshair texture dimensions (for vertex setup) */ int crosshair_tex_width; - /* GIF animation state */ - int gif_frame_count; - int gif_frame_height; /* height of a single frame */ - int* gif_delays; /* delay per frame in ms */ - int gif_current_frame; - struct timespec gif_last_frame_time; + /* per-swapchain vertex data (avoids global shared across swapchains) */ + vertex_t vertices[4]; + + /* animation state (GIF / APNG) */ + int anim_frame_count; + int anim_frame_height; /* height of a single frame */ + int* anim_delays; /* delay per frame in ms */ + int anim_current_frame; + struct timespec anim_last_frame_time; krosshair_draw_t* draw; } swapchain_data_t; -// TODO: change all of this to be adjustable at runtime -// const float texture_size_px = 24.0f; -// const float screen_width = 1920.0f; -// const float screen_height = 1080.0f; -// -// const float width = (texture_size_px / screen_width) * 2.0f; -// const float height = (texture_size_px / screen_height) * 2.0f; -// -// const float tex_height = 520.0f; -// const float tex_width = 520.0f; -// -// const float texture_correct_width = width * (tex_height / tex_width); - -// vertex_t vertices[] = { -// {{-texture_correct_width, -height}, {0.0f, 0.0f}}, -// { {texture_correct_width, -height}, {1.0f, 0.0f}}, -// { {texture_correct_width, height}, {1.0f, 1.0f}}, -// { {-texture_correct_width, height}, {0.0f, 1.0f}} -// }; -// -vertex_t vertices[4] = {0}; - /* * Set up the quad vertices for rendering. * uv_top / uv_bottom: vertical UV range (0..1 for full texture, * or a sub-range for atlas frame selection) */ -static void setup_vertices_uv(float canvas_width, float canvas_height, +static void setup_vertices_uv(vertex_t* vertices, + float canvas_width, float canvas_height, float tex_width, float tex_height, float scale, float uv_top, float uv_bottom) { @@ -476,11 +441,12 @@ static void setup_vertices_uv(float canvas_width, float canvas_height, vertices[3].tex_pos = (vec2_t){0.0f, uv_bottom}; } -static void setup_vertices(float canvas_width, float canvas_height, +static void setup_vertices(vertex_t* vertices, + float canvas_width, float canvas_height, float tex_width, float tex_height, float scale) { - setup_vertices_uv(canvas_width, canvas_height, tex_width, tex_height, - scale, 0.0f, 1.0f); + setup_vertices_uv(vertices, canvas_width, canvas_height, tex_width, + tex_height, scale, 0.0f, 1.0f); } uint16_t indices[] = {0, 1, 2, 2, 3, 0}; @@ -554,8 +520,8 @@ static instance_data_t* new_instance_data(VkInstance instance) { instance_data_t* instance_data = malloc(sizeof(instance_data_t)); instance_data->instance = instance; - printf("[*] mapping data->instance obj: %lu data: %p\n", - HKEY(instance_data->instance), instance_data); + KROSSHAIR_LOG("[*] mapping data->instance obj: %lu data: %p\n", + HKEY(instance_data->instance), (void*)instance_data); map_object(HKEY(instance_data->instance), instance_data, "instance_data->instance"); return instance_data; @@ -567,8 +533,8 @@ static device_data_t* new_device_data(VkDevice device, device_data_t* device_data = malloc(sizeof(device_data_t)); device_data->instance = instance; device_data->device = device; - printf("[*] mapping data->device obj: %lu %p\n", - HKEY(device_data->device), device_data); + KROSSHAIR_LOG("[*] mapping data->device obj: %lu %p\n", + HKEY(device_data->device), (void*)device_data); map_object(HKEY(device_data->device), device_data, "device_data->device"); return device_data; @@ -582,8 +548,8 @@ static cmd_buffer_data_t* new_cmd_buffer_data(VkCommandBuffer cmd_buffer, cmdbuffer_data->device_data = device_data; cmdbuffer_data->cmd_buffer = cmd_buffer; cmdbuffer_data->level = level; - printf("[*] mapping data->cmd_buffer obj: %lu %p\n", - HKEY(cmdbuffer_data->cmd_buffer), cmdbuffer_data); + KROSSHAIR_LOG("[*] mapping data->cmd_buffer obj: %lu %p\n", + HKEY(cmdbuffer_data->cmd_buffer), (void*)cmdbuffer_data); map_object(HKEY(cmdbuffer_data->cmd_buffer), cmdbuffer_data, "cmdbuffer_data->cmd_buffer"); return cmdbuffer_data; @@ -676,14 +642,14 @@ static void shutdown_krosshair_image(swapchain_data_t* data) data->descriptor_set = VK_NULL_HANDLE; } - /* clean up GIF animation state */ - if (data->gif_delays) { - free(data->gif_delays); - data->gif_delays = NULL; + /* clean up animation state */ + if (data->anim_delays) { + free(data->anim_delays); + data->anim_delays = NULL; } - data->gif_frame_count = 0; - data->gif_frame_height = 0; - data->gif_current_frame = 0; + data->anim_frame_count = 0; + data->anim_frame_height = 0; + data->anim_current_frame = 0; data->crosshair_tex_width = 0; } @@ -1016,7 +982,7 @@ static char* get_crosshair_path(void) return strdup(cm_path); snprintf(cm_path, sizeof(cm_path), - "%s/.config/crosshair-maker/projects/current.apng", home); + "%s/.config/crosshair-maker/projects/current.gif", home); if (stat(cm_path, &st) == 0) return strdup(cm_path); @@ -1559,26 +1525,26 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, tex_height = atlas_height; /* store animation state */ - data->gif_frame_count = frames; - data->gif_frame_height = frame_height; - data->gif_current_frame = 0; - clock_gettime(CLOCK_MONOTONIC, &data->gif_last_frame_time); + data->anim_frame_count = frames; + data->anim_frame_height = frame_height; + data->anim_current_frame = 0; + clock_gettime(CLOCK_MONOTONIC, &data->anim_last_frame_time); if (delays) { - data->gif_delays = malloc(sizeof(int) * frames); + data->anim_delays = malloc(sizeof(int) * frames); for (int gi = 0; gi < frames; gi++) { /* stbi already converts GIF centisecond * delays to milliseconds internally * (10 * cs). delay 0 means "as fast * as possible", default to ~100ms */ - data->gif_delays[gi] = + data->anim_delays[gi] = delays[gi] > 0 ? delays[gi] : 100; } free(delays); } else { - data->gif_delays = malloc(sizeof(int) * frames); + data->anim_delays = malloc(sizeof(int) * frames); for (int gi = 0; gi < frames; gi++) - data->gif_delays[gi] = 100; + data->anim_delays[gi] = 100; } KROSSHAIR_LOG("[KROSSHAIR] loaded GIF atlas: %dx%d (%d frames, frame_h=%d)\n", @@ -1633,12 +1599,12 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, image_size = (VkDeviceSize)tex_width * atlas_height * 4; pixels = (stbi_uc*)apng_data; - data->gif_frame_count = apng_frames; - data->gif_frame_height = frame_height; - data->gif_current_frame = 0; - clock_gettime(CLOCK_MONOTONIC, &data->gif_last_frame_time); + data->anim_frame_count = apng_frames; + data->anim_frame_height = frame_height; + data->anim_current_frame = 0; + clock_gettime(CLOCK_MONOTONIC, &data->anim_last_frame_time); - data->gif_delays = apng_delays; + data->anim_delays = apng_delays; KROSSHAIR_LOG("[KROSSHAIR] loaded APNG atlas: %dx%d (%d frames, frame_h=%d)\n", tex_width, atlas_height, apng_frames, frame_height); @@ -1660,7 +1626,7 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, } if (!pixels) { - printf( + KROSSHAIR_LOG( "[KROSSHAIR_ERROR] failed to load crosshair " "image.\n"); free(crosshair_path); @@ -1704,16 +1670,18 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, data->crosshair_tex_width = tex_width; - if (data->gif_frame_count > 1) { - /* for GIF, use frame dimensions for quad size, + if (data->anim_frame_count > 1) { + /* for animated crosshairs, use frame dimensions for quad size, * UV selects first frame from atlas */ - float uv_step = 1.0f / (float)data->gif_frame_count; - setup_vertices_uv((float)data->width, (float)data->height, - (float)data->gif_frame_height, + float uv_step = 1.0f / (float)data->anim_frame_count; + setup_vertices_uv(data->vertices, + (float)data->width, (float)data->height, + (float)data->anim_frame_height, (float)tex_width, 1.0f, 0.0f, uv_step); } else { - setup_vertices((float)data->width, (float)data->height, + setup_vertices(data->vertices, + (float)data->width, (float)data->height, (float)tex_height, (float)tex_width, 1.0f); } @@ -1869,16 +1837,16 @@ static krosshair_draw_t* render_swapchain_display( draw->cmd_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); /* advance animation frame if needed (GIF or APNG) */ - if (data->gif_frame_count > 1 && data->gif_delays) { + if (data->anim_frame_count > 1 && data->anim_delays) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); long elapsed_ms = - (now.tv_sec - data->gif_last_frame_time.tv_sec) * 1000 + - (now.tv_nsec - data->gif_last_frame_time.tv_nsec) / 1000000; + (now.tv_sec - data->anim_last_frame_time.tv_sec) * 1000 + + (now.tv_nsec - data->anim_last_frame_time.tv_nsec) / 1000000; int advanced = 0; - int delay = data->gif_delays[data->gif_current_frame]; + int delay = data->anim_delays[data->anim_current_frame]; /* consume all elapsed time, advancing multiple frames if * the present rate is lower than the animation rate */ @@ -1886,30 +1854,31 @@ static krosshair_draw_t* render_swapchain_display( /* accumulate: add delay to last_frame_time instead * of resetting to now, so leftover time carries * over and the animation stays in sync */ - data->gif_last_frame_time.tv_nsec += (long)delay * 1000000L; - while (data->gif_last_frame_time.tv_nsec >= 1000000000L) { - data->gif_last_frame_time.tv_sec++; - data->gif_last_frame_time.tv_nsec -= 1000000000L; + data->anim_last_frame_time.tv_nsec += (long)delay * 1000000L; + while (data->anim_last_frame_time.tv_nsec >= 1000000000L) { + data->anim_last_frame_time.tv_sec++; + data->anim_last_frame_time.tv_nsec -= 1000000000L; } - data->gif_current_frame = - (data->gif_current_frame + 1) % data->gif_frame_count; - delay = data->gif_delays[data->gif_current_frame]; + data->anim_current_frame = + (data->anim_current_frame + 1) % data->anim_frame_count; + delay = data->anim_delays[data->anim_current_frame]; advanced = 1; /* recalculate elapsed from updated base */ elapsed_ms = - (now.tv_sec - data->gif_last_frame_time.tv_sec) * 1000 + - (now.tv_nsec - data->gif_last_frame_time.tv_nsec) / 1000000; + (now.tv_sec - data->anim_last_frame_time.tv_sec) * 1000 + + (now.tv_nsec - data->anim_last_frame_time.tv_nsec) / 1000000; } if (advanced) { - float uv_step = 1.0f / (float)data->gif_frame_count; - float uv_top = uv_step * (float)data->gif_current_frame; + float uv_step = 1.0f / (float)data->anim_frame_count; + float uv_top = uv_step * (float)data->anim_current_frame; float uv_bot = uv_top + uv_step; setup_vertices_uv( + data->vertices, (float)data->width, (float)data->height, - (float)data->gif_frame_height, + (float)data->anim_frame_height, (float)data->crosshair_tex_width, 1.0f, uv_top, uv_bot); @@ -1918,7 +1887,7 @@ static krosshair_draw_t* render_swapchain_display( } } - size_t vertex_size = sizeof(vertices); + size_t vertex_size = sizeof(data->vertices); size_t index_size = sizeof(indices); if (draw->vertex_buffer_size < vertex_size) { create_or_resize_buffer(device_data, &draw->vertex_buffer, @@ -1940,7 +1909,7 @@ static krosshair_draw_t* render_swapchain_display( VK_CHECK(device_data->vtable.MapMemory( device_data->device, draw->vertex_buffer_mem, 0, draw->vertex_buffer_size, 0, &vtx_dst)); - memcpy(vtx_dst, vertices, sizeof(vertices)); + memcpy(vtx_dst, data->vertices, sizeof(data->vertices)); VkMappedMemoryRange vtx_range = {}; vtx_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; @@ -2419,13 +2388,17 @@ static void instance_data_map_physical_devices(instance_data_t* instance_data, for (uint32_t i = 0; i < physical_device_count; i++) { if (map) { - printf("[*] mapping physical_devices[%d] obj: %lu %p\n", - i, HKEY(physical_devices[i]), instance_data); + KROSSHAIR_LOG("[*] mapping physical_devices[%d] obj: %lu %p\n", + i, HKEY(physical_devices[i]), (void*)instance_data); char* fmt_phys_device; asprintf(&fmt_phys_device, "physical_devices[%d]", i); map_object(HKEY(physical_devices[i]), instance_data, fmt_phys_device); } else { + /* free the name string we allocated with asprintf */ + vk_object_t obj; + if (vk_map_get(&vk_obj_map, HKEY(physical_devices[i]), &obj)) + free((char*)obj.name); unmap_object(HKEY(physical_devices[i])); } } @@ -2440,8 +2413,8 @@ static swapchain_data_t* new_swapchain_data(VkSwapchainKHR swapchain, memset(swapchain_data, 0, sizeof(*swapchain_data)); swapchain_data->device_data = device_data; swapchain_data->swapchain = swapchain; - printf("[*] mapping data->swapchain obj: %lu %p\n", - HKEY(swapchain_data->swapchain), swapchain_data); + KROSSHAIR_LOG("[*] mapping data->swapchain obj: %lu %p\n", + HKEY(swapchain_data->swapchain), (void*)swapchain_data); map_object(HKEY(swapchain_data->swapchain), swapchain_data, "swapchain_data->swapchain"); return swapchain_data; @@ -2547,8 +2520,8 @@ static queue_data_t* new_queue_data(VkQueue queue, queue_data->queue = queue; queue_data->flags = family_props->queueFlags; queue_data->family_index = family_index; - printf("[*] mapping data->queue obj: %lu %p\n", HKEY(queue_data->queue), - queue_data); + KROSSHAIR_LOG("[*] mapping data->queue obj: %lu %p\n", HKEY(queue_data->queue), + (void*)queue_data); map_object(HKEY(queue_data->queue), queue_data, "queue_data->queue"); if (queue_data->flags & VK_QUEUE_GRAPHICS_BIT) { From 0d49e08058820c015bad6e349834af457dbdefb5 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Wed, 22 Apr 2026 02:51:28 +0000 Subject: [PATCH 16/25] chore: bump version to v0.2.1 --- PKGBUILD | 2 +- aur/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 776dfc4..5f16dbb 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.0 +pkgver=0.2.1 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') diff --git a/aur/PKGBUILD b/aur/PKGBUILD index beaaa9d..e8d2fca 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.0 +pkgver=0.2.1 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') From 09b5f5f97a6ed372c1ffe4d41eb318e4647b19c6 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Tue, 21 Apr 2026 20:07:52 -0700 Subject: [PATCH 17/25] fix: version AUR source filenames to prevent stale cache --- aur/PKGBUILD | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aur/PKGBUILD b/aur/PKGBUILD index e8d2fca..4d714ca 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -19,15 +19,15 @@ elif [ "$_arch" = "aarch64" ]; then fi source=( - "https://github.com/fibsussy/krosshair/releases/download/v${pkgver}/krosshair-linux-${_arch}.tar.gz" - "LICENSE::https://raw.githubusercontent.com/fibsussy/krosshair/v${pkgver}/LICENSE" + "krosshair-${pkgver}-linux-${_arch}.tar.gz::https://github.com/fibsussy/krosshair/releases/download/v${pkgver}/krosshair-linux-${_arch}.tar.gz" + "LICENSE-${pkgver}::https://raw.githubusercontent.com/fibsussy/krosshair/v${pkgver}/LICENSE" ) sha256sums=('SKIP' 'SKIP') package() { install -Dm755 "$srcdir/krosshair.so" "$pkgdir/usr/lib/krosshair/krosshair.so" install -Dm644 "$srcdir/krosshair.json" "$pkgdir/usr/share/vulkan/implicit_layer.d/krosshair.json" - install -Dm644 "$srcdir/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + install -Dm644 "$srcdir/LICENSE-${pkgver}" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" install -dm755 "$pkgdir/usr/share/krosshair/crosshairs" cp -r "$srcdir/crosshairs/"* "$pkgdir/usr/share/krosshair/crosshairs/" 2>/dev/null || true From 3aff5d9544121be34f48a8da5bf9247558504cba Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Wed, 22 Apr 2026 03:10:24 +0000 Subject: [PATCH 18/25] chore: bump version to v0.2.2 --- PKGBUILD | 2 +- aur/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 5f16dbb..62eca62 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.1 +pkgver=0.2.2 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') diff --git a/aur/PKGBUILD b/aur/PKGBUILD index 4d714ca..43ed528 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.1 +pkgver=0.2.2 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') From 38769faa1b149c31f2915fd43733a6ec7253ca7d Mon Sep 17 00:00:00 2001 From: fibsussy Date: Sat, 25 Apr 2026 01:59:54 -0700 Subject: [PATCH 19/25] single dynamic mask with 7 effects --- shaders/dynamic.frag | 132 +++++++ shaders/dynamic_frag.spv | Bin 0 -> 11544 bytes shaders/dynamic_spv.h | 8 + shaders/dynamic_vert.spv | Bin 0 -> 988 bytes src/layer.c | 777 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 903 insertions(+), 14 deletions(-) create mode 100644 shaders/dynamic.frag create mode 100644 shaders/dynamic_frag.spv create mode 100644 shaders/dynamic_spv.h create mode 100644 shaders/dynamic_vert.spv diff --git a/shaders/dynamic.frag b/shaders/dynamic.frag new file mode 100644 index 0000000..7dddd9e --- /dev/null +++ b/shaders/dynamic.frag @@ -0,0 +1,132 @@ +#version 450 + +layout(location = 0) in vec2 frag_tex_coord; +layout(location = 0) out vec4 out_color; + +layout(binding = 0) uniform sampler2D mask_sampler; +layout(binding = 1) uniform sampler2D game_fb_sampler; + +// Push constants: 76 bytes total. Fixed processing order. +layout(push_constant) uniform PushConstants { + vec2 quad_ndc_min; // NDC min corner of the mask quad + vec2 quad_ndc_size; // NDC size of the mask quad + float invert_str; // Invert strength (0 = disabled) + float dodge_str; // Dodge strength + float dodge_r; // Dodge tint R + float dodge_g; // Dodge tint G + float dodge_b; // Dodge tint B + float burn_str; // Burn strength + float burn_r; // Burn tint R + float burn_g; // Burn tint G + float burn_b; // Burn tint B + float complement_str; // Complement strength + float lumainvert_str; // Luma Invert strength + float huerotate_str; // Hue Rotate strength + float huerotate_angle; // Hue Rotate angle (degrees) + float saturate_str; // Saturate strength + float saturate_amount; // Saturate amount (0-1) +} pc; + +// ── RGB <-> HSL conversions ────────────────────────────────────── + +vec3 rgb_to_hsl(vec3 c) { + float mx = max(c.r, max(c.g, c.b)); + float mn = min(c.r, min(c.g, c.b)); + float l = (mx + mn) * 0.5; + float d = mx - mn; + + if (d < 0.00001) return vec3(0.0, 0.0, l); + + float s = (l > 0.5) ? d / (2.0 - mx - mn) : d / (mx + mn); + float h; + + if (mx == c.r) + h = mod((c.g - c.b) / d, 6.0); + else if (mx == c.g) + h = (c.b - c.r) / d + 2.0; + else + h = (c.r - c.g) / d + 4.0; + + h /= 6.0; + if (h < 0.0) h += 1.0; + + return vec3(h, s, l); +} + +float hue_to_rgb(float p, float q, float t) { + if (t < 0.0) t += 1.0; + if (t > 1.0) t -= 1.0; + if (t < 1.0/6.0) return p + (q - p) * 6.0 * t; + if (t < 1.0/2.0) return q; + if (t < 2.0/3.0) return p + (q - p) * (2.0/3.0 - t) * 6.0; + return p; +} + +vec3 hsl_to_rgb(vec3 hsl) { + float h = hsl.x, s = hsl.y, l = hsl.z; + if (s < 0.00001) return vec3(l); + float q = (l < 0.5) ? l * (1.0 + s) : l + s - l * s; + float p = 2.0 * l - q; + return vec3( + hue_to_rgb(p, q, h + 1.0/3.0), + hue_to_rgb(p, q, h), + hue_to_rgb(p, q, h - 1.0/3.0) + ); +} + +void main() { + // Binary mask: check red channel (grayscale) + float mask = texture(mask_sampler, frag_tex_coord).r; + if (mask < 0.5) discard; + + // Sample game framebuffer + vec2 ndc = pc.quad_ndc_min + frag_tex_coord * pc.quad_ndc_size; + vec2 screen_uv = ndc * 0.5 + 0.5; + vec3 color = texture(game_fb_sampler, screen_uv).rgb; + + // Fixed order: invert → dodge → burn → complement → luma_invert → hue_rotate → saturate + + if (pc.invert_str > 0.0) { + color = mix(color, vec3(1.0) - color, pc.invert_str); + } + + if (pc.dodge_str > 0.0) { + vec3 dodged = min(color + vec3(pc.dodge_r, pc.dodge_g, pc.dodge_b), vec3(1.0)); + color = mix(color, dodged, pc.dodge_str); + } + + if (pc.burn_str > 0.0) { + vec3 burned = max(color - vec3(pc.burn_r, pc.burn_g, pc.burn_b), vec3(0.0)); + color = mix(color, burned, pc.burn_str); + } + + if (pc.complement_str > 0.0) { + vec3 hsl = rgb_to_hsl(color); + hsl.x = mod(hsl.x + 0.5, 1.0); + hsl.y = 1.0; + hsl.z = 1.0 - hsl.z; + color = mix(color, hsl_to_rgb(hsl), pc.complement_str); + } + + if (pc.lumainvert_str > 0.0) { + vec3 hsl = rgb_to_hsl(color); + hsl.z = 1.0 - hsl.z; + color = mix(color, hsl_to_rgb(hsl), pc.lumainvert_str); + } + + if (pc.huerotate_str > 0.0) { + vec3 hsl = rgb_to_hsl(color); + hsl.x = mod(hsl.x + pc.huerotate_angle / 360.0, 1.0); + hsl.z = 1.0 - hsl.z; + color = mix(color, hsl_to_rgb(hsl), pc.huerotate_str); + } + + if (pc.saturate_str > 0.0) { + vec3 hsl = rgb_to_hsl(color); + hsl.y = pc.saturate_amount; + hsl.z = 1.0 - hsl.z; + color = mix(color, hsl_to_rgb(hsl), pc.saturate_str); + } + + out_color = vec4(color, 1.0); +} diff --git a/shaders/dynamic_frag.spv b/shaders/dynamic_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..9ac95e89b75075857fa11daf8752a55d0e2b618b GIT binary patch literal 11544 zcmbW6cYs|*6~-TI5?X-Jr3eWG37tp@F%Squ2oNL`1qE3)o6RPY-3?nJAS#g-RC+HW zphy(~0RamL#0H98Y>0pzv0*_){r%p%-(zzB^smA6`@(O9Xm zMq|~+FIQ?bpLH55qcqUQG}{AbA31xcq2YNu?Y8?a2CUWSXvP_{c4L*sC|a$rYhk~R z)p0zFjU!H-2|yi;+GsqAJ{q-*AI&^#;2Z3n+c`YYxnO9~q$Trrokm^PJ5=FgX%|%Z;Q~JjPRw#}#(4^yJf8!%@*mast+;EjtB=-t zy;$Qf)%YK4{LeN1a*e-I zX=`)aV|t$Fjtur!L$+gAjozHUHP33%dd;b&d8V8F=f1XX&wuxTrR?kJZ?B~ zjd;7t^|gF!;^R&X4h(k<%4UH!d_ddQ*W^R5ha4UY`I)~)UH?zDYfeFG!? z!_7T>9UHKi%Q%|WS$ zv-ZuiF{*Jq+XXO+)ceFX?so?S+EL(whG%hP*FJHkos&U;4yrXe@5qrl9zEO=Y ztiU@OPZY6FuHYNhczOjsy7{gf7#Zfcx7L0jYxI6hpbkFaTefJEdrvlR^N#izp2ezj z54NiO(dg1p^PENV+^e}~(K;&4cUm;hyK%28G|#)*W`*W?R~uhwo_Dp0g=P+FlM2nV zuC_y=dDhi-DKyWz+HQsB8CTo0&^+5}dli~zT5aD#^DL{)EHvw(HVd=#l2%b?#HTN$FmN`uLjqxZoJ$(r)K=Xy1%$?Ehnq zy%FPh9=zA)BKKXY=ALg19uKBz?uC3436K3Z1siKF)>i)(7(eY=c)oq&-x;1->;ksG z`R~C0UFQ@u_b--y)6qTC;RnF2QTRb{-y7kx;f@=A4BYX{WGvN@Qk=$ z@@Fe;4_0qot%;9u|3I-O#+rlQm8^l>bLDrRlKa^iZf*SBEV-YLCHM2Ot%vWO$(Z%n8FLQz>W!8D5Har6u5dN)ynD4f*vGxnw;QJB z{)ipNJoW%PU-+ICKZ9}gPlfxQQ%^o`0@w4IhNeD;?CiG}SS>cTTKC>){4{o|=5~Bz zvu^#bkYjSS&Aj`7op(BxI_wKpPaS4})l!H3!9LbO-+q{ybr5IWZw6b3%yl5xxemZG z*DSDlVh#oya}bu8L%`~ZITUQnY%DQv0jsB0hk+g2zWSC{wVwkvFa2Yws&zda%ui!$ zOuu_$?Pk*I%X*Fgm-~7o+?eEb6u4f?x1y;hueX8KV%fu^(fDcZq4PMlvDriY?qTX| zn|a?3cHU#K)Z-ms_3YuXV72VwJHbBgp}ylVHTO`QHFtu`J?w%z*9ldO_hv3wJ^9Q7 z8`F&?pB}J!VtT>G%*PV50IZ%`Ed)EZef8!3ybEkz`m=|N!2C47_v=3qvv$YR>dSii zz~vtH!;MK^17Pzy21{Ox!RpEDB(Pd6dpL;3Pje5Q$FYsg9_n`wQ)k=EI}CQ-AuRKb zfYq~yOTcQ`!;`^2?xDVSV`}c9IBR|n*fpESskHK`)qOY(?DrRS{io2XnU~)g-V0Xq zyMFR|A6$JYG4B8S!D_zW&#Sc4;p%>m%UDa{8Oyok#>M}E%J1(H`sHQ+Gb+EoS0tA+ z(bPQ~=5kimM?K@74R&7pIj-Ee)aM*9|aq4>~*yAdE~cu({ujCHGH*)t6Ow?mn>Ez1Y%9yC3XW`tnZr3|PIq z(+|LtgE`8LOO6j#{_-q6gr=Ue^jWZDs;A%Qz>b?cFE=iA`#jjXg+B~7-WwEerntIOCV_>yd&eG#({4~#!c{skY&TUTmJxked+sykVu=6g*vL9at ztLH3z1+12{^fj=LXGz~zF*VPUI5qe>*!j)lNm_Yo@C~qMNnQUFv}(!gn_%;L3QJz! z0;^|Fz74it-tTf_;{Q(NFZcSpXzJPP?}6QG_4NBb*m1Mha^teDAAns~_z%IxyN;)6 zcVhS2$G?e8Ao(qHvyYR`OexDuAZ3JS23Qm zoJIeJs-BqfV8n)Nw!i-P{M&bY&Tp*wx?lQICx3@@4dFY3jagc~ z*Zq6BG3x%^z&gDVQ}_FyW4h;R8NJCW-5;#xdY%6O zS|8`v_h#%ZnB#~u&VgXp5q=QZx}**VgJ)sti8%yZ)@nA~IQ4w~9tw7Beb#R#t(xx@ zb2AU~$(VZ$~m1oa~=gYFJouW%Hw-0*!gqT z-v(YCEARNxaP@mRb5m)L!R)8*9=wCr$34*ZcB}_;?c$7m9N4ip!!rLn!Rm=Q9&Ai` z*E-?q*{c)4_EXO|U0~~)8qEctfT`y@&^)kuH)bu4rB$g?1lv#D+MG!1V{P=k3me9qOPqBt0@v5who+vG{wk*2n*lWS)Mhc*e(G7rN#L?J zgK*>2msanQA+Wl4Ahl7mHm<>Z%{#e_fX%neWeHq8G4HNo%KbhWO+ERZ0=A!e@;wz? z=KCJFaq7wUy~hE(NRYjk(Wf z(E7N~`aXcESvPUUIScGKS;yI6wKK7-L(RO?-!}cv0oy-(8F)s)&js&@-B`x?7})$0^Kr0o>Z$!rVCUE8nUR~Hd1joO!R0z{fvZi%T<2}HKCV;W zt(cnQh%?UZVAth5V*SR&|4DE;&!^yOcVfLG3puPez3VD<}+aPP)|J{0NYnzv~zgqDbe3q>Vegv})8)K>C7r~EUzGJP2Jn@f#jo%DQ{NrGCzrOEaKg1kIoN>MfcAW6e3uX8w8#{3buoa4vva*m(CjZsgZpMuLi&%o`I9DW8iMm_iTS+Ha2OI~Va zUgnoMehxNwW4#~p_?`zlf987uJPT7#%rC(9%ly9t8>jA=&(W$S{#RhnX=?i$u-dP& z#QY9yKl^(JG!P{gn$jjmZGXSR3!Bzl)rVsGbug)T2DQ4!oyLw?N49)Y2<$hij8^poQ-Ee6pTZ$ z8LOwa<%2Nl1fM=ScSbLrJ&c0MV=#+)Vc%bz;heMg(P(kz$se9so*ujhVRzzs;*tOI zI_(X+^4IN;$I}7YwEch5F0sZmRgeFKk0+_vvs`vuJY%N+uj39nd^#O_IOf*WFaBx@ z78q~Kn3;pATapWE9;+gC*zahUR<0{5x~~twV(OQLv&wY^>vWEJ%han1uPJjMuBIK{ zTn)~Mx^(Nx&inNoGiNyZinvert_str = 0.0f; + pc->dodge_str = 0.0f; + pc->dodge_r = 1.0f; pc->dodge_g = 1.0f; pc->dodge_b = 1.0f; + pc->burn_str = 0.0f; + pc->burn_r = 1.0f; pc->burn_g = 1.0f; pc->burn_b = 1.0f; + pc->complement_str = 0.0f; + pc->lumainvert_str = 0.0f; + pc->huerotate_str = 0.0f; + pc->huerotate_angle = 180.0f; + pc->saturate_str = 0.0f; + pc->saturate_amount = 0.0f; + + if (!path) return; + + FILE* f = fopen(path, "r"); + if (!f) return; + + char line[512]; + while (fgets(line, sizeof(line), f)) { + /* skip comments and blank lines */ + if (line[0] == '#' || line[0] == '\n' || line[0] == '\r') + continue; + + char name[64]; + float a1 = 0, a2 = 0, a3 = 0, a4 = 0; + int n = sscanf(line, "%63s %f %f %f %f", name, &a1, &a2, &a3, &a4); + if (n < 2) continue; + + if (strcmp(name, "invert") == 0) { + pc->invert_str = a1; + } else if (strcmp(name, "dodge") == 0) { + pc->dodge_str = a1; + if (n >= 5) { pc->dodge_r = a2; pc->dodge_g = a3; pc->dodge_b = a4; } + } else if (strcmp(name, "burn") == 0) { + pc->burn_str = a1; + if (n >= 5) { pc->burn_r = a2; pc->burn_g = a3; pc->burn_b = a4; } + } else if (strcmp(name, "complement") == 0) { + pc->complement_str = a1; + } else if (strcmp(name, "lumainvert") == 0) { + pc->lumainvert_str = a1; + } else if (strcmp(name, "huerotate") == 0) { + pc->huerotate_str = a1; + if (n >= 3) pc->huerotate_angle = a2; + } else if (strcmp(name, "saturate") == 0) { + pc->saturate_str = a1; + if (n >= 3) pc->saturate_amount = a2; + } + } + fclose(f); +} + typedef struct swapchain_data { device_data_t* device_data; @@ -406,6 +478,39 @@ typedef struct swapchain_data { krosshair_draw_t* draw; + /* ── single dynamic effect mask (optional) ── */ + struct { + int uploaded; + VkImage image; + VkImageView image_view; + VkDeviceMemory mem; + VkBuffer upload_buffer; + VkDeviceMemory upload_buffer_mem; + VkDescriptorSet descriptor_set; + char* path; + struct timespec mtime; + int tex_width; + vertex_t vertices[4]; + } dynamic_mask; + char* dynamic_cfg_path; + struct timespec dynamic_cfg_mtime; + struct dynamic_push_constants dynamic_pc; + + /* game framebuffer copy (for shader-based dynamic effects) */ + VkImage game_fb_image; + VkImageView game_fb_image_view; + VkDeviceMemory game_fb_mem; + uint32_t game_fb_width, game_fb_height; + + /* separate descriptor set layout + pipeline for shader-based dynamic */ + VkDescriptorSetLayout shader_desc_layout; + VkDescriptorPool shader_desc_pool; + VkPipelineLayout shader_pipeline_layout; + VkPipeline shader_pipeline; + + /* descriptor set for dynamic mask + game_fb */ + VkDescriptorSet shader_mask_desc_set; + } swapchain_data_t; /* @@ -602,6 +707,8 @@ static void create_or_resize_buffer(device_data_t* device_data, *buffer_size = new_size; } +static void shutdown_dynamic_mask(swapchain_data_t* data); + static void shutdown_krosshair_image(swapchain_data_t* data) { device_data_t* device_data = data->device_data; @@ -634,12 +741,28 @@ static void shutdown_krosshair_image(swapchain_data_t* data) } if (data->descriptor_set) { - /* use ResetDescriptorPool instead of FreeDescriptorSets - * because the pool was created without - * VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT */ + /* Tear down dynamic mask GPU resources BEFORE resetting the pool, + * since its descriptor set comes from the same pool and + * would become invalid. shutdown_dynamic_mask only destroys + * image/view/memory — the descriptor_set handle is wiped + * by the pool reset below. */ + shutdown_dynamic_mask(data); + data->dynamic_mask.uploaded = 0; + if (data->dynamic_mask.path) { + free(data->dynamic_mask.path); + data->dynamic_mask.path = NULL; + } + device_data->vtable.ResetDescriptorPool(device_data->device, data->descriptor_pool, 0); data->descriptor_set = VK_NULL_HANDLE; + + /* also reset shader desc pool (shader mask desc set is invalid) */ + if (data->shader_desc_pool) { + device_data->vtable.ResetDescriptorPool( + device_data->device, data->shader_desc_pool, 0); + data->shader_mask_desc_set = VK_NULL_HANDLE; + } } /* clean up animation state */ @@ -653,6 +776,40 @@ static void shutdown_krosshair_image(swapchain_data_t* data) data->crosshair_tex_width = 0; } +static void shutdown_dynamic_mask(swapchain_data_t* data) +{ + device_data_t* device_data = data->device_data; + + if (data->dynamic_mask.image_view) { + device_data->vtable.DestroyImageView(device_data->device, + data->dynamic_mask.image_view, NULL); + data->dynamic_mask.image_view = VK_NULL_HANDLE; + } + if (data->dynamic_mask.image) { + device_data->vtable.DestroyImage(device_data->device, + data->dynamic_mask.image, NULL); + data->dynamic_mask.image = VK_NULL_HANDLE; + } + if (data->dynamic_mask.mem) { + device_data->vtable.FreeMemory(device_data->device, + data->dynamic_mask.mem, NULL); + data->dynamic_mask.mem = VK_NULL_HANDLE; + } + if (data->dynamic_mask.upload_buffer) { + device_data->vtable.DestroyBuffer(device_data->device, + data->dynamic_mask.upload_buffer, NULL); + data->dynamic_mask.upload_buffer = VK_NULL_HANDLE; + } + if (data->dynamic_mask.upload_buffer_mem) { + device_data->vtable.FreeMemory(device_data->device, + data->dynamic_mask.upload_buffer_mem, NULL); + data->dynamic_mask.upload_buffer_mem = VK_NULL_HANDLE; + } + + data->dynamic_mask.descriptor_set = VK_NULL_HANDLE; + data->dynamic_mask.tex_width = 0; +} + static void destroy_draw(swapchain_data_t* data, krosshair_draw_t* draw); static void destroy_swapchain_data(swapchain_data_t* data) @@ -667,6 +824,44 @@ static void destroy_swapchain_data(swapchain_data_t* data) } shutdown_krosshair_image(data); + shutdown_dynamic_mask(data); + + /* shader-based dynamic resources */ + if (data->game_fb_image_view) { + device_data->vtable.DestroyImageView(device_data->device, + data->game_fb_image_view, NULL); + data->game_fb_image_view = VK_NULL_HANDLE; + } + if (data->game_fb_image) { + device_data->vtable.DestroyImage(device_data->device, + data->game_fb_image, NULL); + data->game_fb_image = VK_NULL_HANDLE; + } + if (data->game_fb_mem) { + device_data->vtable.FreeMemory(device_data->device, + data->game_fb_mem, NULL); + data->game_fb_mem = VK_NULL_HANDLE; + } + if (data->shader_pipeline != VK_NULL_HANDLE) { + device_data->vtable.DestroyPipeline(device_data->device, + data->shader_pipeline, NULL); + data->shader_pipeline = VK_NULL_HANDLE; + } + if (data->shader_pipeline_layout != VK_NULL_HANDLE) { + device_data->vtable.DestroyPipelineLayout(device_data->device, + data->shader_pipeline_layout, NULL); + data->shader_pipeline_layout = VK_NULL_HANDLE; + } + if (data->shader_desc_pool != VK_NULL_HANDLE) { + device_data->vtable.DestroyDescriptorPool(device_data->device, + data->shader_desc_pool, NULL); + data->shader_desc_pool = VK_NULL_HANDLE; + } + if (data->shader_desc_layout != VK_NULL_HANDLE) { + device_data->vtable.DestroyDescriptorSetLayout(device_data->device, + data->shader_desc_layout, NULL); + data->shader_desc_layout = VK_NULL_HANDLE; + } if (data->descriptor_pool != VK_NULL_HANDLE) { device_data->vtable.DestroyDescriptorPool(device_data->device, @@ -675,7 +870,7 @@ static void destroy_swapchain_data(swapchain_data_t* data) } if (data->descriptor_layout != VK_NULL_HANDLE) { device_data->vtable.DestroyDescriptorSetLayout(device_data->device, - data->descriptor_layout, NULL); + data->descriptor_layout, NULL); data->descriptor_layout = VK_NULL_HANDLE; } if (data->crosshair_sampler != VK_NULL_HANDLE) { @@ -721,6 +916,14 @@ static void destroy_swapchain_data(swapchain_data_t* data) free(data->crosshair_path); data->crosshair_path = NULL; } + if (data->dynamic_mask.path) { + free(data->dynamic_mask.path); + data->dynamic_mask.path = NULL; + } + if (data->dynamic_cfg_path) { + free(data->dynamic_cfg_path); + data->dynamic_cfg_path = NULL; + } } static void update_image_descriptor(swapchain_data_t* data, @@ -994,6 +1197,44 @@ static char* get_crosshair_path(void) return NULL; } +// malloc's returned string, free later +// returns the path to {stem}.dynamic.png, or NULL if absent +static char* get_dynamic_mask_path(void) +{ + const char* home = getenv("HOME"); + if (!home) return NULL; + + char cm_path[4096]; + struct stat st; + + snprintf(cm_path, sizeof(cm_path), + "%s/.config/crosshair-maker/projects/current.dynamic.png", + home); + if (stat(cm_path, &st) == 0) + return strdup(cm_path); + + return NULL; +} + +// malloc's returned string, free later +// returns the path to {stem}.dynamic.cfg, or NULL if absent +static char* get_dynamic_cfg_path(void) +{ + const char* home = getenv("HOME"); + if (!home) return NULL; + + char cm_path[4096]; + struct stat st; + + snprintf(cm_path, sizeof(cm_path), + "%s/.config/crosshair-maker/projects/current.dynamic.cfg", + home); + if (stat(cm_path, &st) == 0) + return strdup(cm_path); + + return NULL; +} + /* ───────────────────── APNG loader ───────────────────── */ static const unsigned char png_signature[8] = { @@ -1688,6 +1929,141 @@ static void ensure_swapchain_crosshair(swapchain_data_t* data, data->crosshair_uploaded = 1; } +/* + * Load the single dynamic mask + parse the config file. + * Both are optional — if no mask file exists, nothing happens. + */ +static void ensure_swapchain_dynamic_mask(swapchain_data_t* data, + VkCommandBuffer cmd_buffer) +{ + device_data_t* device_data = data->device_data; + + char* mpath = get_dynamic_mask_path(); + int using_file = (mpath != NULL); + + /* ── check for mask image reload ── */ + if (data->dynamic_mask.uploaded) { + int needs_reload = 0; + + if (using_file && data->dynamic_mask.path) { + if (strcmp(data->dynamic_mask.path, mpath) != 0) { + needs_reload = 1; + } else { + struct timespec new_mtime; + if (get_file_mtime(mpath, &new_mtime) == 0) { + if (new_mtime.tv_sec != data->dynamic_mask.mtime.tv_sec || + new_mtime.tv_nsec != data->dynamic_mask.mtime.tv_nsec) { + needs_reload = 1; + } + } + } + } else if (!using_file && data->dynamic_mask.path) { + shutdown_dynamic_mask(data); + data->dynamic_mask.uploaded = 0; + free(data->dynamic_mask.path); + data->dynamic_mask.path = NULL; + free(mpath); + return; + } + + if (!needs_reload) { + free(mpath); + /* still check cfg for hot-reload */ + goto check_cfg; + } + + shutdown_dynamic_mask(data); + data->dynamic_mask.uploaded = 0; + free(data->dynamic_mask.path); + data->dynamic_mask.path = NULL; + /* invalidate shader desc set so it gets re-created */ + if (data->shader_desc_pool) { + device_data->vtable.ResetDescriptorPool( + device_data->device, data->shader_desc_pool, 0); + data->shader_mask_desc_set = VK_NULL_HANDLE; + } + } + + if (!using_file) { + free(mpath); + return; + } + + int tex_width, tex_height, tex_channels; + stbi_uc* pixels = stbi_load(mpath, &tex_width, &tex_height, + &tex_channels, STBI_rgb_alpha); + if (!pixels) { + KROSSHAIR_LOG("[KROSSHAIR_ERROR] failed to load dynamic mask: %s\n", + mpath); + free(mpath); + return; + } + + VkDeviceSize image_size = (VkDeviceSize)tex_width * tex_height * 4; + + data->dynamic_mask.descriptor_set = create_image_with_desc( + data, tex_width, tex_height, VK_FORMAT_R8G8B8A8_SRGB, + &data->dynamic_mask.image, &data->dynamic_mask.mem, + &data->dynamic_mask.image_view); + + upload_image_data( + device_data, cmd_buffer, pixels, image_size, tex_width, + tex_height, &data->dynamic_mask.upload_buffer, + &data->dynamic_mask.upload_buffer_mem, data->dynamic_mask.image); + stbi_image_free(pixels); + + data->dynamic_mask.path = mpath; + get_file_mtime(mpath, &data->dynamic_mask.mtime); + data->dynamic_mask.tex_width = tex_width; + + setup_vertices(data->dynamic_mask.vertices, + (float)data->width, (float)data->height, + (float)tex_height, (float)tex_width, 1.0f); + + data->dynamic_mask.uploaded = 1; + KROSSHAIR_LOG("[KROSSHAIR] loaded dynamic mask from: %s\n", mpath); + + /* invalidate shader desc set so it gets re-created with new image view */ + if (data->shader_desc_pool) { + device_data->vtable.ResetDescriptorPool( + device_data->device, data->shader_desc_pool, 0); + data->shader_mask_desc_set = VK_NULL_HANDLE; + } + +check_cfg: + /* ── check for config file reload ── */ + { + char* cfg_path = get_dynamic_cfg_path(); + int cfg_exists = (cfg_path != NULL); + + if (cfg_exists && data->dynamic_cfg_path) { + struct timespec new_mtime; + if (get_file_mtime(cfg_path, &new_mtime) == 0) { + if (new_mtime.tv_sec != data->dynamic_cfg_mtime.tv_sec || + new_mtime.tv_nsec != data->dynamic_cfg_mtime.tv_nsec) { + parse_dynamic_cfg(cfg_path, &data->dynamic_pc); + data->dynamic_cfg_mtime = new_mtime; + KROSSHAIR_LOG("[KROSSHAIR] reloaded dynamic cfg: %s\n", cfg_path); + } + } + } else if (cfg_exists) { + /* first time loading cfg */ + parse_dynamic_cfg(cfg_path, &data->dynamic_pc); + get_file_mtime(cfg_path, &data->dynamic_cfg_mtime); + data->dynamic_cfg_path = cfg_path; + cfg_path = NULL; /* don't free, ownership transferred */ + KROSSHAIR_LOG("[KROSSHAIR] loaded dynamic cfg: %s\n", data->dynamic_cfg_path); + } else if (!cfg_exists && data->dynamic_cfg_path) { + /* cfg file was removed */ + parse_dynamic_cfg(NULL, &data->dynamic_pc); + free(data->dynamic_cfg_path); + data->dynamic_cfg_path = NULL; + } + + free(cfg_path); + } +} + /* allocated a krosshair_draw_t instance that must be free'd at the end of its * lifetime * */ @@ -1813,14 +2189,14 @@ static krosshair_draw_t* render_swapchain_display( device_data->vtable.BeginCommandBuffer(draw->cmd_buffer, &buffer_begin_info); ensure_swapchain_crosshair(data, draw->cmd_buffer); + ensure_swapchain_dynamic_mask(data, draw->cmd_buffer); + + /* FB copy needed whenever the dynamic mask is active */ + int needs_fb_copy = data->dynamic_mask.uploaded; VkImageMemoryBarrier imb = {}; imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; imb.pNext = NULL; - imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; imb.image = data->images[image_index]; imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imb.subresourceRange.baseMipLevel = 0; @@ -1829,9 +2205,158 @@ static krosshair_draw_t* render_swapchain_display( imb.subresourceRange.layerCount = 1; imb.srcQueueFamilyIndex = present_queue->family_index; imb.dstQueueFamilyIndex = device_data->graphic_queue->family_index; - device_data->vtable.CmdPipelineBarrier( - draw->cmd_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, NULL, 0, NULL, 1, &imb); + + if (needs_fb_copy) { + /* ── copy game framebuffer for shader-based modes ── + * 1) PRESENT_SRC → TRANSFER_SRC (so we can read) + * 2) blit full swapchain to game_fb_image + * 3) TRANSFER_SRC → COLOR_ATTACHMENT (so render pass works) + */ + + /* ensure game_fb texture exists at swapchain resolution */ + if (!data->game_fb_image || + data->game_fb_width != data->width || + data->game_fb_height != data->height) { + if (data->game_fb_image_view) { + device_data->vtable.DestroyImageView( + device_data->device, data->game_fb_image_view, NULL); + data->game_fb_image_view = VK_NULL_HANDLE; + } + if (data->game_fb_image) { + device_data->vtable.DestroyImage( + device_data->device, data->game_fb_image, NULL); + data->game_fb_image = VK_NULL_HANDLE; + } + if (data->game_fb_mem) { + device_data->vtable.FreeMemory( + device_data->device, data->game_fb_mem, NULL); + data->game_fb_mem = VK_NULL_HANDLE; + } + + VkImageCreateInfo fbi = {}; + fbi.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + fbi.imageType = VK_IMAGE_TYPE_2D; + fbi.format = data->format; + fbi.extent.width = data->width; + fbi.extent.height = data->height; + fbi.extent.depth = 1; + fbi.mipLevels = 1; + fbi.arrayLayers = 1; + fbi.samples = VK_SAMPLE_COUNT_1_BIT; + fbi.tiling = VK_IMAGE_TILING_OPTIMAL; + fbi.usage = VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT; + fbi.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + fbi.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VK_CHECK(device_data->vtable.CreateImage( + device_data->device, &fbi, NULL, &data->game_fb_image)); + + VkMemoryRequirements mreq; + device_data->vtable.GetImageMemoryRequirements( + device_data->device, data->game_fb_image, &mreq); + + VkMemoryAllocateInfo mai = {}; + mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + mai.allocationSize = mreq.size; + mai.memoryTypeIndex = + vk_memory_type(device_data, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + mreq.memoryTypeBits); + VK_CHECK(device_data->vtable.AllocateMemory( + device_data->device, &mai, NULL, &data->game_fb_mem)); + VK_CHECK(device_data->vtable.BindImageMemory( + device_data->device, data->game_fb_image, + data->game_fb_mem, 0)); + + VkImageViewCreateInfo fvi = {}; + fvi.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + fvi.image = data->game_fb_image; + fvi.viewType = VK_IMAGE_VIEW_TYPE_2D; + fvi.format = data->format; + fvi.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + fvi.subresourceRange.levelCount = 1; + fvi.subresourceRange.layerCount = 1; + VK_CHECK(device_data->vtable.CreateImageView( + device_data->device, &fvi, NULL, + &data->game_fb_image_view)); + + data->game_fb_width = data->width; + data->game_fb_height = data->height; + + KROSSHAIR_LOG("[KROSSHAIR] created game FB copy texture %ux%u\n", + data->width, data->height); + } + + /* transition swapchain: PRESENT_SRC → TRANSFER_SRC */ + imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imb.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + imb.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + device_data->vtable.CmdPipelineBarrier( + draw->cmd_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &imb); + + /* transition game_fb: UNDEFINED → TRANSFER_DST */ + VkImageMemoryBarrier fb_bar = {}; + fb_bar.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + fb_bar.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + fb_bar.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + fb_bar.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + fb_bar.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + fb_bar.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + fb_bar.image = data->game_fb_image; + fb_bar.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + fb_bar.subresourceRange.levelCount = 1; + fb_bar.subresourceRange.layerCount = 1; + device_data->vtable.CmdPipelineBarrier( + draw->cmd_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &fb_bar); + + /* copy swapchain → game_fb */ + VkImageCopy region = {}; + region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.srcSubresource.layerCount = 1; + region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.dstSubresource.layerCount = 1; + region.extent.width = data->width; + region.extent.height = data->height; + region.extent.depth = 1; + device_data->vtable.CmdCopyImage( + draw->cmd_buffer, + data->images[image_index], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + data->game_fb_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ®ion); + + /* transition game_fb: TRANSFER_DST → SHADER_READ_ONLY */ + fb_bar.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + fb_bar.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + fb_bar.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + fb_bar.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + device_data->vtable.CmdPipelineBarrier( + draw->cmd_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + 0, 0, NULL, 0, NULL, 1, &fb_bar); + + /* transition swapchain: TRANSFER_SRC → COLOR_ATTACHMENT */ + imb.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imb.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + device_data->vtable.CmdPipelineBarrier( + draw->cmd_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + 0, 0, NULL, 0, NULL, 1, &imb); + } else { + /* no FB copy needed — simple transition */ + imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + device_data->vtable.CmdPipelineBarrier( + draw->cmd_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + 0, 0, NULL, 0, NULL, 1, &imb); + } device_data->vtable.CmdBeginRenderPass( draw->cmd_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); @@ -1972,6 +2497,100 @@ static krosshair_draw_t* render_swapchain_display( sizeof(indices) / sizeof(indices[0]), 1, 0, 0, 0); + /* ── single dynamic effect mask draw (optional) ── + * Uses the shader pipeline that samples the game FB copy. + * Only runs if the dynamic mask is uploaded and the shader pipeline exists. + */ + if (data->dynamic_mask.uploaded && data->shader_pipeline && data->game_fb_image_view) { + /* re-upload dynamic mask vertices */ + { + void* vtx_dst = NULL; + VK_CHECK(device_data->vtable.MapMemory( + device_data->device, draw->vertex_buffer_mem, 0, + draw->vertex_buffer_size, 0, &vtx_dst)); + memcpy(vtx_dst, data->dynamic_mask.vertices, + sizeof(data->dynamic_mask.vertices)); + + VkMappedMemoryRange vtx_range = {}; + vtx_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + vtx_range.memory = draw->vertex_buffer_mem; + vtx_range.size = VK_WHOLE_SIZE; + VK_CHECK(device_data->vtable.FlushMappedMemoryRanges( + device_data->device, 1, &vtx_range)); + device_data->vtable.UnmapMemory(device_data->device, + draw->vertex_buffer_mem); + } + + device_data->vtable.CmdBindPipeline( + draw->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + data->shader_pipeline); + + VkDeviceSize mask_offsets[1] = {0}; + device_data->vtable.CmdBindVertexBuffers( + draw->cmd_buffer, 0, 1, &draw->vertex_buffer, mask_offsets); + + /* allocate/update descriptor set for mask + game_fb if needed */ + if (!data->shader_mask_desc_set) { + VkDescriptorSetAllocateInfo dsai = {}; + dsai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + dsai.descriptorPool = data->shader_desc_pool; + dsai.descriptorSetCount = 1; + dsai.pSetLayouts = &data->shader_desc_layout; + VK_CHECK(device_data->vtable.AllocateDescriptorSets( + device_data->device, &dsai, + &data->shader_mask_desc_set)); + + VkDescriptorImageInfo di_mask = {}; + di_mask.sampler = data->crosshair_sampler; + di_mask.imageView = data->dynamic_mask.image_view; + di_mask.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + VkDescriptorImageInfo di_fb = {}; + di_fb.sampler = data->crosshair_sampler; + di_fb.imageView = data->game_fb_image_view; + di_fb.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + VkWriteDescriptorSet writes[2] = {}; + writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[0].dstSet = data->shader_mask_desc_set; + writes[0].dstBinding = 0; + writes[0].descriptorCount = 1; + writes[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writes[0].pImageInfo = &di_mask; + writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[1].dstSet = data->shader_mask_desc_set; + writes[1].dstBinding = 1; + writes[1].descriptorCount = 1; + writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writes[1].pImageInfo = &di_fb; + device_data->vtable.UpdateDescriptorSets( + device_data->device, 2, writes, 0, NULL); + } + + device_data->vtable.CmdBindDescriptorSets( + draw->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + data->shader_pipeline_layout, 0, 1, + &data->shader_mask_desc_set, 0, NULL); + + /* fill quad NDC bounds into push constants */ + data->dynamic_pc.quad_ndc_min[0] = data->dynamic_mask.vertices[0].pos.x; + data->dynamic_pc.quad_ndc_min[1] = data->dynamic_mask.vertices[0].pos.y; + data->dynamic_pc.quad_ndc_size[0] = data->dynamic_mask.vertices[2].pos.x - + data->dynamic_mask.vertices[0].pos.x; + data->dynamic_pc.quad_ndc_size[1] = data->dynamic_mask.vertices[2].pos.y - + data->dynamic_mask.vertices[0].pos.y; + + device_data->vtable.CmdPushConstants( + draw->cmd_buffer, data->shader_pipeline_layout, + VK_SHADER_STAGE_FRAGMENT_BIT, 0, + sizeof(data->dynamic_pc), &data->dynamic_pc); + + device_data->vtable.CmdDrawIndexed( + draw->cmd_buffer, + sizeof(indices) / sizeof(indices[0]), + 1, 0, 0, 0); + } + device_data->vtable.CmdEndRenderPass(draw->cmd_buffer); /* @@ -2119,11 +2738,11 @@ static void setup_swapchain_data_pipeline(swapchain_data_t* data) VkDescriptorPoolSize sampler_pool_size = {}; sampler_pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - sampler_pool_size.descriptorCount = 1; + sampler_pool_size.descriptorCount = 1 + 1; /* crosshair + dynamic mask */ VkDescriptorPoolCreateInfo desc_pool_info = {}; desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - desc_pool_info.maxSets = 1; + desc_pool_info.maxSets = 1 + 1; desc_pool_info.poolSizeCount = 1; desc_pool_info.pPoolSizes = &sampler_pool_size; VK_CHECK(device_data->vtable.CreateDescriptorPool( @@ -2272,6 +2891,135 @@ static void setup_swapchain_data_pipeline(swapchain_data_t* data) vert_module, NULL); device_data->vtable.DestroyShaderModule(device_data->device, frag_module, NULL); + + /* ═══════════════════════════════════════════════════════════ + * Shader-based dynamic pipeline (Complement, LumaInvert, etc.) + * Uses a custom fragment shader that reads the game framebuffer. + * ═══════════════════════════════════════════════════════════ */ + { + VkShaderModule dyn_vert_mod, dyn_frag_mod; + + VkShaderModuleCreateInfo dvi = {}; + dvi.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + dvi.codeSize = sizeof(dynamic_vert_spv); + dvi.pCode = (const uint32_t*)dynamic_vert_spv; + VK_CHECK(device_data->vtable.CreateShaderModule( + device_data->device, &dvi, NULL, &dyn_vert_mod)); + + VkShaderModuleCreateInfo dfi = {}; + dfi.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + dfi.codeSize = sizeof(dynamic_frag_spv); + dfi.pCode = (const uint32_t*)dynamic_frag_spv; + VK_CHECK(device_data->vtable.CreateShaderModule( + device_data->device, &dfi, NULL, &dyn_frag_mod)); + + /* descriptor set layout: binding 0 = mask, binding 1 = game FB */ + VkDescriptorSetLayoutBinding shader_bindings[2] = {}; + shader_bindings[0].binding = 0; + shader_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + shader_bindings[0].descriptorCount = 1; + shader_bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + shader_bindings[0].pImmutableSamplers = &sampler; + shader_bindings[1].binding = 1; + shader_bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + shader_bindings[1].descriptorCount = 1; + shader_bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + shader_bindings[1].pImmutableSamplers = &sampler; + + VkDescriptorSetLayoutCreateInfo sdl_info = {}; + sdl_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + sdl_info.bindingCount = 2; + sdl_info.pBindings = shader_bindings; + VK_CHECK(device_data->vtable.CreateDescriptorSetLayout( + device_data->device, &sdl_info, NULL, + &data->shader_desc_layout)); + + /* push constant range: full dynamic_push_constants (76 bytes) */ + VkPushConstantRange pc_range = {}; + pc_range.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + pc_range.offset = 0; + pc_range.size = sizeof(struct dynamic_push_constants); + + VkPipelineLayoutCreateInfo spl_info = {}; + spl_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + spl_info.setLayoutCount = 1; + spl_info.pSetLayouts = &data->shader_desc_layout; + spl_info.pushConstantRangeCount = 1; + spl_info.pPushConstantRanges = &pc_range; + VK_CHECK(device_data->vtable.CreatePipelineLayout( + device_data->device, &spl_info, NULL, + &data->shader_pipeline_layout)); + + /* descriptor pool for shader dynamic desc set */ + VkDescriptorPoolSize sp_size = {}; + sp_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + sp_size.descriptorCount = 1 * 2; /* 2 bindings: mask + game_fb */ + + VkDescriptorPoolCreateInfo sp_info = {}; + sp_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + sp_info.maxSets = 1; + sp_info.poolSizeCount = 1; + sp_info.pPoolSizes = &sp_size; + VK_CHECK(device_data->vtable.CreateDescriptorPool( + device_data->device, &sp_info, NULL, + &data->shader_desc_pool)); + + /* shader stages */ + VkPipelineShaderStageCreateInfo sstage[2] = {}; + sstage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + sstage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + sstage[0].module = dyn_vert_mod; + sstage[0].pName = "main"; + sstage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + sstage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + sstage[1].module = dyn_frag_mod; + sstage[1].pName = "main"; + + /* the shader outputs final composited color — standard alpha blend */ + VkPipelineColorBlendAttachmentState shader_ca = {}; + shader_ca.blendEnable = VK_TRUE; + shader_ca.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + shader_ca.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + shader_ca.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + shader_ca.colorBlendOp = VK_BLEND_OP_ADD; + shader_ca.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + shader_ca.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + shader_ca.alphaBlendOp = VK_BLEND_OP_ADD; + + VkPipelineColorBlendStateCreateInfo shader_blend = {}; + shader_blend.sType = + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + shader_blend.attachmentCount = 1; + shader_blend.pAttachments = &shader_ca; + + /* reuse vertex_info, input_asm_info, viewport_info, raster_info, + * ms_info, depth_info, dynamic_state from earlier */ + VkGraphicsPipelineCreateInfo spi = {}; + spi.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + spi.stageCount = 2; + spi.pStages = sstage; + spi.pVertexInputState = &vertex_info; + spi.pInputAssemblyState = &input_asm_info; + spi.pViewportState = &viewport_info; + spi.pRasterizationState = &raster_info; + spi.pMultisampleState = &ms_info; + spi.pDepthStencilState = &depth_info; + spi.pColorBlendState = &shader_blend; + spi.pDynamicState = &dynamic_state; + spi.layout = data->shader_pipeline_layout; + spi.renderPass = data->render_pass; + VK_CHECK(device_data->vtable.CreateGraphicsPipelines( + device_data->device, VK_NULL_HANDLE, 1, &spi, NULL, + &data->shader_pipeline)); + + device_data->vtable.DestroyShaderModule(device_data->device, + dyn_vert_mod, NULL); + device_data->vtable.DestroyShaderModule(device_data->device, + dyn_frag_mod, NULL); + } } static void setup_swapchain_data(swapchain_data_t* data, @@ -2425,7 +3173,8 @@ static VkResult overlay_CreateSwapchainKHR( const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) { VkSwapchainCreateInfoKHR create_info = *pCreateInfo; - create_info.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + create_info.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT; device_data_t* device_data = FIND_OBJ(device_data_t, device); From 9e7592a07d6887ba7bfad541adc567e92be9b935 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Sat, 25 Apr 2026 06:18:38 -0700 Subject: [PATCH 20/25] fix: separate vertex buffer for dynamic mask, fixes APNG animation crash --- src/layer.c | 57 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/src/layer.c b/src/layer.c index 0b0fdaa..7b28a36 100644 --- a/src/layer.c +++ b/src/layer.c @@ -348,6 +348,10 @@ typedef struct krosshair_draw { VkDeviceMemory vertex_buffer_mem; VkDeviceSize vertex_buffer_size; + VkBuffer vertex_buffer2; /* separate vertex buffer for dynamic mask */ + VkDeviceMemory vertex_buffer2_mem; + VkDeviceSize vertex_buffer2_size; + VkBuffer index_buffer; VkDeviceMemory index_buffer_mem; VkDeviceSize index_buffer_size; @@ -2137,6 +2141,14 @@ static void destroy_draw(swapchain_data_t* data, krosshair_draw_t* draw) device_data->vtable.FreeMemory(device_data->device, draw->vertex_buffer_mem, NULL); } + if (draw->vertex_buffer2 != VK_NULL_HANDLE) { + device_data->vtable.DestroyBuffer(device_data->device, + draw->vertex_buffer2, NULL); + } + if (draw->vertex_buffer2_mem != VK_NULL_HANDLE) { + device_data->vtable.FreeMemory(device_data->device, + draw->vertex_buffer2_mem, NULL); + } if (draw->index_buffer != VK_NULL_HANDLE) { device_data->vtable.DestroyBuffer(device_data->device, draw->index_buffer, NULL); @@ -2501,33 +2513,40 @@ static krosshair_draw_t* render_swapchain_display( * Uses the shader pipeline that samples the game FB copy. * Only runs if the dynamic mask is uploaded and the shader pipeline exists. */ - if (data->dynamic_mask.uploaded && data->shader_pipeline && data->game_fb_image_view) { - /* re-upload dynamic mask vertices */ - { - void* vtx_dst = NULL; - VK_CHECK(device_data->vtable.MapMemory( - device_data->device, draw->vertex_buffer_mem, 0, - draw->vertex_buffer_size, 0, &vtx_dst)); - memcpy(vtx_dst, data->dynamic_mask.vertices, - sizeof(data->dynamic_mask.vertices)); - - VkMappedMemoryRange vtx_range = {}; - vtx_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - vtx_range.memory = draw->vertex_buffer_mem; - vtx_range.size = VK_WHOLE_SIZE; - VK_CHECK(device_data->vtable.FlushMappedMemoryRanges( - device_data->device, 1, &vtx_range)); - device_data->vtable.UnmapMemory(device_data->device, - draw->vertex_buffer_mem); +if (data->dynamic_mask.uploaded && data->shader_pipeline && data->game_fb_image_view) { + /* ensure vertex_buffer2 exists for dynamic mask */ + size_t vtx2_size = sizeof(data->dynamic_mask.vertices); + if (draw->vertex_buffer2_size < vtx2_size) { + create_or_resize_buffer(device_data, &draw->vertex_buffer2, + &draw->vertex_buffer2_mem, + &draw->vertex_buffer2_size, vtx2_size, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); } + /* upload dynamic mask vertices to separate buffer */ + void* vtx_dst = NULL; + VK_CHECK(device_data->vtable.MapMemory( + device_data->device, draw->vertex_buffer2_mem, 0, + draw->vertex_buffer2_size, 0, &vtx_dst)); + memcpy(vtx_dst, data->dynamic_mask.vertices, + sizeof(data->dynamic_mask.vertices)); + + VkMappedMemoryRange vtx_range = {}; + vtx_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + vtx_range.memory = draw->vertex_buffer2_mem; + vtx_range.size = VK_WHOLE_SIZE; + VK_CHECK(device_data->vtable.FlushMappedMemoryRanges( + device_data->device, 1, &vtx_range)); + device_data->vtable.UnmapMemory(device_data->device, + draw->vertex_buffer2_mem); + device_data->vtable.CmdBindPipeline( draw->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->shader_pipeline); VkDeviceSize mask_offsets[1] = {0}; device_data->vtable.CmdBindVertexBuffers( - draw->cmd_buffer, 0, 1, &draw->vertex_buffer, mask_offsets); + draw->cmd_buffer, 0, 1, &draw->vertex_buffer2, mask_offsets); /* allocate/update descriptor set for mask + game_fb if needed */ if (!data->shader_mask_desc_set) { From d2bb3efef6d24a89a474e9f8067aeb7f3077cbd1 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sat, 25 Apr 2026 13:22:53 +0000 Subject: [PATCH 21/25] chore: bump version to v0.2.3 --- PKGBUILD | 2 +- aur/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 62eca62..9f0426b 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.2 +pkgver=0.2.3 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') diff --git a/aur/PKGBUILD b/aur/PKGBUILD index 43ed528..e33d38a 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.2 +pkgver=0.2.3 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') From dd765b2f3a3521559bf984076ad1a2f2395fe024 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Sun, 26 Apr 2026 01:43:52 -0700 Subject: [PATCH 22/25] fix: match dynamic effects to crosshair-maker (hue_rotate, saturate formulas) - Fix hue_rotate: S=original, L=1.0-original_L (was setting S=1, L=1 making white) - Fix saturate: L=1.0-original_L (was setting L=1 making white) - Regenerated SPIR-V headers from fixed GLSL --- shaders/dynamic.frag | 19 ++++++++++++++----- shaders/dynamic_spv.h | 7 ++++--- src/layer.c | 8 ++++++-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/shaders/dynamic.frag b/shaders/dynamic.frag index 7dddd9e..e3e9a88 100644 --- a/shaders/dynamic.frag +++ b/shaders/dynamic.frag @@ -25,6 +25,7 @@ layout(push_constant) uniform PushConstants { float huerotate_angle; // Hue Rotate angle (degrees) float saturate_str; // Saturate strength float saturate_amount; // Saturate amount (0-1) + float opacity; // Overall effect opacity (0-1) } pc; // ── RGB <-> HSL conversions ────────────────────────────────────── @@ -75,14 +76,15 @@ vec3 hsl_to_rgb(vec3 hsl) { } void main() { - // Binary mask: check red channel (grayscale) + // Continuous mask: use red channel (grayscale) as blend factor float mask = texture(mask_sampler, frag_tex_coord).r; - if (mask < 0.5) discard; + if (mask < 0.004) discard; // ~1/255, skip fully transparent pixels // Sample game framebuffer vec2 ndc = pc.quad_ndc_min + frag_tex_coord * pc.quad_ndc_size; vec2 screen_uv = ndc * 0.5 + 0.5; - vec3 color = texture(game_fb_sampler, screen_uv).rgb; + vec3 original = texture(game_fb_sampler, screen_uv).rgb; + vec3 color = original; // Fixed order: invert → dodge → burn → complement → luma_invert → hue_rotate → saturate @@ -116,17 +118,24 @@ void main() { if (pc.huerotate_str > 0.0) { vec3 hsl = rgb_to_hsl(color); + float original_l = hsl.z; hsl.x = mod(hsl.x + pc.huerotate_angle / 360.0, 1.0); - hsl.z = 1.0 - hsl.z; + // hsl.y keeps original saturation, L = 1.0 - original_L matches crosshair-maker + hsl.z = 1.0 - original_l; color = mix(color, hsl_to_rgb(hsl), pc.huerotate_str); } if (pc.saturate_str > 0.0) { vec3 hsl = rgb_to_hsl(color); + // Match crosshair-maker: hsl_to_rgb_f32(h, amount, 1.0 - original_l) + float original_l = hsl.z; hsl.y = pc.saturate_amount; - hsl.z = 1.0 - hsl.z; + hsl.z = 1.0 - original_l; // Match crosshair-maker formula color = mix(color, hsl_to_rgb(hsl), pc.saturate_str); } + // Apply overall opacity, then blend by mask alpha (supports anti-aliased edges) + color = mix(original, color, mask * pc.opacity); + out_color = vec4(color, 1.0); } diff --git a/shaders/dynamic_spv.h b/shaders/dynamic_spv.h index 16a2599..039786a 100644 --- a/shaders/dynamic_spv.h +++ b/shaders/dynamic_spv.h @@ -1,8 +1,9 @@ // Auto-generated SPIR-V headers for dynamic shader // DO NOT EDIT — regenerate from .frag/.vert sources -static const unsigned char dynamic_vert_spv[] = {0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x06, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43, 0x6c, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x06, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43, 0x75, 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x05, 0x00, 0x06, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x66, 0x72, 0x61, 0x67, 0x5f, 0x74, 0x65, 0x78, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x74, 0x65, 0x78, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x20, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; +static const unsigned char dynamic_vert_spv[] = {0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x0b,0x00,0x08,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30,0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x05,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00,0x0b,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x65,0x72,0x56,0x65,0x72,0x74,0x65,0x78,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x06,0x00,0x07,0x00,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74,0x53,0x69,0x7a,0x65,0x00,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x0b,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x67,0x6c,0x5f,0x43,0x6c,0x69,0x70,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,0x00,0x06,0x00,0x07,0x00,0x0b,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x67,0x6c,0x5f,0x43,0x75,0x6c,0x6c,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,0x00,0x05,0x00,0x03,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x12,0x00,0x00,0x00,0x69,0x6e,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x05,0x00,0x06,0x00,0x1c,0x00,0x00,0x00,0x66,0x72,0x61,0x67,0x5f,0x74,0x65,0x78,0x5f,0x63,0x6f,0x6f,0x72,0x64,0x00,0x00,0x05,0x00,0x06,0x00,0x1d,0x00,0x00,0x00,0x69,0x6e,0x5f,0x74,0x65,0x78,0x5f,0x63,0x6f,0x6f,0x72,0x64,0x00,0x00,0x00,0x00,0x47,0x00,0x03,0x00,0x0b,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0b,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0b,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x13,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x21,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x06,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x1e,0x00,0x06,0x00,0x0b,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0c,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x20,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x36,0x00,0x05,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x19,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x1a,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00}; static const unsigned int dynamic_vert_spv_size = 988; -static const unsigned char dynamic_frag_spv[] = {0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00, 0xe6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x72, 0x67, 0x62, 0x5f, 0x74, 0x6f, 0x5f, 0x68, 0x73, 0x6c, 0x28, 0x76, 0x66, 0x33, 0x3b, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x12, 0x00, 0x00, 0x00, 0x68, 0x75, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x67, 0x62, 0x28, 0x66, 0x31, 0x3b, 0x66, 0x31, 0x3b, 0x66, 0x31, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00, 0x00, 0x68, 0x73, 0x6c, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x67, 0x62, 0x28, 0x76, 0x66, 0x33, 0x3b, 0x00, 0x05, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, 0x68, 0x73, 0x6c, 0x00, 0x05, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x6d, 0x78, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x24, 0x00, 0x00, 0x00, 0x6d, 0x6e, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xea, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xec, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xee, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x02, 0x01, 0x00, 0x00, 0x6d, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x01, 0x00, 0x00, 0x6d, 0x61, 0x73, 0x6b, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x66, 0x72, 0x61, 0x67, 0x5f, 0x74, 0x65, 0x78, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x15, 0x01, 0x00, 0x00, 0x6e, 0x64, 0x63, 0x00, 0x05, 0x00, 0x06, 0x00, 0x16, 0x01, 0x00, 0x00, 0x50, 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x75, 0x61, 0x64, 0x5f, 0x6e, 0x64, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x71, 0x75, 0x61, 0x64, 0x5f, 0x6e, 0x64, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x16, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x16, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x64, 0x67, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x64, 0x67, 0x65, 0x5f, 0x72, 0x00, 0x06, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x64, 0x67, 0x65, 0x5f, 0x67, 0x00, 0x06, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64, 0x6f, 0x64, 0x67, 0x65, 0x5f, 0x62, 0x00, 0x06, 0x00, 0x06, 0x00, 0x16, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x72, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x67, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x62, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x68, 0x75, 0x65, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x68, 0x75, 0x65, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x67, 0x6c, 0x65, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x05, 0x00, 0x03, 0x00, 0x18, 0x01, 0x00, 0x00, 0x70, 0x63, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x24, 0x01, 0x00, 0x00, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x75, 0x76, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x29, 0x01, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x2a, 0x01, 0x00, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x62, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00, 0x05, 0x00, 0x04, 0x00, 0x44, 0x01, 0x00, 0x00, 0x64, 0x6f, 0x64, 0x67, 0x65, 0x64, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x5e, 0x01, 0x00, 0x00, 0x62, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x79, 0x01, 0x00, 0x00, 0x68, 0x73, 0x6c, 0x00, 0x05, 0x00, 0x04, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x95, 0x01, 0x00, 0x00, 0x68, 0x73, 0x6c, 0x00, 0x05, 0x00, 0x04, 0x00, 0x96, 0x01, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x9e, 0x01, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xab, 0x01, 0x00, 0x00, 0x68, 0x73, 0x6c, 0x00, 0x05, 0x00, 0x04, 0x00, 0xac, 0x01, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xbe, 0x01, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xcb, 0x01, 0x00, 0x00, 0x68, 0x73, 0x6c, 0x00, 0x05, 0x00, 0x04, 0x00, 0xcc, 0x01, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xd8, 0x01, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x06, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x06, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x16, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2a, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2a, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x21, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xac, 0xc5, 0x27, 0x37, 0x14, 0x00, 0x02, 0x00, 0x39, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0xab, 0xaa, 0x2a, 0x3e, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0xab, 0xaa, 0x2a, 0x3f, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0xab, 0xaa, 0xaa, 0x3e, 0x19, 0x00, 0x09, 0x00, 0x03, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x04, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x05, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x08, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x09, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x14, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x13, 0x00, 0x16, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x17, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x17, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x1f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x05, 0x01, 0x00, 0x00, 0x2a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x30, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x63, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6b, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x73, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0xa5, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0xb1, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x43, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0xcf, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xdf, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xdf, 0x01, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x14, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x14, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x96, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x9e, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0xab, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0xac, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0xbe, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0xcb, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x04, 0x01, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x08, 0x01, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x10, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x11, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x12, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x08, 0x01, 0x00, 0x00, 0x1d, 0x01, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x08, 0x01, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x1f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x08, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, 0x1d, 0x01, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x15, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x08, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x24, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x04, 0x01, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00, 0x2a, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x08, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2e, 0x01, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x29, 0x01, 0x00, 0x00, 0x2e, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x35, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x33, 0x01, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x34, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x3a, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x3a, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3d, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3d, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x35, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x35, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x41, 0x01, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x42, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4b, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x4d, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x00, 0x4d, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x4b, 0x01, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x44, 0x01, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x53, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x53, 0x01, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x29, 0x01, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x43, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x43, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x59, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x00, 0x59, 0x01, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x5b, 0x01, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x5d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x5b, 0x01, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x5d, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, 0x01, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x63, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x69, 0x01, 0x00, 0x00, 0x62, 0x01, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x69, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x00, 0x00, 0x6b, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5e, 0x01, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6d, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6e, 0x01, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x6f, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x6f, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x71, 0x01, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x72, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x6d, 0x01, 0x00, 0x00, 0x6e, 0x01, 0x00, 0x00, 0x71, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x29, 0x01, 0x00, 0x00, 0x72, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x5d, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x5d, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x73, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x75, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x78, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x76, 0x01, 0x00, 0x00, 0x77, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x77, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x7b, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x7b, 0x01, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x79, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x7d, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7e, 0x01, 0x00, 0x00, 0x7d, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x7e, 0x01, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x81, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x82, 0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x83, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x83, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x85, 0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x86, 0x01, 0x00, 0x00, 0x85, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x87, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x88, 0x01, 0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x8b, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x73, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x8b, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x87, 0x01, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x29, 0x01, 0x00, 0x00, 0x8e, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x78, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x78, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x91, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x92, 0x01, 0x00, 0x00, 0x91, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x92, 0x01, 0x00, 0x00, 0x93, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x93, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x96, 0x01, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x96, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x95, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x99, 0x01, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00, 0x99, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9b, 0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x9b, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9d, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9f, 0x01, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x9e, 0x01, 0x00, 0x00, 0x9f, 0x01, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x9e, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0xa1, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa2, 0x01, 0x00, 0x00, 0xa1, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0xa3, 0x01, 0x00, 0x00, 0xa2, 0x01, 0x00, 0x00, 0xa2, 0x01, 0x00, 0x00, 0xa2, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x9d, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0xa3, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x29, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x94, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x94, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0xa6, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xa5, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa7, 0x01, 0x00, 0x00, 0xa6, 0x01, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0xa7, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xaa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xa8, 0x01, 0x00, 0x00, 0xa9, 0x01, 0x00, 0x00, 0xaa, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xa9, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xad, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xac, 0x01, 0x00, 0x00, 0xad, 0x01, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xae, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xac, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xab, 0x01, 0x00, 0x00, 0xae, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xaf, 0x01, 0x00, 0x00, 0xab, 0x01, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xaf, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0xb2, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xb1, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb3, 0x01, 0x00, 0x00, 0xb2, 0x01, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb5, 0x01, 0x00, 0x00, 0xb3, 0x01, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb6, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb5, 0x01, 0x00, 0x00, 0x8d, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00, 0xb6, 0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0xab, 0x01, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xb8, 0x01, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xb9, 0x01, 0x00, 0x00, 0xab, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xba, 0x01, 0x00, 0x00, 0xb9, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xbb, 0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0xba, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xbc, 0x01, 0x00, 0x00, 0xab, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xbc, 0x01, 0x00, 0x00, 0xbb, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xbd, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0xab, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xbe, 0x01, 0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0xbe, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xa5, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc3, 0x01, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc4, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0xbd, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc3, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x29, 0x01, 0x00, 0x00, 0xc4, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xaa, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xaa, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0xc6, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x00, 0x00, 0xc6, 0x01, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, 0xc7, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xca, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xc8, 0x01, 0x00, 0x00, 0xc9, 0x01, 0x00, 0x00, 0xca, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xc9, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xcc, 0x01, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xce, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xcb, 0x01, 0x00, 0x00, 0xce, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xcf, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd1, 0x01, 0x00, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xd2, 0x01, 0x00, 0x00, 0xcb, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xd2, 0x01, 0x00, 0x00, 0xd1, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xd3, 0x01, 0x00, 0x00, 0xcb, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd4, 0x01, 0x00, 0x00, 0xd3, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd5, 0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0xd4, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xd6, 0x01, 0x00, 0x00, 0xcb, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xd6, 0x01, 0x00, 0x00, 0xd5, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xd7, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xd9, 0x01, 0x00, 0x00, 0xcb, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xd8, 0x01, 0x00, 0x00, 0xd9, 0x01, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0xda, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0xdb, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0xdb, 0x01, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0xdd, 0x01, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0xde, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0xd7, 0x01, 0x00, 0x00, 0xda, 0x01, 0x00, 0x00, 0xdd, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x29, 0x01, 0x00, 0x00, 0xde, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xca, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xca, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xe1, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe2, 0x01, 0x00, 0x00, 0xe1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe3, 0x01, 0x00, 0x00, 0xe1, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe4, 0x01, 0x00, 0x00, 0xe1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x0c, 0x01, 0x00, 0x00, 0xe5, 0x01, 0x00, 0x00, 0xe2, 0x01, 0x00, 0x00, 0xe3, 0x01, 0x00, 0x00, 0xe4, 0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xe0, 0x01, 0x00, 0x00, 0xe5, 0x01, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x24, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x43, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x45, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x44, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x46, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x44, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x46, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x46, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x59, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x6b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x74, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x6b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x81, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x82, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x83, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x83, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x90, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x90, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x94, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x95, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x96, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x96, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0xab, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0xba, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x16, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xc5, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xc9, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xca, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xd1, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xd2, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xd2, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xcf, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xea, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xec, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xee, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x39, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xf2, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, 0x39, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xfb, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xfd, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x39, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0xff, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00}; -static const unsigned int dynamic_frag_spv_size = 11544; +static const unsigned char dynamic_frag_spv[] = {0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x0b,0x00,0x08,0x00,0xf6,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30,0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x07,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x0a,0x01,0x00,0x00,0xf0,0x01,0x00,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x05,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00,0x0b,0x00,0x00,0x00,0x72,0x67,0x62,0x5f,0x74,0x6f,0x5f,0x68,0x73,0x6c,0x28,0x76,0x66,0x33,0x3b,0x00,0x05,0x00,0x03,0x00,0x0a,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x05,0x00,0x08,0x00,0x12,0x00,0x00,0x00,0x68,0x75,0x65,0x5f,0x74,0x6f,0x5f,0x72,0x67,0x62,0x28,0x66,0x31,0x3b,0x66,0x31,0x3b,0x66,0x31,0x3b,0x00,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x0f,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x10,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x11,0x00,0x00,0x00,0x74,0x00,0x00,0x00,0x05,0x00,0x06,0x00,0x15,0x00,0x00,0x00,0x68,0x73,0x6c,0x5f,0x74,0x6f,0x5f,0x72,0x67,0x62,0x28,0x76,0x66,0x33,0x3b,0x00,0x05,0x00,0x03,0x00,0x14,0x00,0x00,0x00,0x68,0x73,0x6c,0x00,0x05,0x00,0x03,0x00,0x17,0x00,0x00,0x00,0x6d,0x78,0x00,0x00,0x05,0x00,0x03,0x00,0x24,0x00,0x00,0x00,0x6d,0x6e,0x00,0x00,0x05,0x00,0x03,0x00,0x2d,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x33,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x41,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x5b,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0xbf,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0xc2,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0xc5,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0xcf,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0xe2,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xea,0x00,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xec,0x00,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xee,0x00,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xf0,0x00,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xf2,0x00,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xf4,0x00,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xf9,0x00,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xfb,0x00,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xfd,0x00,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x02,0x01,0x00,0x00,0x6d,0x61,0x73,0x6b,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00,0x06,0x01,0x00,0x00,0x6d,0x61,0x73,0x6b,0x5f,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00,0x0a,0x01,0x00,0x00,0x66,0x72,0x61,0x67,0x5f,0x74,0x65,0x78,0x5f,0x63,0x6f,0x6f,0x72,0x64,0x00,0x00,0x05,0x00,0x03,0x00,0x16,0x01,0x00,0x00,0x6e,0x64,0x63,0x00,0x05,0x00,0x06,0x00,0x17,0x01,0x00,0x00,0x50,0x75,0x73,0x68,0x43,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x73,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x17,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x71,0x75,0x61,0x64,0x5f,0x6e,0x64,0x63,0x5f,0x6d,0x69,0x6e,0x00,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x17,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x71,0x75,0x61,0x64,0x5f,0x6e,0x64,0x63,0x5f,0x73,0x69,0x7a,0x65,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x17,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x69,0x6e,0x76,0x65,0x72,0x74,0x5f,0x73,0x74,0x72,0x00,0x00,0x06,0x00,0x06,0x00,0x17,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x64,0x6f,0x64,0x67,0x65,0x5f,0x73,0x74,0x72,0x00,0x00,0x00,0x06,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0x64,0x6f,0x64,0x67,0x65,0x5f,0x72,0x00,0x06,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x05,0x00,0x00,0x00,0x64,0x6f,0x64,0x67,0x65,0x5f,0x67,0x00,0x06,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x06,0x00,0x00,0x00,0x64,0x6f,0x64,0x67,0x65,0x5f,0x62,0x00,0x06,0x00,0x06,0x00,0x17,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x62,0x75,0x72,0x6e,0x5f,0x73,0x74,0x72,0x00,0x00,0x00,0x00,0x06,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x62,0x75,0x72,0x6e,0x5f,0x72,0x00,0x00,0x06,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x09,0x00,0x00,0x00,0x62,0x75,0x72,0x6e,0x5f,0x67,0x00,0x00,0x06,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x0a,0x00,0x00,0x00,0x62,0x75,0x72,0x6e,0x5f,0x62,0x00,0x00,0x06,0x00,0x07,0x00,0x17,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x5f,0x73,0x74,0x72,0x00,0x00,0x06,0x00,0x07,0x00,0x17,0x01,0x00,0x00,0x0c,0x00,0x00,0x00,0x6c,0x75,0x6d,0x61,0x69,0x6e,0x76,0x65,0x72,0x74,0x5f,0x73,0x74,0x72,0x00,0x00,0x06,0x00,0x07,0x00,0x17,0x01,0x00,0x00,0x0d,0x00,0x00,0x00,0x68,0x75,0x65,0x72,0x6f,0x74,0x61,0x74,0x65,0x5f,0x73,0x74,0x72,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x17,0x01,0x00,0x00,0x0e,0x00,0x00,0x00,0x68,0x75,0x65,0x72,0x6f,0x74,0x61,0x74,0x65,0x5f,0x61,0x6e,0x67,0x6c,0x65,0x00,0x06,0x00,0x07,0x00,0x17,0x01,0x00,0x00,0x0f,0x00,0x00,0x00,0x73,0x61,0x74,0x75,0x72,0x61,0x74,0x65,0x5f,0x73,0x74,0x72,0x00,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x17,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x73,0x61,0x74,0x75,0x72,0x61,0x74,0x65,0x5f,0x61,0x6d,0x6f,0x75,0x6e,0x74,0x00,0x06,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x6f,0x70,0x61,0x63,0x69,0x74,0x79,0x00,0x05,0x00,0x03,0x00,0x19,0x01,0x00,0x00,0x70,0x63,0x00,0x00,0x05,0x00,0x05,0x00,0x25,0x01,0x00,0x00,0x73,0x63,0x72,0x65,0x65,0x6e,0x5f,0x75,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x2a,0x01,0x00,0x00,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00,0x2b,0x01,0x00,0x00,0x67,0x61,0x6d,0x65,0x5f,0x66,0x62,0x5f,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x00,0x05,0x00,0x04,0x00,0x30,0x01,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x47,0x01,0x00,0x00,0x64,0x6f,0x64,0x67,0x65,0x64,0x00,0x00,0x05,0x00,0x04,0x00,0x61,0x01,0x00,0x00,0x62,0x75,0x72,0x6e,0x65,0x64,0x00,0x00,0x05,0x00,0x03,0x00,0x7c,0x01,0x00,0x00,0x68,0x73,0x6c,0x00,0x05,0x00,0x04,0x00,0x7d,0x01,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x8b,0x01,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x98,0x01,0x00,0x00,0x68,0x73,0x6c,0x00,0x05,0x00,0x04,0x00,0x99,0x01,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0xa1,0x01,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0xae,0x01,0x00,0x00,0x68,0x73,0x6c,0x00,0x05,0x00,0x04,0x00,0xaf,0x01,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0xb2,0x01,0x00,0x00,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x5f,0x6c,0x00,0x00,0x05,0x00,0x04,0x00,0xc3,0x01,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0xd0,0x01,0x00,0x00,0x68,0x73,0x6c,0x00,0x05,0x00,0x04,0x00,0xd1,0x01,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0xd4,0x01,0x00,0x00,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x5f,0x6c,0x00,0x00,0x05,0x00,0x04,0x00,0xdf,0x01,0x00,0x00,0x70,0x61,0x72,0x61,0x6d,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0xf0,0x01,0x00,0x00,0x6f,0x75,0x74,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x06,0x01,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x06,0x01,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x0a,0x01,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x03,0x00,0x17,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x05,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x06,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x09,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x0a,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x0c,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x0d,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x0e,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x0f,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x17,0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x2b,0x01,0x00,0x00,0x21,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x2b,0x01,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0xf0,0x01,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x21,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x06,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x21,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x21,0x00,0x06,0x00,0x0e,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x18,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x18,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x18,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x18,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xac,0xc5,0x27,0x37,0x14,0x00,0x02,0x00,0x39,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0xc0,0x40,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x9a,0x00,0x00,0x00,0xab,0xaa,0x2a,0x3e,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xae,0x00,0x00,0x00,0xab,0xaa,0x2a,0x3f,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0xab,0xaa,0xaa,0x3e,0x19,0x00,0x09,0x00,0x03,0x01,0x00,0x00,0x06,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x03,0x00,0x04,0x01,0x00,0x00,0x03,0x01,0x00,0x00,0x20,0x00,0x04,0x00,0x05,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x01,0x00,0x00,0x3b,0x00,0x04,0x00,0x05,0x01,0x00,0x00,0x06,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x08,0x01,0x00,0x00,0x06,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x09,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x01,0x00,0x00,0x3b,0x00,0x04,0x00,0x09,0x01,0x00,0x00,0x0a,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x0c,0x01,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x6f,0x12,0x83,0x3b,0x20,0x00,0x04,0x00,0x15,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x08,0x01,0x00,0x00,0x1e,0x00,0x14,0x00,0x17,0x01,0x00,0x00,0x08,0x01,0x00,0x00,0x08,0x01,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x18,0x01,0x00,0x00,0x09,0x00,0x00,0x00,0x17,0x01,0x00,0x00,0x3b,0x00,0x04,0x00,0x18,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x09,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x1b,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x1c,0x01,0x00,0x00,0x09,0x00,0x00,0x00,0x08,0x01,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x20,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x05,0x01,0x00,0x00,0x2b,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x32,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x33,0x01,0x00,0x00,0x09,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x2c,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x3a,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x41,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x49,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x4c,0x01,0x00,0x00,0x05,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x4f,0x01,0x00,0x00,0x06,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x5b,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x63,0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x66,0x01,0x00,0x00,0x09,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x69,0x01,0x00,0x00,0x0a,0x00,0x00,0x00,0x2c,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x6e,0x01,0x00,0x00,0x3d,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x76,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0x92,0x01,0x00,0x00,0x0c,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0xa8,0x01,0x00,0x00,0x0d,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0xb7,0x01,0x00,0x00,0x0e,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xba,0x01,0x00,0x00,0x00,0x00,0xb4,0x43,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0xca,0x01,0x00,0x00,0x0f,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0xd7,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x1a,0x01,0x00,0x00,0xe9,0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0xef,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x0c,0x01,0x00,0x00,0x3b,0x00,0x04,0x00,0xef,0x01,0x00,0x00,0xf0,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x36,0x00,0x05,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x02,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x15,0x01,0x00,0x00,0x16,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x15,0x01,0x00,0x00,0x25,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x2a,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x30,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x47,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x61,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x7c,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x7d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x8b,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x98,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x99,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0xa1,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0xae,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0xaf,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xb2,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0xc3,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0xd0,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0xd1,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xd4,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0xdf,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x04,0x01,0x00,0x00,0x07,0x01,0x00,0x00,0x06,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x01,0x00,0x00,0x0b,0x01,0x00,0x00,0x0a,0x01,0x00,0x00,0x57,0x00,0x05,0x00,0x0c,0x01,0x00,0x00,0x0d,0x01,0x00,0x00,0x07,0x01,0x00,0x00,0x0b,0x01,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x0e,0x01,0x00,0x00,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x02,0x01,0x00,0x00,0x0e,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x0f,0x01,0x00,0x00,0x02,0x01,0x00,0x00,0xb8,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x0f,0x01,0x00,0x00,0x10,0x01,0x00,0x00,0xf7,0x00,0x03,0x00,0x13,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x11,0x01,0x00,0x00,0x12,0x01,0x00,0x00,0x13,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x12,0x01,0x00,0x00,0xfc,0x00,0x01,0x00,0xf8,0x00,0x02,0x00,0x13,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x1c,0x01,0x00,0x00,0x1d,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x1b,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x01,0x00,0x00,0x1e,0x01,0x00,0x00,0x1d,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x01,0x00,0x00,0x1f,0x01,0x00,0x00,0x0a,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x1c,0x01,0x00,0x00,0x21,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x20,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x01,0x00,0x00,0x22,0x01,0x00,0x00,0x21,0x01,0x00,0x00,0x85,0x00,0x05,0x00,0x08,0x01,0x00,0x00,0x23,0x01,0x00,0x00,0x1f,0x01,0x00,0x00,0x22,0x01,0x00,0x00,0x81,0x00,0x05,0x00,0x08,0x01,0x00,0x00,0x24,0x01,0x00,0x00,0x1e,0x01,0x00,0x00,0x23,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x16,0x01,0x00,0x00,0x24,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x01,0x00,0x00,0x26,0x01,0x00,0x00,0x16,0x01,0x00,0x00,0x8e,0x00,0x05,0x00,0x08,0x01,0x00,0x00,0x27,0x01,0x00,0x00,0x26,0x01,0x00,0x00,0x31,0x00,0x00,0x00,0x50,0x00,0x05,0x00,0x08,0x01,0x00,0x00,0x28,0x01,0x00,0x00,0x31,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x08,0x01,0x00,0x00,0x29,0x01,0x00,0x00,0x27,0x01,0x00,0x00,0x28,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x25,0x01,0x00,0x00,0x29,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x04,0x01,0x00,0x00,0x2c,0x01,0x00,0x00,0x2b,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x01,0x00,0x00,0x2d,0x01,0x00,0x00,0x25,0x01,0x00,0x00,0x57,0x00,0x05,0x00,0x0c,0x01,0x00,0x00,0x2e,0x01,0x00,0x00,0x2c,0x01,0x00,0x00,0x2d,0x01,0x00,0x00,0x4f,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x2e,0x01,0x00,0x00,0x2e,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x2a,0x01,0x00,0x00,0x2f,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x31,0x01,0x00,0x00,0x2a,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x30,0x01,0x00,0x00,0x31,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x34,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x32,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x35,0x01,0x00,0x00,0x34,0x01,0x00,0x00,0xba,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x36,0x01,0x00,0x00,0x35,0x01,0x00,0x00,0x3d,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x38,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x36,0x01,0x00,0x00,0x37,0x01,0x00,0x00,0x38,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x37,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x39,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x3b,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x83,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x3c,0x01,0x00,0x00,0x3a,0x01,0x00,0x00,0x3b,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x3d,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x32,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x3e,0x01,0x00,0x00,0x3d,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x3f,0x01,0x00,0x00,0x3e,0x01,0x00,0x00,0x3e,0x01,0x00,0x00,0x3e,0x01,0x00,0x00,0x0c,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x39,0x01,0x00,0x00,0x3c,0x01,0x00,0x00,0x3f,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x30,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0xf9,0x00,0x02,0x00,0x38,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x38,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x42,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x41,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x43,0x01,0x00,0x00,0x42,0x01,0x00,0x00,0xba,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x44,0x01,0x00,0x00,0x43,0x01,0x00,0x00,0x3d,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x46,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x44,0x01,0x00,0x00,0x45,0x01,0x00,0x00,0x46,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x45,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x48,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x4a,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x49,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x4b,0x01,0x00,0x00,0x4a,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x4d,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x4c,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x4e,0x01,0x00,0x00,0x4d,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x50,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x4f,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x51,0x01,0x00,0x00,0x50,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x52,0x01,0x00,0x00,0x4b,0x01,0x00,0x00,0x4e,0x01,0x00,0x00,0x51,0x01,0x00,0x00,0x81,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x53,0x01,0x00,0x00,0x48,0x01,0x00,0x00,0x52,0x01,0x00,0x00,0x0c,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x54,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x53,0x01,0x00,0x00,0x3a,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x47,0x01,0x00,0x00,0x54,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x55,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x56,0x01,0x00,0x00,0x47,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x57,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x41,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x58,0x01,0x00,0x00,0x57,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x59,0x01,0x00,0x00,0x58,0x01,0x00,0x00,0x58,0x01,0x00,0x00,0x58,0x01,0x00,0x00,0x0c,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0x5a,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x55,0x01,0x00,0x00,0x56,0x01,0x00,0x00,0x59,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x30,0x01,0x00,0x00,0x5a,0x01,0x00,0x00,0xf9,0x00,0x02,0x00,0x46,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x46,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x5c,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x5b,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x5d,0x01,0x00,0x00,0x5c,0x01,0x00,0x00,0xba,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x5e,0x01,0x00,0x00,0x5d,0x01,0x00,0x00,0x3d,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x60,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x5e,0x01,0x00,0x00,0x5f,0x01,0x00,0x00,0x60,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x5f,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x62,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x64,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x63,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x65,0x01,0x00,0x00,0x64,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x67,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x66,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x68,0x01,0x00,0x00,0x67,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x6a,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x69,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x6b,0x01,0x00,0x00,0x6a,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x6c,0x01,0x00,0x00,0x65,0x01,0x00,0x00,0x68,0x01,0x00,0x00,0x6b,0x01,0x00,0x00,0x83,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x6d,0x01,0x00,0x00,0x62,0x01,0x00,0x00,0x6c,0x01,0x00,0x00,0x0c,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x6f,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x6d,0x01,0x00,0x00,0x6e,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x61,0x01,0x00,0x00,0x6f,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x70,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x71,0x01,0x00,0x00,0x61,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x72,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x5b,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x73,0x01,0x00,0x00,0x72,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x74,0x01,0x00,0x00,0x73,0x01,0x00,0x00,0x73,0x01,0x00,0x00,0x73,0x01,0x00,0x00,0x0c,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0x75,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x70,0x01,0x00,0x00,0x71,0x01,0x00,0x00,0x74,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x30,0x01,0x00,0x00,0x75,0x01,0x00,0x00,0xf9,0x00,0x02,0x00,0x60,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x60,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x77,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x76,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x78,0x01,0x00,0x00,0x77,0x01,0x00,0x00,0xba,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x79,0x01,0x00,0x00,0x78,0x01,0x00,0x00,0x3d,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x7b,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x79,0x01,0x00,0x00,0x7a,0x01,0x00,0x00,0x7b,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x7a,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x7e,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x7d,0x01,0x00,0x00,0x7e,0x01,0x00,0x00,0x39,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x7f,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0x7d,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x7c,0x01,0x00,0x00,0x7f,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x7c,0x01,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x81,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x82,0x01,0x00,0x00,0x81,0x01,0x00,0x00,0x31,0x00,0x00,0x00,0x8d,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x83,0x01,0x00,0x00,0x82,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x84,0x01,0x00,0x00,0x7c,0x01,0x00,0x00,0x19,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x84,0x01,0x00,0x00,0x83,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x85,0x01,0x00,0x00,0x7c,0x01,0x00,0x00,0x1c,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x85,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x86,0x01,0x00,0x00,0x7c,0x01,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x87,0x01,0x00,0x00,0x86,0x01,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x88,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0x87,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x89,0x01,0x00,0x00,0x7c,0x01,0x00,0x00,0x1f,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x89,0x01,0x00,0x00,0x88,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x8a,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x8c,0x01,0x00,0x00,0x7c,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x8b,0x01,0x00,0x00,0x8c,0x01,0x00,0x00,0x39,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x8d,0x01,0x00,0x00,0x15,0x00,0x00,0x00,0x8b,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x8e,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x76,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x8f,0x01,0x00,0x00,0x8e,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x90,0x01,0x00,0x00,0x8f,0x01,0x00,0x00,0x8f,0x01,0x00,0x00,0x8f,0x01,0x00,0x00,0x0c,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0x91,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x8a,0x01,0x00,0x00,0x8d,0x01,0x00,0x00,0x90,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x30,0x01,0x00,0x00,0x91,0x01,0x00,0x00,0xf9,0x00,0x02,0x00,0x7b,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x7b,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0x93,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x92,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x94,0x01,0x00,0x00,0x93,0x01,0x00,0x00,0xba,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x95,0x01,0x00,0x00,0x94,0x01,0x00,0x00,0x3d,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x97,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x95,0x01,0x00,0x00,0x96,0x01,0x00,0x00,0x97,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x96,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x9a,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x99,0x01,0x00,0x00,0x9a,0x01,0x00,0x00,0x39,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x9b,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0x99,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x98,0x01,0x00,0x00,0x9b,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x9c,0x01,0x00,0x00,0x98,0x01,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x9d,0x01,0x00,0x00,0x9c,0x01,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x9e,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0x9d,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x9f,0x01,0x00,0x00,0x98,0x01,0x00,0x00,0x1f,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x9f,0x01,0x00,0x00,0x9e,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xa0,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xa2,0x01,0x00,0x00,0x98,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0xa1,0x01,0x00,0x00,0xa2,0x01,0x00,0x00,0x39,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0xa3,0x01,0x00,0x00,0x15,0x00,0x00,0x00,0xa1,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0xa4,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0x92,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xa5,0x01,0x00,0x00,0xa4,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0xa6,0x01,0x00,0x00,0xa5,0x01,0x00,0x00,0xa5,0x01,0x00,0x00,0xa5,0x01,0x00,0x00,0x0c,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0xa7,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0xa0,0x01,0x00,0x00,0xa3,0x01,0x00,0x00,0xa6,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x30,0x01,0x00,0x00,0xa7,0x01,0x00,0x00,0xf9,0x00,0x02,0x00,0x97,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0x97,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0xa9,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0xa8,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xaa,0x01,0x00,0x00,0xa9,0x01,0x00,0x00,0xba,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0xab,0x01,0x00,0x00,0xaa,0x01,0x00,0x00,0x3d,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0xad,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0xab,0x01,0x00,0x00,0xac,0x01,0x00,0x00,0xad,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0xac,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xb0,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0xaf,0x01,0x00,0x00,0xb0,0x01,0x00,0x00,0x39,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0xb1,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0xaf,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0xae,0x01,0x00,0x00,0xb1,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0xae,0x01,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xb4,0x01,0x00,0x00,0xb3,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0xb2,0x01,0x00,0x00,0xb4,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xb5,0x01,0x00,0x00,0xae,0x01,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xb6,0x01,0x00,0x00,0xb5,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0xb8,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0xb7,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xb9,0x01,0x00,0x00,0xb8,0x01,0x00,0x00,0x88,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xbb,0x01,0x00,0x00,0xb9,0x01,0x00,0x00,0xba,0x01,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xbc,0x01,0x00,0x00,0xb6,0x01,0x00,0x00,0xbb,0x01,0x00,0x00,0x8d,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xbd,0x01,0x00,0x00,0xbc,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xbe,0x01,0x00,0x00,0xae,0x01,0x00,0x00,0x19,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xbe,0x01,0x00,0x00,0xbd,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xbf,0x01,0x00,0x00,0xb2,0x01,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xc0,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0xbf,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xc1,0x01,0x00,0x00,0xae,0x01,0x00,0x00,0x1f,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xc1,0x01,0x00,0x00,0xc0,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xc4,0x01,0x00,0x00,0xae,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0xc3,0x01,0x00,0x00,0xc4,0x01,0x00,0x00,0x39,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0xc5,0x01,0x00,0x00,0x15,0x00,0x00,0x00,0xc3,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0xc6,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0xa8,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xc7,0x01,0x00,0x00,0xc6,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0xc8,0x01,0x00,0x00,0xc7,0x01,0x00,0x00,0xc7,0x01,0x00,0x00,0xc7,0x01,0x00,0x00,0x0c,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0xc9,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0xc5,0x01,0x00,0x00,0xc8,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x30,0x01,0x00,0x00,0xc9,0x01,0x00,0x00,0xf9,0x00,0x02,0x00,0xad,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0xad,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0xcb,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0xca,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xcc,0x01,0x00,0x00,0xcb,0x01,0x00,0x00,0xba,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0xcd,0x01,0x00,0x00,0xcc,0x01,0x00,0x00,0x3d,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0xcf,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0xcd,0x01,0x00,0x00,0xce,0x01,0x00,0x00,0xcf,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0xce,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xd2,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0xd1,0x01,0x00,0x00,0xd2,0x01,0x00,0x00,0x39,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0xd3,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0xd1,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0xd0,0x01,0x00,0x00,0xd3,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xd5,0x01,0x00,0x00,0xd0,0x01,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xd6,0x01,0x00,0x00,0xd5,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0xd4,0x01,0x00,0x00,0xd6,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0xd8,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0xd7,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xd9,0x01,0x00,0x00,0xd8,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xda,0x01,0x00,0x00,0xd0,0x01,0x00,0x00,0x1c,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xda,0x01,0x00,0x00,0xd9,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xdb,0x01,0x00,0x00,0xd4,0x01,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xdc,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0xdb,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xdd,0x01,0x00,0x00,0xd0,0x01,0x00,0x00,0x1f,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xdd,0x01,0x00,0x00,0xdc,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xde,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0xd0,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0xdf,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,0x39,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0xe1,0x01,0x00,0x00,0x15,0x00,0x00,0x00,0xdf,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0xe2,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0xca,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xe3,0x01,0x00,0x00,0xe2,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0xe4,0x01,0x00,0x00,0xe3,0x01,0x00,0x00,0xe3,0x01,0x00,0x00,0xe3,0x01,0x00,0x00,0x0c,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0xe5,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0xde,0x01,0x00,0x00,0xe1,0x01,0x00,0x00,0xe4,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x30,0x01,0x00,0x00,0xe5,0x01,0x00,0x00,0xf9,0x00,0x02,0x00,0xcf,0x01,0x00,0x00,0xf8,0x00,0x02,0x00,0xcf,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xe6,0x01,0x00,0x00,0x2a,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xe7,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xe8,0x01,0x00,0x00,0x02,0x01,0x00,0x00,0x41,0x00,0x05,0x00,0x33,0x01,0x00,0x00,0xea,0x01,0x00,0x00,0x19,0x01,0x00,0x00,0xe9,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xeb,0x01,0x00,0x00,0xea,0x01,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xec,0x01,0x00,0x00,0xe8,0x01,0x00,0x00,0xeb,0x01,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0xed,0x01,0x00,0x00,0xec,0x01,0x00,0x00,0xec,0x01,0x00,0x00,0xec,0x01,0x00,0x00,0x0c,0x00,0x08,0x00,0x07,0x00,0x00,0x00,0xee,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0xe6,0x01,0x00,0x00,0xe7,0x01,0x00,0x00,0xed,0x01,0x00,0x00,0x3e,0x00,0x03,0x00,0x30,0x01,0x00,0x00,0xee,0x01,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0xf1,0x01,0x00,0x00,0x30,0x01,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xf2,0x01,0x00,0x00,0xf1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xf3,0x01,0x00,0x00,0xf1,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xf4,0x01,0x00,0x00,0xf1,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x50,0x00,0x07,0x00,0x0c,0x01,0x00,0x00,0xf5,0x01,0x00,0x00,0xf2,0x01,0x00,0x00,0xf3,0x01,0x00,0x00,0xf4,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xf0,0x01,0x00,0x00,0xf5,0x01,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00,0x36,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x37,0x00,0x03,0x00,0x08,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x0c,0x00,0x07,0x00,0x06,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x0c,0x00,0x07,0x00,0x06,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x17,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x0c,0x00,0x07,0x00,0x06,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x0c,0x00,0x07,0x00,0x06,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x24,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x2d,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x33,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0xb8,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x3a,0x00,0x00,0x00,0x3b,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x3b,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0xfe,0x00,0x02,0x00,0x3f,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x3c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0xba,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x43,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x43,0x00,0x00,0x00,0x45,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x45,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x47,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x88,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x4d,0x00,0x00,0x00,0x47,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x44,0x00,0x00,0x00,0x4d,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0x46,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x4e,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x51,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x52,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x51,0x00,0x00,0x00,0x88,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x52,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x44,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0x46,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x46,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x41,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x56,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x56,0x00,0x00,0x00,0xb4,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x58,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x59,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x5c,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x5c,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x5e,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0x5e,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x88,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x8d,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x5b,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0x5a,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x65,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x66,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x67,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x67,0x00,0x00,0x00,0xb4,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x66,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x69,0x00,0x00,0x00,0x6a,0x00,0x00,0x00,0x74,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x6a,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x6e,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x6f,0x00,0x00,0x00,0x6e,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x6f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x88,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x72,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x72,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x5b,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0x6b,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x74,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x75,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0x75,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x79,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x7a,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x88,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x7b,0x00,0x00,0x00,0x79,0x00,0x00,0x00,0x7a,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x7d,0x00,0x00,0x00,0x7b,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x5b,0x00,0x00,0x00,0x7d,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0x6b,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x6b,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0x5a,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x5a,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0x88,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x5b,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0xb8,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x81,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x81,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x83,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x82,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x86,0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x5b,0x00,0x00,0x00,0x86,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0x83,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x83,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x87,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x89,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x8a,0x00,0x00,0x00,0x87,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0x89,0x00,0x00,0x00,0xfe,0x00,0x02,0x00,0x8a,0x00,0x00,0x00,0x38,0x00,0x01,0x00,0x36,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x37,0x00,0x03,0x00,0x0d,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x37,0x00,0x03,0x00,0x0d,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x37,0x00,0x03,0x00,0x0d,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x13,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x8d,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0xb8,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x8d,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x8e,0x00,0x00,0x00,0x8f,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x8f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x91,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x91,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x11,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0x90,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x90,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x93,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0xba,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x94,0x00,0x00,0x00,0x93,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x94,0x00,0x00,0x00,0x95,0x00,0x00,0x00,0x96,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x95,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x97,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x98,0x00,0x00,0x00,0x97,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x11,0x00,0x00,0x00,0x98,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0x96,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x96,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x99,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0xb8,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0x9b,0x00,0x00,0x00,0x99,0x00,0x00,0x00,0x9a,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0x9d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0x9b,0x00,0x00,0x00,0x9c,0x00,0x00,0x00,0x9d,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x9c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x9e,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x9f,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xa1,0x00,0x00,0x00,0x9f,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xa2,0x00,0x00,0x00,0xa1,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xa3,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xa4,0x00,0x00,0x00,0xa2,0x00,0x00,0x00,0xa3,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xa5,0x00,0x00,0x00,0x9e,0x00,0x00,0x00,0xa4,0x00,0x00,0x00,0xfe,0x00,0x02,0x00,0xa5,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x9d,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xa7,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0xb8,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0xa8,0x00,0x00,0x00,0xa7,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0xa8,0x00,0x00,0x00,0xa9,0x00,0x00,0x00,0xaa,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0xa9,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xab,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0xfe,0x00,0x02,0x00,0xab,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0xaa,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xad,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0xb8,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0xaf,0x00,0x00,0x00,0xad,0x00,0x00,0x00,0xae,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0xb1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0xaf,0x00,0x00,0x00,0xb0,0x00,0x00,0x00,0xb1,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0xb0,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xb3,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xb5,0x00,0x00,0x00,0xb3,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xb7,0x00,0x00,0x00,0xae,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0xb5,0x00,0x00,0x00,0xb7,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xb9,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xba,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0xb9,0x00,0x00,0x00,0xfe,0x00,0x02,0x00,0xba,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0xb1,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xbc,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0xfe,0x00,0x02,0x00,0xbc,0x00,0x00,0x00,0x38,0x00,0x01,0x00,0x36,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x37,0x00,0x03,0x00,0x08,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x16,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xc2,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xc5,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xcf,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xea,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xec,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xee,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xf2,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xf9,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xfb,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0xfd,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xc1,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xbf,0x00,0x00,0x00,0xc1,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xc3,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xc4,0x00,0x00,0x00,0xc3,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xc2,0x00,0x00,0x00,0xc4,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0xc6,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xc7,0x00,0x00,0x00,0xc6,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xc5,0x00,0x00,0x00,0xc7,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0xc2,0x00,0x00,0x00,0xb8,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0xcb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0xc9,0x00,0x00,0x00,0xca,0x00,0x00,0x00,0xcb,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0xca,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xcc,0x00,0x00,0x00,0xc5,0x00,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0xcd,0x00,0x00,0x00,0xcc,0x00,0x00,0x00,0xcc,0x00,0x00,0x00,0xcc,0x00,0x00,0x00,0xfe,0x00,0x02,0x00,0xcd,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0xcb,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0xc5,0x00,0x00,0x00,0xb8,0x00,0x05,0x00,0x39,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0xf7,0x00,0x03,0x00,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x00,0x04,0x00,0xd1,0x00,0x00,0x00,0xd3,0x00,0x00,0x00,0xd9,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0xd3,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xd5,0x00,0x00,0x00,0xc5,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xd6,0x00,0x00,0x00,0xc2,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xd7,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0xd6,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,0xd5,0x00,0x00,0x00,0xd7,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xd2,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0xd4,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0xd9,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xda,0x00,0x00,0x00,0xc5,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0xc2,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xdc,0x00,0x00,0x00,0xda,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xdd,0x00,0x00,0x00,0xc5,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xde,0x00,0x00,0x00,0xc2,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xdf,0x00,0x00,0x00,0xdd,0x00,0x00,0x00,0xde,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0xdc,0x00,0x00,0x00,0xdf,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xd2,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0xf9,0x00,0x02,0x00,0xd4,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0xd4,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xe1,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xcf,0x00,0x00,0x00,0xe1,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xe3,0x00,0x00,0x00,0xc5,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xe4,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0xe3,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xe5,0x00,0x00,0x00,0xcf,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xe6,0x00,0x00,0x00,0xe4,0x00,0x00,0x00,0xe5,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xe2,0x00,0x00,0x00,0xe6,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xe7,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xe9,0x00,0x00,0x00,0xe7,0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xeb,0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xea,0x00,0x00,0x00,0xeb,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xed,0x00,0x00,0x00,0xcf,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xec,0x00,0x00,0x00,0xed,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xee,0x00,0x00,0x00,0xe9,0x00,0x00,0x00,0x39,0x00,0x07,0x00,0x06,0x00,0x00,0x00,0xef,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0xea,0x00,0x00,0x00,0xec,0x00,0x00,0x00,0xee,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xf0,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xf3,0x00,0x00,0x00,0xcf,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xf2,0x00,0x00,0x00,0xf3,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xf5,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xf4,0x00,0x00,0x00,0xf5,0x00,0x00,0x00,0x39,0x00,0x07,0x00,0x06,0x00,0x00,0x00,0xf6,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0xf2,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xf7,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0xf7,0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xfa,0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xf9,0x00,0x00,0x00,0xfa,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0xcf,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xfb,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xfd,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x39,0x00,0x07,0x00,0x06,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0xf9,0x00,0x00,0x00,0xfb,0x00,0x00,0x00,0xfd,0x00,0x00,0x00,0x50,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xef,0x00,0x00,0x00,0xf6,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x02,0x00,0xff,0x00,0x00,0x00,0x38,0x00,0x01,0x00}; +static const unsigned int dynamic_frag_spv_size = 11984; + diff --git a/src/layer.c b/src/layer.c index 7b28a36..649fd1d 100644 --- a/src/layer.c +++ b/src/layer.c @@ -374,8 +374,9 @@ struct dynamic_push_constants { float huerotate_angle; /* 4 */ float saturate_str; /* 4 */ float saturate_amount; /* 4 */ + float opacity; /* 4 */ }; -/* Total: 76 bytes (19 floats) */ +/* Total: 80 bytes (20 floats) */ static void parse_dynamic_cfg(const char* path, struct dynamic_push_constants* pc) { @@ -391,6 +392,7 @@ static void parse_dynamic_cfg(const char* path, struct dynamic_push_constants* p pc->huerotate_angle = 180.0f; pc->saturate_str = 0.0f; pc->saturate_amount = 0.0f; + pc->opacity = 1.0f; if (!path) return; @@ -426,6 +428,8 @@ static void parse_dynamic_cfg(const char* path, struct dynamic_push_constants* p } else if (strcmp(name, "saturate") == 0) { pc->saturate_str = a1; if (n >= 3) pc->saturate_amount = a2; + } else if (strcmp(name, "opacity") == 0) { + pc->opacity = a1; } } fclose(f); @@ -2954,7 +2958,7 @@ static void setup_swapchain_data_pipeline(swapchain_data_t* data) device_data->device, &sdl_info, NULL, &data->shader_desc_layout)); - /* push constant range: full dynamic_push_constants (76 bytes) */ + /* push constant range: full dynamic_push_constants (80 bytes) */ VkPushConstantRange pc_range = {}; pc_range.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; pc_range.offset = 0; From cbdea2eeb4f1e59849c91c4d2fc9e18970d5322b Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 26 Apr 2026 08:52:03 +0000 Subject: [PATCH 23/25] chore: bump version to v0.2.4 --- PKGBUILD | 2 +- aur/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 9f0426b..c39455b 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.3 +pkgver=0.2.4 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') diff --git a/aur/PKGBUILD b/aur/PKGBUILD index e33d38a..88f99c1 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.3 +pkgver=0.2.4 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') From 441cd50a3d57011ffbb857dbe006a63a9d6bb501 Mon Sep 17 00:00:00 2001 From: fibsussy Date: Sun, 26 Apr 2026 01:53:11 -0700 Subject: [PATCH 24/25] chore: rebuild dynamic shader SPIR-V --- shaders/dynamic_frag.spv | Bin 11544 -> 11984 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/shaders/dynamic_frag.spv b/shaders/dynamic_frag.spv index 9ac95e89b75075857fa11daf8752a55d0e2b618b..5e720a1afd82b5b60e2c3424e2f387b0ac47a1cd 100644 GIT binary patch literal 11984 zcmbW6cbr{C6~`}ZHnadCG!cXZP$JEQ7GfX}K@&7e5ET`5dD(0>E7{$!B?5vH0mT9; zHoyi}1O-JD!~%j?umFl;N3j7SB4R;B{eIuOzsKZ${L9N8=J)%ZGc#w-%-r{O)3f1j z8&%Z?)n?Vk)n7NL+Rs+ihA0)<)ONdg>9I@q9iLdS?*RwSF<^_TryXa^meoep6k2V# zH8i4QQydRs(}`1O0#Fa5R@IH@y{Kh;FY|1MZ)|XR-^6I&s`1sc*RI@u0dYOmrs(}x zFZs=&T{Ssi4571E&Rx*?L2k!xNxP=T(`iqt@m91GZ9KKwmX--JMt7cVI(mDY?ZLw* zcgEaZ%&N>~AMk2Syg%)V8ZV+9ukrD;t7?3Gfo}vS=4NolxfPr|?*@1BpHkf?ZjH5u zX|31&4gNrbKiJ?8HTc5~{z!xWv%w#2@D16w;nw(x$mBD%np*R|@z(H~)dOSE-TRee zt--#Dfs_0CM@PpflJ(jSePl&{yYKekWs~Epju;&opJySyJLEumrst3)I)Y-H;&$(zcbG!(FV<_qj{#={g*$sZqI-JsHGep80oH|QH%`-_`ECQt%=F8$GUZW-kq+mH9R^w zGSSW5yEM9{)ju?GN_$^-U{ls`L3{b{iQw`6v4Me+zR9)3sqKk2IyN*oG}7|OqfD*# zLK|!i5A>~E-aS5^@j2-IqpL?fO!CF>_8zs*(3GkLw{8RVnK}*5U2eyo4leJ@8`tAK z)dfZDh3omIRF|yBd#Wpn*elob^;TEGvz|UyWS%#z7t>SSR`kDpJzsBi$N%VmS0l!E z=jh}F*QZm9#mwP-n`Hrc!guY^Huv7`+~qypJF$cebFX%*{n6-Bsd;Xrd5_dQ1JQbF z&39xp?~iehD>Uzq+D?V${ZX4)Xx<;S-3!ee)Mgi&cSmjSLi6sZ%_%hRj@ki*=ABVH zxX`>SYKIh>cSP;*Li28@9a(7BLv2Z+c^A}{V(y9OdKTEahL?NfzGjcM=F`wx&*I(K zLo416WW8o$+cTbZlIx!dw?=B(EV%U%tLt}t=`)L-uFd}Hv2BTS&t_sid)0i04()RH zaD&3X3)mcucg(pM&tc)#`Qtb5F>f29=7XajY7|en_2W4_yuVFv=h!Pxb9Ei%6TTyrodPk=`t{ZhwFNcz-ubv68-pFs zIvBqRT(`RMa_^y<@zVgtdsmY0bhObKXD+b+w&3>u(e7Mr)4r#Um3i#@|C-}JjDI?H?-T!i@YH92u>D=b-u&OS zJ{8S9jiuirbkBMCQSj8wd6#0oU*bO+?zrK{!yP}oAMU*fUkNvt@FBSGlH@f4_pHVe zw-(*^OZfS4-!0*n!o6GJ*TB7Za`U?mUR75g5&tc4-!I{J!hN@d-wXG>V*URJwkDn< z_fPISMC~A|VV$j!kJ{f+tdX(iG!ia-1Yj|9PWDjTrT--4en=i{Py>=Io$q!F3S(4 ze!den!h9ddy%U>Z-uL6Ex_h)aW{mnVXzu?OwGONnvP~_S-vw^&=`#y#pP5)uPOxuw(0UeV#G3jPWF}+Ie;S9$+;;KbFPPb?a37xnR@Z!NyhD!f+1KxQ#?A$+>GK}Qt(EVz12Ai~ zA7;G!cwntxM~wS;5M0goiTijk*vEa;HxE;D@5GsRKG^xf7u5Vr#x<`);J!oElh2{x zWZym z3|Kw2dM?dShb4=(rh1#n}M*Ky!x zEnkSHp1fWJR*Pj1UyR02dk>w*v5n2y)$bmr&bFENC1B_E^E35$DOf#w_%g6s_V5I- zk9(-E4^wjw#aZ)maJh#o;Lg=w$9QiB!0O3o5Nym!EcvVgt0(5=U}J``#GD9LPpwvi z9oxS8a({-w=A}P-I11*c{kw<$5zN}PX!T`1Yry3mo&+~0d5wXawH!xNPhJyXwOICW z5{;ks9y*U>8=F1U?;fVkwwd=8VCP+nr5-1P)w74EfYq{xuLS$Jhx$&%)Z9aH*8D24 zYc`M5Y31|l`|xV8-;LDupGK=@UVfgQ0ao*Oi{!NquD*^K_y09w%y<8}wRR?4-S3DQ z>nwQ2axS@X@tnuu>YfdAIj8QUo^f9fc3%5AuH3lP=MCWU zOuPwhys>Yjm8V|kg8loWy5sLpdmh%@yEoT*&dgijYO$P|x1#aWJ~QUw_{KW7IqCPz zWM6GF@7uu6dp?$WydA8bGxH9xTF%V7z&@TCeecB7JTv0dqnV9$)Y z{tIZ;Qt$VG)yjQ(FI+wQ^gghAtDb)E2dAIo%8g4-7lX|y`~zU)jlG0co*X|2cAwN! zuMdHn_4+WHdiLofV6|BG>7!`;wD-w89N$>yHYfe=Q)+3Oc|Qhr-b=CU(`8`w?9=67 zwd~U;z&`GizK>&S?vpq*_#`;{bR}4x8hi@uKB=4M6|`!p_ou;X z12(>V7kn13p0!@9AG-$2T0aL?Kc~K`k=t)c9tw=S)2{_$s)$-(N#h z&pG=#SS^-w_6;yHYfd_vz!In%==BS^WK7`9^V41=bU{Ttd?_jE7-?# zrtdqLn&(WM8hjU=b9Oseo*H})>^W06&)aC#Qt$7B)yi}B1Gu{JchJhSjvsWd`*(UGbg7+-=@4#7y zpON>#H^h?XePHvv7fbzq4_5d0M*G|kwx4=({{vV(mfRmeA6VV*xQ^+bt7Q!T-J%@xK)7S({c{l57c`-A=un>^rue9s3v zf6n>~z?)*_9X}4Pel_QCKJ5!J`>DGJFQ)Zz5A?kV8^Bzs}sQXQ_napuysw1mV-~g)bqV<1z5cwvlhqGs#!PJV7}&^F;{}i+6=;* z`L9A#Pi=<4_EWbuC(`;@8+|XwCNSp`XWgs8&2sV8Qnjw$zM6iq#~Sp&A8de(6g zxU9_>+&J}h^}A&ptnM91ZPcudYcOB)PA-#R^DT2(3s+CfE9#hXzfVR}Prj#s?Wdl6 zPX(9xz7lSndh$ITtbQ7neAUW)&AZ%N_c(LB3he&pyu2E$R-O&D#Ge5+KJUSGV6{Ur z_xVg(ANN_`YcMtICeAo#gB>U9cr94%EG+9#Gw<}bP5;+{?H_&)cu~P$58emMd-e@r z`xvLs_pDmJZ%hTxzH;CWmvu>Z#3nV71idEnpvOqwmd_ zn&XHw&RfBbliHjQR!eR4sac!!w@v@IfsM&$#oNJZ_IHooN$X=C`rd)5nTI&zybJ6& zIinYV)yh27%p?76)Bi%S{Zo&3gVip=%;UYZKIWnCJ(!w#h%?Un!0to%`@z!-elb{o z^1K9W%*9x~AAA6;-j8LR4}#4vF&_dOr=Hq>80`G|JTr3hGtZ3kQE<7=OW|sBG1qw+ zt&i)}_c2V(al{$taby*7MWw zvYuDh{?zj`aAVXn#%ICil9+42=AoW?UJJIbzG$BVtGf@W@pWKx(&yUc=4|en?+aja z)-TSz-3Yub=CcVlk2-8jyA9?T+tKFtg6qM?hu_%XH#hjL4gTE*zq`TjYw-IU{DB64 zu)!Z{@P`}xkp}-~gFjmHMSPZR4!!}i4m)6}B>c(3y zdE&ncHhvc@@m~Y08*e@3@qHca7!-tFH8 ztHnGcYWA~#`rQV$U*^9ZtTq>O{yS)WoL}GfupeQLBhEPA2Rlyq55TS~=lM?XS(tjx z{SU$R(`RiwOKQG5o!2>>D`Wl`T+Z8>60k`wOsR z=}TT}WnSi&IerN?cVoRD^7wuQcK*!wYw!|GJu$xl+b{F~7HpilW8O`xmiXU+J*TPd zy_ZP6aJKw{!^33;Fu=6>d{q(2b-@x`ujs6Z+E7$xFcyjW+AW#2)fs>Q(2)Q}< eesHYh@Ncj=*xxw)xl{iETNCp%&O4>%d-uN*=zr1x literal 11544 zcmbW6cYs|*6~-TI5?X-Jr3eWG37tp@F%Squ2oNL`1qE3)o6RPY-3?nJAS#g-RC+HW zphy(~0RamL#0H98Y>0pzv0*_){r%p%-(zzB^smA6`@(O9Xm zMq|~+FIQ?bpLH55qcqUQG}{AbA31xcq2YNu?Y8?a2CUWSXvP_{c4L*sC|a$rYhk~R z)p0zFjU!H-2|yi;+GsqAJ{q-*AI&^#;2Z3n+c`YYxnO9~q$Trrokm^PJ5=FgX%|%Z;Q~JjPRw#}#(4^yJf8!%@*mast+;EjtB=-t zy;$Qf)%YK4{LeN1a*e-I zX=`)aV|t$Fjtur!L$+gAjozHUHP33%dd;b&d8V8F=f1XX&wuxTrR?kJZ?B~ zjd;7t^|gF!;^R&X4h(k<%4UH!d_ddQ*W^R5ha4UY`I)~)UH?zDYfeFG!? z!_7T>9UHKi%Q%|WS$ zv-ZuiF{*Jq+XXO+)ceFX?so?S+EL(whG%hP*FJHkos&U;4yrXe@5qrl9zEO=Y ztiU@OPZY6FuHYNhczOjsy7{gf7#Zfcx7L0jYxI6hpbkFaTefJEdrvlR^N#izp2ezj z54NiO(dg1p^PENV+^e}~(K;&4cUm;hyK%28G|#)*W`*W?R~uhwo_Dp0g=P+FlM2nV zuC_y=dDhi-DKyWz+HQsB8CTo0&^+5}dli~zT5aD#^DL{)EHvw(HVd=#l2%b?#HTN$FmN`uLjqxZoJ$(r)K=Xy1%$?Ehnq zy%FPh9=zA)BKKXY=ALg19uKBz?uC3436K3Z1siKF)>i)(7(eY=c)oq&-x;1->;ksG z`R~C0UFQ@u_b--y)6qTC;RnF2QTRb{-y7kx;f@=A4BYX{WGvN@Qk=$ z@@Fe;4_0qot%;9u|3I-O#+rlQm8^l>bLDrRlKa^iZf*SBEV-YLCHM2Ot%vWO$(Z%n8FLQz>W!8D5Har6u5dN)ynD4f*vGxnw;QJB z{)ipNJoW%PU-+ICKZ9}gPlfxQQ%^o`0@w4IhNeD;?CiG}SS>cTTKC>){4{o|=5~Bz zvu^#bkYjSS&Aj`7op(BxI_wKpPaS4})l!H3!9LbO-+q{ybr5IWZw6b3%yl5xxemZG z*DSDlVh#oya}bu8L%`~ZITUQnY%DQv0jsB0hk+g2zWSC{wVwkvFa2Yws&zda%ui!$ zOuu_$?Pk*I%X*Fgm-~7o+?eEb6u4f?x1y;hueX8KV%fu^(fDcZq4PMlvDriY?qTX| zn|a?3cHU#K)Z-ms_3YuXV72VwJHbBgp}ylVHTO`QHFtu`J?w%z*9ldO_hv3wJ^9Q7 z8`F&?pB}J!VtT>G%*PV50IZ%`Ed)EZef8!3ybEkz`m=|N!2C47_v=3qvv$YR>dSii zz~vtH!;MK^17Pzy21{Ox!RpEDB(Pd6dpL;3Pje5Q$FYsg9_n`wQ)k=EI}CQ-AuRKb zfYq~yOTcQ`!;`^2?xDVSV`}c9IBR|n*fpESskHK`)qOY(?DrRS{io2XnU~)g-V0Xq zyMFR|A6$JYG4B8S!D_zW&#Sc4;p%>m%UDa{8Oyok#>M}E%J1(H`sHQ+Gb+EoS0tA+ z(bPQ~=5kimM?K@74R&7pIj-Ee)aM*9|aq4>~*yAdE~cu({ujCHGH*)t6Ow?mn>Ez1Y%9yC3XW`tnZr3|PIq z(+|LtgE`8LOO6j#{_-q6gr=Ue^jWZDs;A%Qz>b?cFE=iA`#jjXg+B~7-WwEerntIOCV_>yd&eG#({4~#!c{skY&TUTmJxked+sykVu=6g*vL9at ztLH3z1+12{^fj=LXGz~zF*VPUI5qe>*!j)lNm_Yo@C~qMNnQUFv}(!gn_%;L3QJz! z0;^|Fz74it-tTf_;{Q(NFZcSpXzJPP?}6QG_4NBb*m1Mha^teDAAns~_z%IxyN;)6 zcVhS2$G?e8Ao(qHvyYR`OexDuAZ3JS23Qm zoJIeJs-BqfV8n)Nw!i-P{M&bY&Tp*wx?lQICx3@@4dFY3jagc~ z*Zq6BG3x%^z&gDVQ}_FyW4h;R8NJCW-5;#xdY%6O zS|8`v_h#%ZnB#~u&VgXp5q=QZx}**VgJ)sti8%yZ)@nA~IQ4w~9tw7Beb#R#t(xx@ zb2AU~$(VZ$~m1oa~=gYFJouW%Hw-0*!gqT z-v(YCEARNxaP@mRb5m)L!R)8*9=wCr$34*ZcB}_;?c$7m9N4ip!!rLn!Rm=Q9&Ai` z*E-?q*{c)4_EXO|U0~~)8qEctfT`y@&^)kuH)bu4rB$g?1lv#D+MG!1V{P=k3me9qOPqBt0@v5who+vG{wk*2n*lWS)Mhc*e(G7rN#L?J zgK*>2msanQA+Wl4Ahl7mHm<>Z%{#e_fX%neWeHq8G4HNo%KbhWO+ERZ0=A!e@;wz? z=KCJFaq7wUy~hE(NRYjk(Wf z(E7N~`aXcESvPUUIScGKS;yI6wKK7-L(RO?-!}cv0oy-(8F)s)&js&@-B`x?7})$0^Kr0o>Z$!rVCUE8nUR~Hd1joO!R0z{fvZi%T<2}HKCV;W zt(cnQh%?UZVAth5V*SR&|4DE;&!^yOcVfLG3puPez3VD<}+aPP)|J{0NYnzv~zgqDbe3q>Vegv})8)K>C7r~EUzGJP2Jn@f#jo%DQ{NrGCzrOEaKg1kIoN>MfcAW6e3uX8w8#{3buoa4vva*m(CjZsgZpMuLi&%o`I9DW8iMm_iTS+Ha2OI~Va zUgnoMehxNwW4#~p_?`zlf987uJPT7#%rC(9%ly9t8>jA=&(W$S{#RhnX=?i$u-dP& z#QY9yKl^(J Date: Sun, 26 Apr 2026 08:54:58 +0000 Subject: [PATCH 25/25] chore: bump version to v0.2.5 --- PKGBUILD | 2 +- aur/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index c39455b..54ddf0b 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.4 +pkgver=0.2.5 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64') diff --git a/aur/PKGBUILD b/aur/PKGBUILD index 88f99c1..2a83a81 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: fibsussy pkgname=krosshair -pkgver=0.2.4 +pkgver=0.2.5 pkgrel=1 pkgdesc="Crosshair overlay for games on linux using Vulkan" arch=('x86_64' 'aarch64')