--- /dev/null
+xop
+xscii
+xtatus
+xighlight
+xhallenge
+xuxuxu
+xarbon
+xource
--- /dev/null
+GNU GENERAL PUBLIC LICENSE
+
+Version 3, 29 June 2007
+
+Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
+
+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.
+
+<one line to give the program's name and a brief idea of what it does.>
+
+Copyright (C) <year> <name of author>
+
+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 <https://www.gnu.org/licenses/>.
+
+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:
+
+<program> Copyright (C) <year> <name of author>
+
+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 <https://www.gnu.org/licenses/>.
+
+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 <https://www.gnu.org/
+licenses /why-not-lgpl.html>.
--- /dev/null
+# xolatilization
+
+## xolatilization --- Collection of my undocumented libraries in single repository for easy installation after distro-hopping.
+
+This isn't like the usual compilation and installation method used in one-off repositories. You should run the 'install.sh' script first, so C
+header files are copied where they should be, then do the usual steps of running 'compile.sh' and 'install.sh', everything should be properly
+compiled and installed in that case. That's the sole reason of this comment.
+
+Compile: `$ sh compile.sh`
+
+Install: `$ sudo sh install.sh`
+
+Libraries:
+- `xtandard` --- Common functions in my programs with nice readable names.
+- `xrena` --- Arena allocator containing one big badass global variable.
+- `xyntax` --- General syntax definition for slow and easy parsing.
+- `xanguage` --- Evil definitions of various programming languages and more.
+- `xachine` --- Tiny Intel (IA32e) semi-32-bit only bytecode assembler.
+- `xiasma` --- Huge Intel (IA32e) 64-bit only selective bytecode assembler.
+- `xector` --- Linear algebra library for 2D, 3D and 4D vectors.
+- `xatrix` --- Linear algebra library for 2D, 3D and 4D matrices.
+- `xphere` --- Spherical coordinate system utility for ray tracing.
+- `xcript` --- Tiny INI-like script parser with extendable definition.
+- `xrocessor` --- Evil embeddable preprocessor Pascal-like syntax.
+- `xerminal` --- VT100 escape sequence shortcuts with 'ioctl' support.
+- `xommon` --- Sane and tiny XCB wrapper for graphical programs.
+- `xpengl` --- Sane and tiny OpenGL+GLFW wrapper for graphical programs.
+- `xulkan` --- Insane and huge XCB+Vulkan wrapper for graphical programs.
+- `xross` --- Wrapper for wrappers above for graphical programs.
+- `xpenal` --- Minimal wrapper for threaded OpenAL sound management.
+- `xprite` --- Dumb and small file format for storing indexed images.
+- `xormat` --- Containment for file formats I hate but have to use sadly.
+- `xui` --- UI library with predefined elements and offsets.
+
+Programs:
+- `xop` --- Retarded program for raw machine code debugging.
+- `xscii` --- Simple (not very) printing of readable ASCII table.
+- `xighlight` --- Highlight few languages and program outputs in terminal.
+- `xhallenge` --- Randomly generate daily challenges based on your attributes.
+- `xuxuxu` --- Terrence Andrew Davis tribute program to generate PNG image.
+- `xarbon` --- Carbon clone to render source code of few languages.
--- /dev/null
+#!/bin/bash
+
+set -xe
+
+mkdir -p $HOME/.config/xolatile/
+mkdir -p $HOME/.config/xolatile/xui
+
+gcc -std=gnu99 -Wall -Wextra -Wpedantic -Werror -Ofast -o xop xop.c
+gcc -std=gnu99 -Wall -Wextra -Wpedantic -Werror -Ofast -o xscii xscii.c
+gcc -std=gnu99 -Wall -Wextra -Wpedantic -Werror -Ofast -o xighlight xighlight.c
+gcc -std=gnu99 -Wall -Wextra -Wpedantic -Werror -Ofast -o xhallenge xhallenge.c
+gcc -std=gnu99 -Wall -Wextra -Wpedantic -Werror -Ofast -o xuxuxu xuxuxu.c -lpng
+gcc -std=gnu99 -Wall -Wextra -Wpedantic -Werror -Ofast -o xarbon xarbon.c -lpng
+
+cp -f xhallenge_list.cfg $HOME/.config/xolatile/xhallenge_list.cfg
+
+cp -rf xui $HOME/.config/xolatile/
+
+exit
--- /dev/null
+#!/bin/bash
+
+set -xe
+
+mkdir -p /usr/local/include/xolatile
+
+cp -f xtandard.h /usr/local/include/xolatile/xtandard.h
+cp -f xrena.h /usr/local/include/xolatile/xrena.h
+cp -f xyntax.h /usr/local/include/xolatile/xyntax.h
+cp -f xanguage.h /usr/local/include/xolatile/xanguage.h
+cp -f xcript.h /usr/local/include/xolatile/xcript.h
+cp -f xiasma.h /usr/local/include/xolatile/xiasma.h
+cp -f xachine.h /usr/local/include/xolatile/xachine.h
+cp -f xprite.h /usr/local/include/xolatile/xprite.h
+cp -f xphere.h /usr/local/include/xolatile/xphere.h
+cp -f xector.h /usr/local/include/xolatile/xector.h
+cp -f xormat.h /usr/local/include/xolatile/xormat.h
+cp -f xerminal.h /usr/local/include/xolatile/xerminal.h
+cp -f xaptor.h /usr/local/include/xolatile/xaptor.h
+cp -f xommon.h /usr/local/include/xolatile/xommon.h
+cp -f xpengl.h /usr/local/include/xolatile/xpengl.h
+cp -f xross.h /usr/local/include/xolatile/xross.h
+cp -f xui.h /usr/local/include/xolatile/xui.h
+cp -f xungeon.h /usr/local/include/xolatile/xungeon.h
+
+cp -rf xanguage /usr/local/include/xolatile/
+cp -rf xormat /usr/local/include/xolatile/
+
+if [ -f xop ]; then
+ cp -f xop /usr/local/bin/xop
+fi
+
+if [ -f xscii ]; then
+ cp -f xscii /usr/local/bin/xscii
+fi
+
+if [ -f xighlight ]; then
+ cp -f xighlight /usr/local/bin/xighlight
+fi
+
+if [ -f xhallenge ]; then
+ cp -f xhallenge /usr/local/bin/xhallenge
+fi
+
+if [ -f xuxuxu ]; then
+ cp -f xuxuxu /usr/local/bin/xuxuxu
+fi
+
+if [ -f xarbon ]; then
+ cp -f xarbon /usr/local/bin/xarbon
+fi
+
+exit
--- /dev/null
+#define use_mathematics
+
+#include "xtandard.h"
+#include "xector.h"
+#include "xarticle.h"
+
+#include <raylib.h>
+
+int main (void) {
+ particle_structure * particle = particle_initialize (1024);
+
+ InitWindow (800, 600, "Xarticle");
+
+ Camera camera = { 0 };
+ camera.position = (Vector3){ 0.0f, 2.0f, 4.0f }; // Camera position
+ camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
+ camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
+ camera.fovy = 60.0f; // Camera field-of-view Y
+ camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
+
+ SetTargetFPS(60);
+
+ Texture texture = LoadTexture ("xui/fullscreen_on.png");
+
+ while (! WindowShouldClose ()) {
+ UpdateCamera(& camera, CAMERA_FIRST_PERSON);
+
+ BeginDrawing ();
+
+ ClearBackground(RAYWHITE);
+
+ BeginMode3D(camera);
+
+ DrawPlane((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector2){ 32.0f, 32.0f }, LIGHTGRAY); // Draw ground
+
+ if (IsKeyPressed (KEY_ONE)) {
+ vector_3 p = {0,0,0};
+ vector_3 t = {0,0,0};
+ vector_3 s = {0.1f,0.1f,0.1f};
+
+ particle_append (particle, 0, 1.0f, 0, 0, & p, & t, & s);
+ }
+
+ if (IsKeyPressed (KEY_TWO)) {
+ vector_3 p = {1,1,1};
+
+ particle_effect_splash (particle, 0, 2.0f, 0, 0, & p, 60, 0.03, 3);
+ }
+
+ if (IsKeyPressed (KEY_THREE)) {
+ vector_3 p = {1,1,1};
+
+ particle_effect_evaporate (particle, 0, 2.0f, 0, 0, & p, 20, 0.001, 3);
+ }
+
+ BeginBlendMode (BLEND_ALPHA_PREMULTIPLY);
+
+ for (uint i = 0; i < particle->count; ++i) {
+ Vector3 vector = {particle->position [i]->x, particle->position [i]->y, particle->position [i]->z};
+ DrawBillboard (camera, texture, vector, 1, RED);
+ }
+
+ EndBlendMode ();
+
+ EndMode3D();
+
+ DrawText (TextFormat ("count = %i", particle->count), 0, 0, 4, RED);
+
+ EndDrawing ();
+
+ particle_synchronize (particle, 60);
+ }
+
+ CloseWindow ();
+
+ particle = particle_deinitialize (particle);
+
+ return (0);
+}
--- /dev/null
+/// _ _
+/// __ ____ _ ___| |__ (_)_ __ ___
+/// \ \/ / _` |/ __| '_ \| | '_ \ / _ \
+/// > < (_| | (__| | | | | | | | __/
+/// /_/\_\__,_|\___|_| |_|_|_| |_|\___|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xachine - Minimalistic statical x86_64, 32-bit, ELF64, GEENOO/Leenoocks bytecode assembler following IA32e.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#define elf_main_header_size (0x40)
+#define elf_text_sector_size (0x38)
+#define elf_data_sector_size (0x38)
+
+#define elf_header_size (elf_main_header_size + elf_text_sector_size + elf_data_sector_size)
+
+typedef enum {
+ operand_relative, operand_register, operand_memory, operand_immediate,
+ operand_count
+} operand_enumeration;
+
+typedef enum {
+ operation_memory, operation_relative, operation_number, operation_string,
+ operation_add, operation_or, operation_add_carry, operation_subtract_carry,
+ operation_and, operation_subtract, operation_exclusive_or, operation_compare,
+ operation_increment, operation_decrement, operation_not, operation_negate,
+ operation_unsigned_multiply, operation_signed_multiply, operation_unsigned_divide, operation_signed_divide,
+ operation_rotate_left, operation_rotate_right, operation_rotate_left_carry, operation_rotate_right_carry,
+ operation_shift_left_sign, operation_shift_right, operation_shift_left, operation_shift_right_sign,
+ operation_jump_overflow, operation_jump_not_overflow, operation_jump_below, operation_jump_above_equal,
+ operation_jump_equal, operation_jump_not_equal, operation_jump_below_equal, operation_jump_above,
+ operation_jump_sign, operation_jump_not_sign, operation_jump_parity_even, operation_jump_parity_odd,
+ operation_jump_lesser, operation_jump_greater_equal, operation_jump_lesser_equal, operation_jump_greater,
+ operation_none, operation_return_near, operation_system_call, operation_call,
+ operation_jump, operation_move,
+ operation_count
+} operation_enumeration;
+
+#ifdef use_debug_printing
+
+static const char * operand_name [operand_count] = {
+ "rel", "reg", "mem", "imm"
+};
+
+static const char * operation_name [operation_count] = {
+ "asmmem", "asmrel", "asmnum", "asmstr",
+ "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp",
+ "inc", "dec", "not", "neg", "mul", "imul", "div", "idiv",
+ "rol", "ror", "rcl", "rcr", "sal", "shr", "shl", "sar",
+ "jo", "jno", "jb", "jae", "je", "jne", "jbe", "ja",
+ "js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg",
+ "nop", "ret", "syscall", "call", "jmp", "mov"
+};
+
+#endif
+
+static uint main_entry_point = 0;
+static uint text_sector_size = 0;
+static uchar * text_sector_byte = null;
+static uint data_sector_size = 0; // This is unused, and it should be used...
+static uchar * data_sector_byte = null; // This is unused, and it should be used...
+
+static uint empty_count = 1;
+static uint empty_holes = 1;
+static uint * empty_array = null;
+static uint * empty_imbue = null;
+static uint * empty_store = null;
+
+static uchar elf_main_header_byte [elf_main_header_size] = { // These should be done properly...
+ 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00,
+ 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static uchar elf_text_sector_byte [elf_text_sector_size] = {
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static uchar elf_data_sector_byte [elf_data_sector_size] = {
+ 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static bool register_register (uint to, uint from) { return ((to == operand_register) && (from == operand_register)); }
+static bool register_memory (uint to, uint from) { return ((to == operand_register) && (from == operand_memory)); }
+static bool register_immediate (uint to, uint from) { return ((to == operand_register) && (from == operand_immediate)); }
+static bool memory_register (uint to, uint from) { return ((to == operand_memory) && (from == operand_register)); }
+static bool memory_immediate (uint to, uint from) { return ((to == operand_memory) && (from == operand_immediate)); }
+static bool register_relative (uint to, uint from) { return ((to == operand_register) && (from == operand_relative)); }
+
+static uint absolute (void) { return (0x4010b0 - text_sector_size - 4); }
+static uint relative (void) { return (0x1000 - text_sector_size - 4); }
+
+static void replace (uchar * destination, uchar * source, ulong size) {
+ for (--size; size >= 0; --size) {
+ destination [size] = source [size];
+ }
+}
+
+static void inset (bool when, uchar data) {
+ text_sector_byte [text_sector_size] = data;
+
+ text_sector_size += (uint) when;
+}
+
+static void inset_immediate (bool when, uint data) {
+ inset (when, (data >> 0) & 0xff);
+ inset (when, (data >> 8) & 0xff);
+ inset (when, (data >> 16) & 0xff);
+ inset (when, (data >> 24) & 0xff);
+}
+
+static void inset_memory (bool when, uint data, uint base) {
+ empty_array [empty_holes] = text_sector_size;
+ empty_imbue [empty_holes] = data;
+
+ empty_holes += when;
+
+ inset_immediate (when, base);
+}
+
+static void inset_relative (bool when, uint data, uint base) {
+ empty_array [empty_holes] = 0;
+ empty_imbue [empty_holes] = data;
+
+ empty_holes += when;
+
+ inset_immediate (when, base);
+}
+
+static uint mc0 (uint code, uint base) {
+ return (0xc0 + 0x01 * (code % 8) + 0x08 * (base % 8));
+}
+
+static uint m05 (uint code) {
+ return (0x05 + 0x08 * code);
+}
+
+static uint store_relative (const uint * array) {
+ const uint relative = array [1];
+#ifdef use_debug_printing
+ print ("/3asmrel/- %i", relative);
+#endif
+ empty_array [empty_holes] = text_sector_size;
+ empty_imbue [empty_holes] = relative;
+
+ ++empty_holes;
+
+ return 1;
+}
+
+static uint store_memory (const uint * array) {
+ const uint memory = array [1];
+#ifdef use_debug_printing
+ print ("/3asmmem/- %i", memory);
+#endif
+ empty_store [memory] = text_sector_size;
+
+ ++empty_count;
+
+ return 1;
+}
+
+static uint store_number (const uint * array) {
+ const uint amount = array [1];
+
+#ifdef use_debug_printing
+ print ("/3asmnum/- %i", amount);
+#endif
+ for (uint index = 0; index < amount; ++index) {
+ inset_immediate (true, array [2 + index]);
+ }
+
+ return amount + 1;
+}
+
+static uint store_string (const uint * array) {
+ const uint amount = array [1];
+
+#ifdef use_debug_printing
+ print ("/3asmstr/- %i", amount);
+#endif
+ for (uint index = 0; index < amount; ++index) {
+ inset (true, array [2 + index]);
+ }
+
+ return amount + 1;
+}
+
+static uint build_double (const uint * array) {
+ const uint operation = array [0];
+ const uint to = array [1];
+ const uint destination = array [2];
+ const uint from = array [3];
+ const uint source = array [4];
+#ifdef use_debug_printing
+ print ("/3%s/- /6%s/- %i /6%s/- %i", operation_name [operation], operand_name [to], destination, operand_name [from], source);
+#endif
+ inset (register_immediate (to, from), 0x81);
+
+ // Seriously, what the fuck...?
+ inset (true, 0x01 + 0x08 * (operation - operation_add) +
+ destination * (register_immediate (to, from)) +
+ 0x01 * register_immediate (to, from) +
+ 0x02 * register_memory (to, from) +
+ 0x04 * memory_immediate (to, from) +
+ 0xc0 * register_immediate (to, from));
+
+ inset (register_register (to, from), mc0 (destination, source));
+
+ inset (register_memory (to, from), m05 (destination));
+ inset (memory_register (to, from), m05 (source));
+
+ inset_memory (register_memory (to, from), source, relative ());
+
+ inset_immediate (register_immediate (to, from), source);
+
+ inset_memory (memory_register (to, from), destination, relative ());
+ inset_memory (memory_immediate (to, from), destination, relative ());
+
+ inset_immediate (memory_immediate (to, from), source);
+
+ inset_memory (register_relative (to, from), source, absolute ());
+
+ return 4;
+}
+
+static uint build_single (const uint * array) {
+ const uint operation = array [0];
+ const uint to = array [1];
+ const uint destination = array [2];
+#ifdef use_debug_printing
+ print ("/3%s/- /6%s/- %i", operation_name [operation], operand_name [to], destination);
+#endif
+ inset (true, 0xf7 + 0x08 * ((operation == operation_increment) || (operation == operation_decrement)));
+ inset (to == operand_register, 0xc0 + 0x08 * (operation - operation_increment) + 0x01 * destination);
+ inset (to == operand_memory, 0x05 + 0x08 * (operation - operation_increment));
+
+ inset_memory (to == operand_memory, destination, relative ());
+
+ return 2;
+}
+
+static uint build_shift (const uint * array) {
+ const uint operation = array [0];
+ const uint to = array [1];
+ const uint destination = array [2];
+ const uint offset = array [3];
+#ifdef use_debug_printing
+ print ("/3%s/- /6%s/- %i /cimm/- %i", operation_name [operation], operand_name [to], destination, offset);
+#endif
+ inset (true, 0xc1);
+
+ inset (to == operand_register, 0x05 + 0x08 * (operation - operation_rotate_left));
+ inset (to == operand_memory, 0xc0 + 0x08 * (operation - operation_rotate_left));
+
+ inset_memory (to == operand_memory, destination, relative ());
+
+ inset (true, offset);
+
+ return 3;
+}
+
+static uint build_static_1 (const uint * array) {
+ const uint operation = array [0];
+#ifdef use_debug_printing
+ print ("/3%s/-", operation_name [operation]);
+#endif
+ switch (operation) {
+ case operation_none: inset (true, 0x90); break;
+ case operation_return_near: inset (true, 0xc3); break;
+ case operation_system_call: inset (true, 0x0f); inset (true, 0x05); break;
+ default: break;
+ }
+
+ return 0;
+}
+
+static uint build_jump_if (const uint * array) {
+ const uint operation = array [0];
+ const uint location = array [1];
+#ifdef use_debug_printing
+ print ("/3%s/- %i", operation_name [operation], location);
+#endif
+ inset (true, 0x0f);
+ inset (true, 0x80 + operation - operation_jump_overflow);
+
+ inset_memory (true, location, -text_sector_size - 4);
+
+ return 2;
+}
+
+static uint build_jump (const uint * array) {
+ const uint to = array [1];
+ const uint destination = array [2];
+#ifdef use_debug_printing
+ print ("/3jmp/- /6%s/- %i", operand_name [to], destination);
+#endif
+ inset (to == operand_register, 0xff);
+ inset (to == operand_register, 0xe0 + 0x01 * destination);
+ inset (to == operand_relative, 0xe9);
+
+ inset_memory (to == operand_relative, destination, -text_sector_size - 4);
+
+ return 2;
+}
+
+static uint build_move (const uint * array) {
+ const uint to = array [1];
+ const uint destination = array [2];
+ const uint from = array [3];
+ const uint source = array [4];
+#ifdef use_debug_printing
+ print ("/3mov/- /6%s/- %i /6%s/- %i", operand_name [to], destination, operand_name [from], source);
+#endif
+ inset (register_register (to, from), 0x89);
+ inset (memory_register (to, from), 0x8b);
+ inset (register_memory (to, from), 0x89);
+ inset (memory_register (to, from), m05 (destination));
+ inset (register_memory (to, from), m05 (source));
+
+ inset (register_register (to, from), mc0 (destination, source));
+
+ inset ((to == operand_register) && ((from == operand_immediate) || (from == operand_relative)), 0xb8 + 0x01 * destination);
+
+ inset (memory_immediate (to, from), 0xc7);
+
+ inset_memory (register_memory (to, from), source, relative ());
+ inset_memory (memory_register (to, from), destination, relative ());
+ inset_memory (memory_immediate (to, from), destination, relative ());
+ inset_memory (register_relative (to, from), source, 0x4010b0);
+
+ inset_immediate (register_immediate (to, from), source);
+ inset_immediate (memory_immediate (to, from), source);
+
+ return 4;
+}
+
+static uint build_call (const uint * array) {
+ const uint from = array [1];
+ const uint source = array [2];
+#ifdef use_debug_printing
+ print ("/3call/- /6%s/- %i", operand_name [from], source);
+#endif
+ inset (from == operand_relative, 0xe8);
+ inset (from == operand_register, 0xff);
+ inset (from == operand_register, 0xd0 + 0x01 * source);
+
+ inset_memory (from == operand_relative, source, -text_sector_size - 4);
+
+ return 2;
+}
+
+static uint (* build_instruction [operation_count]) (const uint * array) = {
+ store_memory, // operation_memory : LABEL
+ store_relative, // operation_relative : "IMPLEMENTED"
+ store_number,
+ store_string,
+ build_double, build_double, build_double, build_double, build_double, build_double, build_double, build_double,
+ build_single, build_single, build_single, build_single, build_single, build_single, build_single, build_single,
+ build_shift, build_shift, build_shift, build_shift, build_shift, build_shift, build_shift, build_shift,
+ build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if,
+ build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if,
+ build_static_1, build_static_1, build_static_1, build_call, build_jump, build_move
+};
+
+static void assemble (uint count, const uint * array, uint external_memory, uint internal_memory) {
+ text_sector_byte = arena_add (external_memory * sizeof (* text_sector_byte));
+ data_sector_byte = arena_add (external_memory * sizeof (* text_sector_byte));
+
+ empty_array = arena_add (internal_memory * sizeof (* empty_array));
+ empty_imbue = arena_add (internal_memory * sizeof (* empty_imbue));
+ empty_store = arena_add (internal_memory * sizeof (* empty_store));
+
+ for (uint index = 0; index < count; ++index) {
+ const uint size = text_sector_size;
+
+ uchar byte = 0;
+#ifdef use_debug_nopping
+ inset (array [index] > operation_string, 0x90);
+#endif
+ index += build_instruction [array [index]] (& array [index]);
+#ifdef use_debug_printing
+ print (" /0--/- ");
+ for (byte = size; byte < text_sector_size; ++byte) {
+ print ("/5%s/- ", format_to_string ((uchar) text_sector_byte [byte], false, 16, 2, '0'));
+ }
+ print ("\n");
+#endif
+ }
+
+ main_entry_point = empty_store [0];
+
+ for (uint index = 1; index < empty_holes; ++index) {
+ uint set = 0;
+ uint get = empty_array [index];
+
+ replace ((uchar *) & set, & text_sector_byte [get], sizeof (set));
+
+ set += empty_store [empty_imbue [index]];
+
+ replace (& text_sector_byte [get], (uchar *) & set, sizeof (get));
+ }
+}
+
+static void elf_main_header (uint entry_point, bool has_program, bool for_linux, bool for_x86_64) {
+ uint enter = entry_point + 0x4000b0;
+
+ elf_main_header_byte [16] = (has_program) ? 0x02 : 0x03;
+ elf_main_header_byte [ 7] = (for_linux) ? 0x03 : 0x00;
+ elf_main_header_byte [18] = (for_x86_64) ? 0x3e : 0x00;
+
+ memory_copy (& elf_main_header_byte [24], & enter, sizeof (enter));
+}
+
+static void elf_text_sector (uint text_size, uint data_size) {
+ uint text = elf_header_size + text_size - data_size;
+
+ memory_copy (& elf_text_sector_byte [32], & text, sizeof (text));
+ memory_copy (& elf_text_sector_byte [40], & text, sizeof (text));
+}
+
+static void elf_data_sector (uint text_size, uint data_size) {
+ uint data = data_size;
+ uint core = elf_header_size + text_size - data_size;
+ uint move = 0x401000 + core;
+
+ memory_copy (& elf_data_sector_byte [ 8], & core, sizeof (core));
+ memory_copy (& elf_data_sector_byte [16], & move, sizeof (move));
+ memory_copy (& elf_data_sector_byte [24], & move, sizeof (move));
+ memory_copy (& elf_data_sector_byte [32], & data, sizeof (data));
+ memory_copy (& elf_data_sector_byte [40], & data, sizeof (data));
+}
--- /dev/null
+/// __ ____ _ _ __ __ _ _ _ __ _ __ _ ___
+/// \ \/ / _` | '_ \ / _` | | | |/ _` |/ _` |/ _ \
+/// > < (_| | | | | (_| | |_| | (_| | (_| | __/
+/// /_/\_\__,_|_| |_|\__, |\__,_|\__,_|\__, |\___|
+/// |___/ |___/
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xanguage - Syntax definitions of programming languages that I care about (and some that I don't care about).
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+typedef enum {
+ language_common, language_ada, language_c, language_cpp,
+ language_d, language_eaxhla, language_flat, language_fortran,
+ language_pascal, language_python, language_go, language_lua,
+ language_bash, language_haskell, language_valgrind,
+ language_count
+} language_enumeration;
+
+typedef struct {
+ uint comment_colour;
+ uint processor_colour;
+ uint character_colour;
+ uint string_colour;
+ uint keyword_colour;
+ uint type_colour;
+ uint bracket_colour;
+ uint operator_colour;
+ uint number_colour;
+ uint lowercase_colour;
+ uint uppercase_colour;
+ uint underscore_colour;
+ uint register_colour;
+ uint extension_colour;
+ uint fatal_colour;
+ uint comment_effect;
+ uint processor_effect;
+ uint character_effect;
+ uint string_effect;
+ uint keyword_effect;
+ uint type_effect;
+ uint bracket_effect;
+ uint operator_effect;
+ uint number_effect;
+ uint lowercase_effect;
+ uint uppercase_effect;
+ uint underscore_effect;
+ uint register_effect;
+ uint extension_effect;
+ uint fatal_effect;
+} language_structure;
+
+#include <xolatile/xanguage/common.h>
+#include <xolatile/xanguage/ada.h>
+#include <xolatile/xanguage/c.h>
+#include <xolatile/xanguage/c++.h>
+#include <xolatile/xanguage/d.h>
+#include <xolatile/xanguage/eaxhla.h>
+#include <xolatile/xanguage/flat.h>
+#include <xolatile/xanguage/fortran.h>
+#include <xolatile/xanguage/pascal.h>
+#include <xolatile/xanguage/python.h>
+#include <xolatile/xanguage/go.h>
+#include <xolatile/xanguage/lua.h>
+#include <xolatile/xanguage/bash.h>
+#include <xolatile/xanguage/haskell.h>
+#include <xolatile/xanguage/valgrind.h>
+
+static language_structure * language_initialize (bool true_colour) {
+ language_structure * language = allocate (sizeof (* language));
+
+ if (true_colour == true) {
+ language->comment_colour = 0xff777777u;
+ language->processor_colour = 0xff3377aau;
+ language->character_colour = 0xff7733ccu;
+ language->string_colour = 0xffcc3377u;
+ language->keyword_colour = 0xff33cceeu;
+ language->type_colour = 0xff55cceeu;
+ language->bracket_colour = 0xffee5533u;
+ language->operator_colour = 0xffeeaa33u;
+ language->number_colour = 0xffee33aau;
+ language->lowercase_colour = 0xffccccccu;
+ language->uppercase_colour = 0xffeeeeeeu;
+ language->underscore_colour = 0xffaaaaaau;
+ language->register_colour = 0xff5577aau;
+ language->extension_colour = 0xff55aaccu;
+ language->fatal_colour = 0xffcc7755u;
+ } else {
+ language->comment_colour = colour_grey;
+ language->processor_colour = colour_cyan;
+ language->character_colour = colour_pink;
+ language->string_colour = colour_pink;
+ language->keyword_colour = colour_yellow;
+ language->type_colour = colour_yellow;
+ language->bracket_colour = colour_blue;
+ language->operator_colour = colour_cyan;
+ language->number_colour = colour_pink;
+ language->lowercase_colour = colour_white;
+ language->uppercase_colour = colour_white;
+ language->underscore_colour = colour_white;
+ language->register_colour = colour_cyan;
+ language->extension_colour = colour_yellow;
+ language->fatal_colour = colour_red;
+ language->comment_effect = effect_bold;
+ language->processor_effect = effect_italic;
+ language->character_effect = effect_bold;
+ language->string_effect = effect_normal;
+ language->keyword_effect = effect_bold;
+ language->type_effect = effect_normal;
+ language->bracket_effect = effect_bold;
+ language->operator_effect = effect_normal;
+ language->number_effect = effect_bold;
+ language->lowercase_effect = effect_normal;
+ language->uppercase_effect = effect_bold;
+ language->underscore_effect = effect_italic;
+ language->register_effect = effect_italic;
+ language->extension_effect = effect_italic;
+ language->fatal_effect = effect_bold;
+ }
+
+ return (language);
+}
+
+static language_structure * language_deinitialize (language_structure * language) {
+ return (deallocate (language));
+}
+
+static void (* language_highlighter (language_enumeration language)) (language_structure * language, syntax_structure * syntax) {
+ static const void (* highlighter [language_count]) (language_structure * language, syntax_structure * syntax) = {
+ language_highlight_common, language_highlight_ada, language_highlight_c, language_highlight_cpp,
+ language_highlight_d, language_highlight_eaxhla, language_highlight_flat, language_highlight_fortran,
+ language_highlight_pascal, language_highlight_python, language_highlight_go, language_highlight_lua,
+ language_highlight_bash, language_highlight_haskell, language_highlight_valgrind
+ };
+
+ fatal_failure (language >= language_count, "language_highlighter: Language index not in enumeration.");
+
+ return (highlighter [language]);
+}
+
+static char * language_short_option (language_enumeration language) {
+ static const char * short_option [language_count] = {
+ "-X", "-A", "-C", "-S", "-D", "-E", "-T", "-F", "-P", "-Y", "-G", "-L", "-B", "-H", "-V"
+ };
+
+ fatal_failure (language >= language_count, "language_short_option: Language index not in enumeration.");
+
+ return (short_option [language]);
+}
+
+static char * language_long_option (language_enumeration language) {
+ static const char * long_option [language_count] = {
+ "--common", "--ada", "--c", "--cpp", "--d", "--eaxhla", "--flat", "--fortran",
+ "--pascal", "--python", "--go", "--lua", "--bash", "--haskell", "--valgrind"
+ };
+
+ fatal_failure (language >= language_count, "language_long_option: Language index not in enumeration.");
+
+ return (long_option [language]);
+}
+
+static char * language_identifier (language_enumeration language) {
+ static const char * identifier [language_count] = {
+ "Common", "Ada", "C", "C++", "D", "EAXHLA", "Flat", "Fortran",
+ "Pascal", "Python", "Go", "Lua", "Bash", "Haskell", "Valgrind"
+ };
+
+ fatal_failure (language >= language_count, "language_identifier: Language index not in enumeration.");
+
+ return (identifier [language]);
+}
+
+static void language_conditionally_select (language_structure * language, syntax_structure * syntax, uint select) {
+ if (syntax->count == 0) {
+ if ((select == file_type_c_source) || (select == file_type_c_header)) {
+ language_highlight_c (language, syntax);
+ } else if ((select == file_type_ada_sexy_body) || (select == file_type_ada_specification)) {
+ language_highlight_ada (language, syntax);
+ } else if ((select == file_type_cpp_source) || (select == file_type_cpp_header)) {
+ language_highlight_cpp (language, syntax);
+ } else if (select == file_type_flat_assembly) {
+ language_highlight_flat (language, syntax);
+ } else if (select == file_type_fortran_90_source) {
+ language_highlight_fortran (language, syntax);
+ } else if (select == file_type_pascal_source) {
+ language_highlight_pascal (language, syntax);
+ } else if (select == file_type_eax_assembly) {
+ language_highlight_eaxhla (language, syntax);
+ } else if (select == file_type_python_script) {
+ language_highlight_python (language, syntax);
+ } else {
+ language_highlight_common (language, syntax);
+ }
+ }
+}
--- /dev/null
+static void language_highlight_ada (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/&|()\" \t\r\n";
+
+ const char * keywords [] = {
+ "abort", "else", "new", "return", "abs", "elsif", "not", "reverse",
+ "abstract", "end", "null", "accept", "entry", "select", "access", "of",
+ "separate", "aliased", "exit", "or", "some", "all", "others", "subtype",
+ "and", "for", "out", "array", "function", "at", "tagged", "generic",
+ "package", "task", "begin", "goto", "pragma", "body", "private", "then",
+ "type", "case", "in", "constant", "until", "is", "raise", "use",
+ "if", "declare", "range", "delay", "limited", "record", "when", "delta",
+ "loop", "rem", "while", "digits", "renames", "with", "do", "mod",
+ "requeue", "xor", "procedure", "protected", "interface", "synchronized", "exception", "overriding",
+ "terminate"
+ };
+
+ syntax_define (syntax, false, false, "--", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ syntax_define (syntax, true, false, "()", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+-*/&|'", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+}
--- /dev/null
+static void language_highlight_bash (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/%!&~^?|@#$()[]{}'\" \t\r\n";
+
+ const char * keywords [] = {
+ "exit", "set", "elif", "done", "in", "then", "function", "fi",
+ "if", "else", "do", "while", "for"
+ };
+
+ syntax_define (syntax, false, false, "#", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\0', language->string_colour, language->string_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\0', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+*-/%!&~^?|@#$", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_cpp (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n";
+
+ const char * keywords [] = {
+ "alignas", "alignof", "and", "asm", "auto", "break", "case",
+ "catch", "class", "compl", "concept", "const", "consteval", "constexpr",
+ "constinit", "continue", "decltype", "default", "delete", "do", "else",
+ "enum", "explicit", "export", "extern", "false", "for", "friend",
+ "goto", "if", "inline", "mutable", "namespace", "new",
+ "noexcept", "not", "nullptr", "operator", "or", "private", "protected", "public",
+ "reflexpr", "register", "requires", "return", "sizeof", "static",
+ "struct", "switch", "synchronized", "template", "this", "throw", "true", "try",
+ "typedef", "typeid", "typename", "union", "using", "virtual",
+ "volatile", "while", "xor", "final", "override", "import", "module"
+ };
+
+ const char * types [] = {
+ "void", "bool", "off_t", "va_list", "float", "double", "float_t", "double_t",
+ "char", "short", "int", "long", "uchar", "ushort", "uint", "ulong",
+ "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t",
+ "signed", "unsigned", "size_t", "ssize_t"
+ };
+
+ const char * commons [] = {
+ "std", "FILE", "DIR", "EOF", "va_arg", "va_start", "va_end", "va_copy"
+ };
+
+ syntax_define (syntax, false, false, "/*", "*/", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "//", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "#", "\n", '\\', language->processor_colour, language->processor_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (types); ++word) {
+ syntax_define (syntax, false, true, types [word], separators, '\0', language->type_colour, language->type_effect);
+ }
+
+ for (ulong word = 0; word < array_length (commons); ++word) {
+ syntax_define (syntax, false, true, commons [word], separators, '\0', language->extension_colour, language->extension_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+*-/%!&~^?|", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_c (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n";
+
+ const char * keywords [] = {
+ "register", "volatile", "auto", "const", "static", "extern", "if", "else",
+ "do", "while", "for", "continue", "switch", "case", "default", "break",
+ "enum", "union", "struct", "typedef", "goto", "return", "sizeof", "inline",
+ "restrict", "true", "false"
+ };
+
+ const char * types [] = {
+ "void", "bool", "off_t", "va_list", "float", "double", "float_t", "double_t",
+ "char", "short", "int", "long", "uchar", "ushort", "uint", "ulong",
+ "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t",
+ "signed", "unsigned", "size_t", "ssize_t"
+ };
+
+ const char * commons [] = {
+ "null", "NULL", "FILE", "DIR", "va_arg", "va_start", "va_end", "va_copy",
+ "alignas", "alignof", "offsetof", "typeof", "EOF", "ABS", "MIN", "MAX",
+ "ARRAYSIZE", "SWAP", "UNUSED", "UNREACHABLE", "STRINGIFY", "CONCAT", "assert", "static_assert"
+ };
+
+ syntax_define (syntax, false, false, "/*", "*/", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "//", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "#", "\n", '\\', language->processor_colour, language->processor_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (types); ++word) {
+ syntax_define (syntax, false, true, types [word], separators, '\0', language->type_colour, language->type_effect);
+ }
+
+ for (ulong word = 0; word < array_length (commons); ++word) {
+ syntax_define (syntax, false, true, commons [word], separators, '\0', language->extension_colour, language->extension_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+*-/%!&~^?|", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_common (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+*-/%!&~^?|()[]{}'\"@#$` \t\r\n";
+
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+*-/%!&~^?|@#$`", "", '\0', language->operator_colour, language->operator_effect);
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+}
--- /dev/null
+static void language_highlight_d (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/%!&~^?|@()[]{}'\"` \t\r\n";
+
+ const char * keywords [] = {
+ "abstract", "alias", "align", "asm", "assert", "auto", "body", "bool",
+ "break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat",
+ "char", "class", "const", "continue", "creal", "dchar", "debug", "default",
+ "delegate", "delete", "deprecated", "do", "double", "else", "enum", "export",
+ "extern", "false", "final", "finally", "float", "for", "foreach", "with",
+ "function", "goto", "idouble", "if", "ifloat", "immutable", "import", "in",
+ "inout", "int", "interface", "invariant", "ireal", "is", "lazy", "long",
+ "macro", "mixin", "module", "new", "nothrow", "null", "out", "override",
+ "package", "pragma", "private", "protected", "public", "pure", "real", "ref",
+ "return", "scope", "shared", "short", "static", "struct", "super", "switch",
+ "synchronized", "template", "this", "throw", "true", "try", "typeid", "typeof",
+ "ubyte", "ucent", "uint", "ulong", "union", "unittest", "ushort", "version",
+ "void", "wchar", "while", "foreach_reverse"
+ };
+
+ const char * types [] = {
+ "byte", "ubyte", "short", "ushort", "int", "uint", "long", "ulong",
+ "cent", "ucent", "char", "wchar", "dchar", "float", "double", "real",
+ "ifloat", "idouble", "ireal", "cfloat", "cdouble", "creal", "void", "bool",
+ "string"
+ };
+
+ syntax_define (syntax, false, false, "/+", "+/", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "/*", "*/", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "//", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+ syntax_define (syntax, false, false, "`", "`", '\0', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (types); ++word) {
+ syntax_define (syntax, false, true, types [word], separators, '\0', language->type_colour, language->type_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+*-/%!&~^?|@", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_eaxhla (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,+-*/[]<>=; \t\r\n";
+
+ const char * declarations [] = {
+ "program", "procedure", "machine", "library", "fast", "unix", "begin", "end",
+ "if", "then", "else", "repeat", "break", "continue", "until", "exit",
+ "fastcall", "shell", "alias", "macro", "scope", "unscope", "use", "include"
+ };
+
+ const char * types [] = {
+ "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64",
+ "f32", "f64", "f80", "v0", "s128", "u128", "s256", "u256",
+ "s512", "u512"
+ };
+
+ const char * instructions [] = {
+ "jnpe", "jpo", "jnpo", "jpe", "jnb", "jae", "jnbe", "ja",
+ "jna", "jbe", "jnae", "jb", "jnl", "jge", "jnle", "jg",
+ "jng", "jle", "jnge", "jl", "cmovng", "cmovle", "cmovnge", "cmovl",
+ "cmovnpe", "cmovpo", "cmovnpo", "cmovpe", "cmovnb", "cmovae", "cmovnbe", "cmova",
+ "cmovna", "cmovbe", "cmovnae", "cmovb", "cmovnl", "cmovge", "cmovnle", "cmovg",
+ "setnpe", "setpo", "setnpo", "setpe", "setnb", "setae", "setnbe", "seta",
+ "setna", "setbe", "setnae", "setb", "setnl", "setge", "setnle", "setg",
+ "setng", "setle", "setnge", "setl", "enter", "call", "jmp", "mov",
+ "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp",
+ "inc", "dec", "not", "neg", "mul", "imul", "div", "idiv",
+ "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
+ "rol", "ror", "rcl", "rcr", "sal", "shr", "shl", "sar",
+ "nop", "retn", "retf", "leave", "popf", "pushf", "in", "out",
+ "syscall", "cpuid", "fnop", "fchs", "fabs", "ftst", "fxam", "fld1",
+ "fldl2t", "fldl2e", "fldpi", "fldlg2", "fldln2", "fldz", "f2xm1", "fyl2x",
+ "fptan", "fpatan", "fxtract", "fprem1", "fdecstp", "fincstp", "fprem", "fyl2xp1",
+ "fsqrt", "fsincos", "frndint", "fscale", "fsin", "fcos", "pop", "push",
+ "bswap", "bsf", "bsr", "loop", "loope", "loopne"
+ };
+
+ const char * registers [] = {
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
+ "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
+ "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
+ "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w",
+ "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
+ "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
+ };
+
+ int word;
+
+ syntax_define (syntax, false, false, "#", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "---", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "//", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (declarations); ++word) {
+ syntax_define (syntax, false, true, declarations [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (types); ++word) {
+ syntax_define (syntax, false, true, types [word], separators, '\0', language->type_colour, language->type_effect);
+ }
+
+ for (ulong word = 0; word < array_length (instructions); ++word) {
+ syntax_define (syntax, false, true, instructions [word], separators, '\0', language->extension_colour, language->extension_effect);
+ }
+
+ for (ulong word = 0; word < array_length (registers); ++word) {
+ syntax_define (syntax, false, true, registers [word], separators, '\0', language->register_colour, language->register_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,+*-/%$<>=;", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_flat (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,+-=:;(){}[]%$<> \t\r\n";
+
+ const char * declarations [] = {
+ "format", "executable", "readable", "writable", "segment", "sector", "entry", "macro",
+ "db", "dw", "dd", "dq", "rb", "rw", "rd", "rq"
+ };
+
+ const char * instructions [] = {
+ "mov", "movabs", "movapd", "movaps", "movebe", "movsd", "movsx", "movzx",
+ "movsxd", "movd", "movq", "movs", "movsb", "movsw", "movsd", "movsq",
+ "cmovmp", "cmovrcxz", "cmovc", "cmovnc", "cmove", "cmovne", "cmovz", "cmovnz",
+ "cmovg", "cmovng", "cmovge", "cmovnge", "cmovl", "cmovnl", "cmovle", "cmovnle",
+ "cmova", "cmovna", "cmovae", "cmovnae", "cmovb", "cmovnb", "cmovbe", "cmovnbe",
+ "cmovs", "cmovns", "cmovo", "cmovno", "cmovp", "cmovnp", "cmovpo", "cmovpe",
+ "cmp", "cmps", "cmpsb", "cmpsw", "cmpsd", "cmpsq", "cmpxchg", "lea",
+ "monitor", "cpuid", "in", "out", "syscall", "sysenter", "sysret", "sysexit",
+ "swap", "bswap", "pop", "push", "call", "ret", "enter", "leave",
+ "and", "or", "not", "neg", "sal", "sar", "shl", "shr",
+ "inc", "dec", "add", "sub", "mul", "div", "imul", "idiv",
+ "nop", "fnop", "adc", "sbb", "aaa", "aas", "aam", "aad",
+ "jmp", "jrcxz", "jc", "jnc", "je", "jne", "jz", "jnz",
+ "jg", "jng", "jge", "jnge", "jl", "jnl", "jle", "jnle",
+ "ja", "jna", "jae", "jnae", "jb", "jnb", "jbe", "jnbe",
+ "js", "jns", "jo", "jno", "jp", "jnp", "jpo", "jpe",
+ "rep", "repe", "repz", "repne", "repnz", "loop", "loope", "loopne"
+ };
+
+ const char * registers [] = {
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
+ "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
+ "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
+ "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w",
+ "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
+ "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b",
+ "ah", "ch", "dh", "bh"
+ };
+
+ int word;
+
+ syntax_define (syntax, false, false, ";", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->string_colour, language->string_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (declarations); ++word) {
+ syntax_define (syntax, false, true, declarations [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (instructions); ++word) {
+ syntax_define (syntax, false, true, instructions [word], separators, '\0', language->extension_colour, language->extension_effect);
+ }
+
+ for (ulong word = 0; word < array_length (registers); ++word) {
+ syntax_define (syntax, false, true, registers [word], separators, '\0', language->register_colour, language->register_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,+-=:;%$<>", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_fortran (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ",:<=>+-*/&()[]\"\' \t\r\n";
+
+ const char * keywords [] = {
+ "allocatable", "allocate", "associate", "backspace", "block", "call", "case", "common",
+ "contains", "cycle", "data", "deallocate", "d0", "do", "else", "elseif",
+ "end", "enddo", "endfile", "endif", "entry", "equivalence", "exit", "external",
+ "forall", "format", "function", "goto", "if", "implicit", "inquire", "intent",
+ "intrinsic", "module", "namelist", "none", "nullify", "only", "open", "optional",
+ "parameter", "pointer", "print", "private", "program", "public", "read", "recursive",
+ "return", "rewind", "save", "select", "sequence", "stop", "subroutine", "target",
+ "then", "to", "type", "use", "where", "write"
+ };
+
+ const char * types [] = {
+ "character", "integer", "logical", "real", "complex"
+ };
+
+ const char * subkeywords [] = {
+ ".and.", ".or.", ".not.", ".true.", ".false.", "in", "out", "len",
+ "dimension", "modulo", "advance"
+ };
+
+ syntax_define (syntax, false, false, "!", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (subkeywords); ++word) {
+ syntax_define (syntax, false, true, subkeywords [word], separators, '\0', language->processor_colour, language->processor_effect);
+ }
+
+ for (ulong word = 0; word < array_length (types); ++word) {
+ syntax_define (syntax, false, true, types [word], separators, '\0', language->type_colour, language->type_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ",:<=>+-*/&", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_go (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\"` \t\r\n";
+
+ const char * keywords [] = {
+ "break", "default", "func", "interface", "select", "case", "defer", "go",
+ "struct", "else", "goto", "package", "switch", "const", "var", "for",
+ "fallthrough", "if", "range", "type", "continue", "import", "return"
+ };
+
+ const char * types [] = {
+ "map", "uint", "int", "uintptr", "uint8", "uint16", "uint32", "uint64",
+ "int8", "int16", "int32", "int64", "float32", "float64", "complex64", "complex128",
+ "byte", "rune", "string", "chan", "bool"
+
+ };
+
+ const char * commons [] = {
+ "true", "false", "nil", "err"
+ };
+
+ syntax_define (syntax, false, false, "/*", "*/", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "//", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+ syntax_define (syntax, false, false, "`", "`", '\0', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (types); ++word) {
+ syntax_define (syntax, false, true, types [word], separators, '\0', language->type_colour, language->type_effect);
+ }
+
+ for (ulong word = 0; word < array_length (commons); ++word) {
+ syntax_define (syntax, false, true, commons [word], separators, '\0', language->extension_colour, language->extension_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+*-/%!&~^?|", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_haskell (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/%!@#$&~^?|()[]{}'\" \t\r\n";
+
+ const char * keywords [] = {
+ "case", "class", "data", "deriving", "do", "else", "if", "import",
+ "in", "infix", "infixl", "infixr", "instance", "let", "of", "module",
+ "newtype", "then", "type", "where"
+ };
+
+ const char * types [] = {
+ "Int", "Integer", "String", "Char", "Float", "Boolean"
+ };
+
+ syntax_define (syntax, false, false, "{-", "-}", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "--", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (types); ++word) {
+ syntax_define (syntax, false, true, types [word], separators, '\0', language->type_colour, language->type_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+*-/%!@#$&~^?|", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_lua (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/%~^#|()[]{}'\" \t\r\n";
+
+ const char * keywords [] = {
+ "and", "break", "do", "else", "elseif", "end", "false", "for",
+ "function", "if", "in", "local", "nil", "not", "or", "until",
+ "repeat", "return", "then", "true", "while"
+ };
+
+ const char * types [] = {
+ "boolean", "number", "string", "userdata", "function", "thread", "table"
+ };
+
+ const char * commons [] = {
+ "require", "print", "seek", "dofile", "loadfile", "assert", "rawset", "rawget",
+ "setfenv", "pairs", "ipairs", "tonumber", "tostring", "foreach", "setn", "getn",
+ "insert", "concat", "sort", "remove", "abs", "ceil", "floor", "log10",
+ "rad", "sqrt", "acos", "cos", "fmod", "max", "random", "tan",
+ "asin", "cosh", "frexp", "min", "randomseed", "tanh", "atan", "deg",
+ "ldexp", "modf", "sin", "atan2", "sinh", "exp", "log", "pow",
+ "open", "close", "read", "write", "input", "output", "format", "lines",
+ "upper", "lower", "find", "gfind", "match", "gmatch", "sub", "gsub",
+ "len", "rep", "char", "dump", "reverse", "byte"
+ };
+
+ syntax_define (syntax, false, false, "--[[", "]]", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "--", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (types); ++word) {
+ syntax_define (syntax, false, true, types [word], separators, '\0', language->type_colour, language->type_effect);
+ }
+
+ for (ulong word = 0; word < array_length (commons); ++word) {
+ syntax_define (syntax, false, true, commons [word], separators, '\0', language->extension_colour, language->extension_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+-*/%~^#|", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_pascal (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/&@#$%^()[] \t\r\n";
+
+ const char * keywords [] = {
+ "absolute", "and", "array", "asm", "begin", "case", "const", "constructor",
+ "destructor", "div", "do", "downto", "else", "end", "file", "for",
+ "function", "goto", "if", "in", "inherited", "inline", "interface", "xor",
+ "label", "mod", "nil", "not", "object", "of", "operator", "or",
+ "packed", "procedure", "program", "record", "reintroduce", "repeat", "self", "set",
+ "shl", "shr", "string", "then", "to", "type", "unit", "until",
+ "uses", "var", "while", "with"
+ };
+
+ syntax_define (syntax, false, false, "//", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "(*", "*)", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "{", "}", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '#', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ syntax_define (syntax, true, false, "[]()", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+-*/&@#$%^", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+}
--- /dev/null
+static void language_highlight_python (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/%!&~^?|()[]{}'\" \t\r\n";
+
+ const char * keywords [] = {
+ "and", "as", "assert", "break", "class", "continue", "def", "del",
+ "elif", "else", "except", "False", "finally", "for", "from", "global",
+ "if", "import", "in", "is", "labmda", "None", "nonlocal", "not",
+ "or", "pass", "raise", "return", "True", "try", "while", "with",
+ "yield", "async", "await"
+ };
+
+ const char * subkeywords [] = {
+ "abs", "all", "any", "apply", "ascii", "basestring", "bin", "bool",
+ "breakpoint", "buffer", "bytearray", "bytes", "callable", "chr", "classmethod", "cmp",
+ "coerce", "compile", "complex", "copyright", "credits", "delattr", "dict", "dir",
+ "divmod", "enumerate", "eval", "execfile", "exit", "file", "filter", "float",
+ "format", "frozenset", "getattr", "globals", "hasattr", "hash", "help", "hex",
+ "id", "input", "int", "intern", "isinstance", "issubclass", "iter", "len",
+ "license", "list", "locals", "long", "map", "max", "memoryview", "min",
+ "next", "object", "oct", "open", "ord", "pow", "property", "quit",
+ "range", "raw_input", "reduce", "reload", "repr", "reversed", "round", "set",
+ "setattr", "slice", "sorted", "staticmethod", "str", "sum", "super", "tuple",
+ "type", "unichr", "unicode", "vars", "xrange", "zip"
+ };
+
+ syntax_define (syntax, false, false, "#", "\n", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'''", "'''", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "\"\"\"", "\"\"\"", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "'", "'", '\\', language->character_colour, language->character_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separators, '\0', language->keyword_colour, language->keyword_effect);
+ }
+
+ for (ulong word = 0; word < array_length (subkeywords); ++word) {
+ syntax_define (syntax, false, true, subkeywords [word], separators, '\0', language->extension_colour, language->extension_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+*-/%!&~^?|", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", separators, '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->underscore_colour, language->underscore_effect);
+}
--- /dev/null
+static void language_highlight_valgrind (language_structure * language, syntax_structure * syntax) {
+ const char * separators = ".,:;<=>+-*/%!&~^?|@#$()[]{}'\" \t\r\n";
+
+ const char * titles [] = {
+ //~"exit", "set", "elif", "done", "in", "then", "function", "fi",
+ "HEAP", "LEAK", "ERROR", "SUMMARY"
+ };
+
+ syntax_define (syntax, false, false, "==", "==", '\0', language->comment_colour, language->comment_effect);
+ syntax_define (syntax, false, false, "\"", "\"", '\0', language->string_colour, language->string_effect);
+ syntax_define (syntax, false, false, "(", ")", '\0', language->lowercase_colour, language->lowercase_effect);
+ syntax_define (syntax, false, false, "0x", ":", '\0', language->string_colour, language->string_effect);
+
+ for (ulong word = 0; word < array_length (titles); ++word) {
+ syntax_define (syntax, false, true, titles [word], separators, '\0', language->fatal_colour, language->fatal_effect);
+ }
+
+ syntax_define (syntax, true, false, "()[]{}", "", '\0', language->bracket_colour, language->bracket_effect);
+ syntax_define (syntax, true, false, ".,:;<=>+*-/%!&~^?|@#$", "", '\0', language->operator_colour, language->operator_effect);
+
+ syntax_define (syntax, true, true, "0123456789", ": ()\t\r\n", '\0', language->number_colour, language->number_effect);
+ syntax_define (syntax, true, true, "abcdefghijklmnopqrstuvwxyz", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+ syntax_define (syntax, true, true, "_", separators, '\0', language->uppercase_colour, language->uppercase_effect);
+}
--- /dev/null
+# ADC — Add with Carry
+
+## Description
+
+Adds the destination operand (first operand), the source operand (second operand), and the carry (CF) flag and stores the result in the
+destination operand. The destination operand can be a register or a memory location; the source operand can be an immediate, a register, or a
+memory location. However, two memory operands cannot be used in one instruction. The state of the CF flag represents a carry from a previous
+addition. When an immediate value is used as an operand, it is sign-extended to the length of the destination operand format.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|------------------|-------|-------------|-------------|--------------------------------------------------------------------|
+| 14 ib | ADC AL, imm8 | I | Valid | Valid | Add with carry imm8 to AL. |
+| 15 iw | ADC AX, imm16 | I | Valid | Valid | Add with carry imm16 to AX. |
+| 15 id | ADC EAX, imm32 | I | Valid | Valid | Add with carry imm32 to EAX. |
+| REX.W + 15 id | ADC RAX, imm32 | I | Valid | N.E. | Add with carry imm32 sign extended to 64-bits to RAX. |
+| 80 /2 ib | ADC r/m8, imm8 | MI | Valid | Valid | Add with carry imm8 to r/m8. |
+| REX + 80 /2 ib | ADC r/m8*, imm8 | MI | Valid | N.E. | Add with carry imm8 to r/m8. |
+| 81 /2 iw | ADC r/m16, imm16 | MI | Valid | Valid | Add with carry imm16 to r/m16. |
+| 81 /2 id | ADC r/m32, imm32 | MI | Valid | Valid | Add with CF imm32 to r/m32. |
+| REX.W + 81 /2 id | ADC r/m64, imm32 | MI | Valid | N.E. | Add with CF imm32 sign extended to 64-bits to r/m64. |
+| 83 /2 ib | ADC r/m16, imm8 | MI | Valid | Valid | Add with CF sign-extended imm8 to r/m16. |
+| 83 /2 ib | ADC r/m32, imm8 | MI | Valid | Valid | Add with CF sign-extended imm8 into r/m32. |
+| REX.W + 83 /2 ib | ADC r/m64, imm8 | MI | Valid | N.E. | Add with CF sign-extended imm8 into r/m64. |
+| 10 /r | ADC r/m8, r8 | MR | Valid | Valid | Add with carry byte register to r/m8. |
+| REX + 10 /r | ADC r/m8*, r8* | MR | Valid | N.E. | Add with carry byte register to r/m64. |
+| 11 /r | ADC r/m16, r16 | MR | Valid | Valid | Add with carry r16 to r/m16. |
+| 11 /r | ADC r/m32, r32 | MR | Valid | Valid | Add with CF r32 to r/m32. |
+| REX.W + 11 /r | ADC r/m64, r64 | MR | Valid | N.E. | Add with CF r64 to r/m64. |
+| 12 /r | ADC r8, r/m8 | RM | Valid | Valid | Add with carry r/m8 to byte register. |
+| REX + 12 /r | ADC r8*, r/m8* | RM | Valid | N.E. | Add with carry r/m64 to byte register. |
+| 13 /r | ADC r16, r/m16 | RM | Valid | Valid | Add with carry r/m16 to r16. |
+| 13 /r | ADC r32, r/m32 | RM | Valid | Valid | Add with CF r/m32 to r32. |
+| REX.W + 13 /r | ADC r64, r/m64 | RM | Valid | N.E. | Add with CF r/m64 to r64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+The ADC instruction does not distinguish between signed or unsigned operands. Instead, the processor evaluates the result for both data types
+and sets the OF and CF flags to indicate a carry in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed
+result.
+
+The ADC instruction is usually executed as part of a multibyte or multiword addition in which an ADD instruction is followed by an ADC
+instruction.
+
+In 64-bit mode, the instruction's default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional
+registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this
+section for encoding data and limits.
--- /dev/null
+# ADD — Add
+
+## Description
+
+Adds the destination operand (first operand) and the source operand (second operand) and then stores the result in the destination operand. The
+destination operand can be a register or a memory location; the source operand can be an immediate, a register, or a memory location. However,
+two memory operands cannot be used in one instruction. When an immediate value is used as an operand, it is sign-extended to the length of the
+destination operand format.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|------------------|-------|-------------|-------------|--------------------------------------------------------------------|
+| 04 ib | ADD AL, imm8 | I | Valid | Valid | Add imm8 to AL. |
+| 05 iw | ADD AX, imm16 | I | Valid | Valid | Add imm16 to AX. |
+| 05 id | ADD EAX, imm32 | I | Valid | Valid | Add imm32 to EAX. |
+| REX.W + 05 id | ADD RAX, imm32 | I | Valid | N.E. | Add imm32 sign-extended to 64-bits to RAX. |
+| 80 /0 ib | ADD r/m8, imm8 | MI | Valid | Valid | Add imm8 to r/m8. |
+| REX + 80 /0 ib | ADD r/m8*, imm8 | MI | Valid | N.E. | Add sign-extended imm8 to r/m64. |
+| 81 /0 iw | ADD r/m16, imm16 | MI | Valid | Valid | Add imm16 to r/m16. |
+| 81 /0 id | ADD r/m32, imm32 | MI | Valid | Valid | Add imm32 to r/m32. |
+| REX.W + 81 /0 id | ADD r/m64, imm32 | MI | Valid | N.E. | Add imm32 sign-extended to 64-bits to r/m64. |
+| 83 /0 ib | ADD r/m16, imm8 | MI | Valid | Valid | Add sign-extended imm8 to r/m16. |
+| 83 /0 ib | ADD r/m32, imm8 | MI | Valid | Valid | Add sign-extended imm8 to r/m32. |
+| REX.W + 83 /0 ib | ADD r/m64, imm8 | MI | Valid | N.E. | Add sign-extended imm8 to r/m64. |
+| 00 /r | ADD r/m8, r8 | MR | Valid | Valid | Add r8 to r/m8. |
+| REX + 00 /r | ADD r/m8*, r8* | MR | Valid | N.E. | Add r8 to r/m8. |
+| 01 /r | ADD r/m16, r16 | MR | Valid | Valid | Add r16 to r/m16. |
+| 01 /r | ADD r/m32, r32 | MR | Valid | Valid | Add r32 to r/m32. |
+| REX.W + 01 /r | ADD r/m64, r64 | MR | Valid | N.E. | Add r64 to r/m64. |
+| 02 /r | ADD r8, r/m8 | RM | Valid | Valid | Add r/m8 to r8. |
+| REX + 02 /r | ADD r8*, r/m8* | RM | Valid | N.E. | Add r/m8 to r8. |
+| 03 /r | ADD r16, r/m16 | RM | Valid | Valid | Add r/m16 to r16. |
+| 03 /r | ADD r32, r/m32 | RM | Valid | Valid | Add r/m32 to r32. |
+| REX.W + 03 /r | ADD r64, r/m64 | RM | Valid | N.E. | Add r/m64 to r64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+The ADD instruction performs integer addition. It evaluates the result for both signed and unsigned integer operands and sets the CF and OF
+flags to indicate a carry (overflow) in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed result.
+
+In 64-bit mode, the instruction's default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional
+registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this
+section for encoding data and limits.
--- /dev/null
+# AND — Logical And
+
+## Description
+
+Performs a bitwise AND operation on the destination (first) and source (second) operands and stores the result in the destination operand
+location. The source operand can be an immediate, a register, or a memory location; the destination operand can be a register or a memory
+location. However, two memory operands cannot be used in one instruction. Each bit of the result is set to 1 if both corresponding bits of the
+first and second operands are 1; otherwise, it is set to 0.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|------------------|-------|-------------|-------------|--------------------------------------------------------------------|
+| 24 ib | AND AL, imm8 | I | Valid | Valid | AL AND imm8. |
+| 25 iw | AND AX, imm16 | I | Valid | Valid | AX AND imm16. |
+| 25 id | AND EAX, imm32 | I | Valid | Valid | EAX AND imm32. |
+| REX.W + 25 id | AND RAX, imm32 | I | Valid | N.E. | RAX AND imm32 sign-extended to 64-bits. |
+| 80 /4 ib | AND r/m8, imm8 | MI | Valid | Valid | r/m8 AND imm8. |
+| REX + 80 /4 ib | AND r/m8*, imm8 | MI | Valid | N.E. | r/m8 AND imm8. |
+| 81 /4 iw | AND r/m16, imm16 | MI | Valid | Valid | r/m16 AND imm16. |
+| 81 /4 id | AND r/m32, imm32 | MI | Valid | Valid | r/m32 AND imm32. |
+| REX.W + 81 /4 id | AND r/m64, imm32 | MI | Valid | N.E. | r/m64 AND imm32 sign extended to 64-bits. |
+| 83 /4 ib | AND r/m16, imm8 | MI | Valid | Valid | r/m16 AND imm8 (sign-extended). |
+| 83 /4 ib | AND r/m32, imm8 | MI | Valid | Valid | r/m32 AND imm8 (sign-extended). |
+| REX.W + 83 /4 ib | AND r/m64, imm8 | MI | Valid | N.E. | r/m64 AND imm8 (sign-extended). |
+| 20 /r | AND r/m8, r8 | MR | Valid | Valid | r/m8 AND r8. |
+| REX + 20 /r | AND r/m8*, r8* | MR | Valid | N.E. | r/m64 AND r8 (sign-extended). |
+| 21 /r | AND r/m16, r16 | MR | Valid | Valid | r/m16 AND r16. |
+| 21 /r | AND r/m32, r32 | MR | Valid | Valid | r/m32 AND r32. |
+| REX.W + 21 /r | AND r/m64, r64 | MR | Valid | N.E. | r/m64 AND r32. |
+| 22 /r | AND r8, r/m8 | RM | Valid | Valid | r8 AND r/m8. |
+| REX + 22 /r | AND r8*, r/m8* | RM | Valid | N.E. | r/m64 AND r8 (sign-extended). |
+| 23 /r | AND r16, r/m16 | RM | Valid | Valid | r16 AND r/m16. |
+| 23 /r | AND r32, r/m32 | RM | Valid | Valid | r32 AND r/m32. |
+| REX.W + 23 /r | AND r64, r/m64 | RM | Valid | N.E. | r64 AND r/m64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the it to be executed atomically.
+
+In 64-bit mode, the instruction's default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional
+registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this
+section for encoding data and limits.
--- /dev/null
+# CALL — Call Procedure
+
+## Description
+
+Saves procedure linking information on the stack and branches to the called procedure specified using the target operand. The target operand
+specifies the address of the first instruction in the called procedure. The operand can be an immediate value, a general-purpose register, or a
+memory location.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|---------------|-------|-------------|-------------|--------------------------------------------------------------------------|
+| E8 cw | CALL rel16 | M | N.S. | Valid | Call near, relative, displacement relative to next instruction. |
+| E8 cd | CALL rel32 | M | Valid | Valid | Call near, relative, displacement relative to next instruction, extend. |
+| FF /2 | CALL r/m16 | M | N.E. | Valid | Call near, absolute indirect, address given in r/m16. |
+| FF /2 | CALL r/m32 | M | N.E. | Valid | Call near, absolute indirect, address given in r/m32. |
+| FF /2 | CALL r/m64 | M | Valid | N.E. | Call near, absolute indirect, address given in r/m64. |
+| 9A cd | CALL ptr16:16 | D | Invalid | Valid | Call far, absolute, address given in operand. |
+| 9A cp | CALL ptr16:32 | D | Invalid | Valid | Call far, absolute, address given in operand. |
+| FF /3 | CALL m16:16 | M | Valid | Valid | Call far, absolute indirect address given in m16:16, extend. |
+| FF /3 | CALL m16:32 | M | Valid | Valid | In 64-bit mode: If selector points to a gate, semi-extend. |
+| REX.W + FF /3 | CALL m16:64 | M | Valid | N.E. | In 64-bit mode: If selector points to a gate, semi-extend. |
+
+## Information
+
+This instruction can be used to execute four types of calls:
+
+• Near Call — A call to a procedure in the current code segment (the segment currently pointed to by the CS register), sometimes referred to as
+an intra-segment call.
+
+• Far Call — A call to a procedure located in a different segment than the current code segment, sometimes referred to as an inter-segment
+call.
+
+• Inter-privilege-level far call — A far call to a procedure in a segment at a different privilege level than that of the currently executing
+program or procedure.
+
+• Task switch — A call to a procedure located in a different task.
+
+The latter two call types (inter-privilege-level call and task switch) can only be executed in protected mode.
+
+Near Call. When executing a near call, the processor pushes the value of the EIP register (which contains the offset of the instruction
+following the CALL instruction) on the stack (for use later as a return-instruction pointer). The processor then branches to the address in the
+current code segment specified by the target operand. The target operand specifies either an absolute offset in the code segment (an offset
+from the base of the code segment) or a relative offset (a signed displacement relative to the current value of the instruction pointer in the
+EIP register; this value points to the instruction following the CALL instruction). The CS register is not changed on near calls.
+
+For a near call absolute, an absolute offset is specified indirectly in a general-purpose register or a memory location (r/m16, r/m32, or
+r/m64). The operand-size attribute determines the size of the target operand (16, 32 or 64 bits). When in 64-bit mode, the operand size for
+near call (and all near branches) is forced to 64-bits. Absolute offsets are loaded directly into the EIP(RIP) register. If the operand size
+attribute is 16, the upper two bytes of the EIP register are cleared, resulting in a maximum instruction pointer size of 16 bits. When
+accessing an absolute offset indirectly using the stack pointer [ESP] as the base register, the base value used is the value of the ESP before
+the instruction executes.
+
+A relative offset (rel16 or rel32) is generally specified as a label in assembly code. But at the machine code level, it is encoded as a
+signed, 16- or 32-bit immediate value. This value is added to the value in the EIP(RIP) register. In 64-bit mode the relative offset is always
+a 32-bit immediate value which is sign extended to 64-bits before it is added to the value in the RIP register for the target calculation. As
+with absolute offsets, the operand-size attribute determines the size of the target operand (16, 32, or 64 bits). In 64-bit mode the target
+operand will always be 64- bits because the operand size is forced to 64-bits for near branches.
+
+Far Calls in Real-Address or Virtual-8086 Mode. When executing a far call in real- address or virtual-8086 mode, the processor pushes the
+current value of both the CS and EIP registers on the stack for use as a return-instruction pointer. The processor then performs a "far branch"
+to the code segment and offset specified with the target operand for the called procedure. The target operand specifies an absolute far address
+either directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or m16:32). With the pointer method, the
+segment and offset of the called procedure is encoded in the instruction using a 4-byte (16-bit operand size) or 6- byte (32-bit operand size)
+far address immediate. With the indirect method, the target operand specifies a memory location that contains a 4-byte (16-bit operand size) or
+6-byte (32-bit operand size) far address. The operand-size attribute determines the size of the offset (16 or 32 bits) in the far address. The
+far address is loaded directly into the CS and EIP registers. If the operand-size attribute is 16, the upper two bytes of the EIP register are
+cleared.
+
+Far Calls in Protected Mode. When the processor is operating in protected mode, the CALL instruction can be used to perform the following types
+of far calls:
+
+• Far call to the same privilege level
+• Far call to a different privilege level (inter-privilege level call)
+• Task switch (far call to another task)
+
+In protected mode, the processor always uses the segment selector part of the far address to access the corresponding descriptor in the GDT or
+LDT. The descriptor type (code segment, call gate, task gate, or TSS) and access rights determine the type of call operation to be performed.
+
+If the selected descriptor is for a code segment, a far call to a code segment at the same privilege level is performed. (If the selected code
+segment is at a different privilege level and the code segment is non-conforming, a general-protection exception is generated.) A far call to
+the same privilege level in protected mode is very similar to one carried out in real-address or virtual-8086 mode. The target operand
+specifies an absolute far address either directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or
+m16:32). The operand- size attribute determines the size of the offset (16 or 32 bits) in the far address. The new code segment selector and
+its descriptor are loaded into CS register; the offset from the instruction is loaded into the EIP register.
+
+A call gate (described in the next paragraph) can also be used to perform a far call to a code segment at the same privilege level. Using this
+mechanism provides an extra level of indirection and is the preferred method of making calls between 16-bit and 32-bit code segments.
+
+When executing an inter-privilege-level far call, the code segment for the procedure being called must be accessed through a call gate. The
+segment selector specified by the target operand identifies the call gate. The target operand can specify the call gate segment selector either
+directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or m16:32). The processor obtains the segment
+selector for the new code segment and the new instruction pointer (offset) from the call gate descriptor. The offset from the target operand is
+ignored when a call gate is used.
+
+On inter-privilege-level calls, the processor switches to the stack for the privilege level of the called procedure. The segment selector for
+the new stack segment is specified in the TSS for the currently running task. The branch to the new code segment occurs after the stack switch.
+(Note that when using a call gate to perform a far call to a segment at the same privilege level, no stack switch occurs.) On the new stack,
+the processor pushes the segment selector and stack pointer for the calling procedure's stack, an optional set of parameters from the calling
+procedures stack, and the segment selector and instruction pointer for the calling procedure's code segment. A value in the call gate
+descriptor determines how many parameters to copy to the new stack. Finally, the processor branches to the address of the procedure being
+called within the new code segment.
+
+Executing a task switch with the CALL instruction is similar to executing a call through a call gate. The target operand specifies the segment
+selector of the task gate for the new task activated by the switch (the offset in the target operand is ignored). The task gate in turn points
+to the TSS for the new task, which contains the segment selectors for the task's code and stack segments. Note that the TSS also contains the
+EIP value for the next instruction that was to be executed before the calling task was suspended. This instruction pointer value is loaded into
+the EIP register to re-start the calling task.
+
+The CALL instruction can also specify the segment selector of the TSS directly, which eliminates the indirection of the task gate.
+
+When you execute at task switch with a CALL instruction, the nested task flag (NT) is set in the EFLAGS register and the new TSS's previous
+task link field is loaded with the old task's TSS selector. Code is expected to suspend this nested task by executing an IRET instruction
+which, because the NT flag is set, automatically uses the previous task link to return to the calling task. (See "Task Linking" in Chapter 7 of
+the Intel® 64 and IA-32 Architectures Software Developer's Manual, Volume 3A, for information on nested tasks.) Switching tasks with the CALL
+instruction differs in this regard from JMP instruction. JMP does not set the NT flag and therefore does not expect an IRET instruction to
+suspend the task.
+
+Mixing 16-Bit and 32-Bit Calls. When making far calls between 16-bit and 32-bit code segments, use a call gate. If the far call is from a
+32-bit code segment to a 16-bit code segment, the call should be made from the first 64 KBytes of the 32-bit code segment. This is because the
+operand-size attribute of the instruction is set to 16, so only a 16-bit return address offset can be saved. Also, the call should be made
+using a 16-bit call gate so that 16-bit values can be pushed on the stack.
+
+Far Calls in Compatibility Mode. When the processor is operating in compatibility mode, the CALL instruction can be used to perform the
+following types of far calls:
+
+• Far call to the same privilege level, remaining in compatibility mode
+• Far call to the same privilege level, transitioning to 64-bit mode
+• Far call to a different privilege level (inter-privilege level call), transitioning to 64-bit mode
+
+Note that a CALL instruction can not be used to cause a task switch in compatibility mode since task switches are not supported in IA-32e mode.
+
+In compatibility mode, the processor always uses the segment selector part of the far address to access the corresponding descriptor in the GDT
+or LDT. The descriptor type (code segment, call gate) and access rights determine the type of call operation to be performed.
+
+If the selected descriptor is for a code segment, a far call to a code segment at the same privilege level is performed. (If the selected code
+segment is at a different privilege level and the code segment is non-conforming, a general-protection exception is generated.) A far call to
+the same privilege level in compatibility mode is very similar to one carried out in protected mode. The target operand specifies an absolute
+far address either directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or m16:32). The operand-size
+attribute determines the size of the offset (16 or 32 bits) in the far address. The new code segment selector and its descriptor are loaded
+into CS register and the offset from the instruction is loaded into the EIP register. The difference is that 64-bit mode may be entered. This
+specified by the L bit in the new code segment descriptor.
+
+Note that a 64-bit call gate (described in the next paragraph) can also be used to perform a far call to a code segment at the same privilege
+level. However, using this mechanism requires that the target code segment descriptor have the L bit set, causing an entry to 64-bit mode.
+
+When executing an inter-privilege-level far call, the code segment for the procedure being called must be accessed through a 64-bit call gate.
+The segment selector specified by the target operand identifies the call gate. The target operand can specify the call gate segment selector
+either directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or m16:32). The processor obtains the
+segment selector for the new code segment and the new instruction pointer (offset) from the 16-byte call gate descriptor. The offset from the
+target operand is ignored when a call gate is used.
+
+On inter-privilege-level calls, the processor switches to the stack for the privilege level of the called procedure. The segment selector for
+the new stack segment is set to NULL. The new stack pointer is specified in the TSS for the currently running task. The branch to the new code
+segment occurs after the stack switch. (Note that when using a call gate to perform a far call to a segment at the same privilege level, an
+implicit stack switch occurs as a result of entering 64-bit mode. The SS selector is unchanged, but stack segment accesses use a segment base
+of 0x0, the limit is ignored, and the default stack size is 64-bits. The full value of RSP is used for the offset, of which the upper 32-bits
+are undefined.) On the new stack, the processor pushes the segment selector and stack pointer for the calling procedure's stack and the segment
+selector and instruction pointer for the calling procedure's code segment. Parameter copy is not supported in IA-32e mode. Finally, the
+processor branches to the address of the procedure being called within the new code segment.
+
+Near/(Far) Calls in 64-bit Mode. When the processor is operating in 64-bit mode, the CALL instruction can be used to perform the following
+types of far calls:
+
+• Far call to the same privilege level, transitioning to compatibility mode
+• Far call to the same privilege level, remaining in 64-bit mode
+• Far call to a different privilege level (inter-privilege level call), remaining in 64-bit mode
+
+Note that in this mode the CALL instruction can not be used to cause a task switch in 64-bit mode since task switches are not supported in
+IA-32e mode.
+
+In 64-bit mode, the processor always uses the segment selector part of the far address to access the corresponding descriptor in the GDT or
+LDT. The descriptor type (code segment, call gate) and access rights determine the type of call operation to be performed.
+
+If the selected descriptor is for a code segment, a far call to a code segment at the same privilege level is performed. (If the selected code
+segment is at a different privilege level and the code segment is non-conforming, a general-protection exception is generated.) A far call to
+the same privilege level in 64-bit mode is very similar to one carried out in compatibility mode. The target operand specifies an absolute far
+address indirectly with a memory location (m16:16, m16:32 or m16:64). The form of CALL with a direct specification of absolute far address is
+not defined in 64-bit mode. The operand-size attribute determines the size of the offset (16, 32, or 64 bits) in the far address. The new code
+segment selector and its descriptor are loaded into the CS register; the offset from the instruction is loaded into the EIP register. The new
+code segment may specify entry either into compatibility or 64-bit mode, based on the L bit value.
+
+A 64-bit call gate (described in the next paragraph) can also be used to perform a far call to a code segment at the same privilege level.
+However, using this mechanism requires that the target code segment descriptor have the L bit set.
+
+When executing an inter-privilege-level far call, the code segment for the procedure being called must be accessed through a 64-bit call gate.
+The segment selector specified by the target operand identifies the call gate. The target operand can only specify the call gate segment
+selector indirectly with a memory location (m16:16, m16:32 or m16:64). The processor obtains the segment selector for the new code segment and
+the new instruction pointer (offset) from the 16-byte call gate descriptor. The offset from the target operand is ignored when a call gate is
+used.
+
+On inter-privilege-level calls, the processor switches to the stack for the privilege level of the called procedure. The segment selector for
+the new stack segment is set to NULL. The new stack pointer is specified in the TSS for the currently running task. The branch to the new code
+segment occurs after the stack switch.
+
+Note that when using a call gate to perform a far call to a segment at the same privilege level, an implicit stack switch occurs as a result of
+entering 64-bit mode. The SS selector is unchanged, but stack segment accesses use a segment base of 0x0, the limit is ignored, and the default
+stack size is 64-bits. (The full value of RSP is used for the offset.) On the new stack, the processor pushes the segment selector and stack
+pointer for the calling procedure's stack and the segment selector and instruction pointer for the calling procedure's code segment. (Parameter
+copy is not supported in IA-32e mode.) Finally, the processor branches to the address of the procedure being called within the new code
+segment.
--- /dev/null
+# CMOVcc — Conditional Move
+
+## Description
+
+The CMOVcc instructions check the state of one or more of the status flags in the EFLAGS register (CF, OF, PF, SF, and ZF) and perform a move
+operation if the flags are in a specified state (or condition). A condition code (cc) is associated with each instruction to indicate the
+condition being tested for. If the condition is not satisfied, a move is not performed and execution continues with the instruction following
+the CMOVcc instruction.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|--------------------|-------|-------------|-------------|------------------------------------------------------------------|
+| 0F 47 /r | CMOVA r16, r/m16 | RM | Valid | Valid | Move if above (CF=0 and ZF=0). |
+| 0F 47 /r | CMOVA r32, r/m32 | RM | Valid | Valid | Move if above (CF=0 and ZF=0). |
+| REX.W + 0F 47 /r | CMOVA r64, r/m64 | RM | Valid | N.E. | Move if above (CF=0 and ZF=0). |
+| 0F 43 /r | CMOVAE r16, r/m16 | RM | Valid | Valid | Move if above or equal (CF=0). |
+| 0F 43 /r | CMOVAE r32, r/m32 | RM | Valid | Valid | Move if above or equal (CF=0). |
+| REX.W + 0F 43 /r | CMOVAE r64, r/m64 | RM | Valid | N.E. | Move if above or equal (CF=0). |
+| 0F 42 /r | CMOVB r16, r/m16 | RM | Valid | Valid | Move if below (CF=1). |
+| 0F 42 /r | CMOVB r32, r/m32 | RM | Valid | Valid | Move if below (CF=1). |
+| REX.W + 0F 42 /r | CMOVB r64, r/m64 | RM | Valid | N.E. | Move if below (CF=1). |
+| 0F 46 /r | CMOVBE r16, r/m16 | RM | Valid | Valid | Move if below or equal (CF=1 or ZF=1). |
+| 0F 46 /r | CMOVBE r32, r/m32 | RM | Valid | Valid | Move if below or equal (CF=1 or ZF=1). |
+| REX.W + 0F 46 /r | CMOVBE r64, r/m64 | RM | Valid | N.E. | Move if below or equal (CF=1 or ZF=1). |
+| 0F 42 /r | CMOVC r16, r/m16 | RM | Valid | Valid | Move if carry (CF=1). |
+| 0F 42 /r | CMOVC r32, r/m32 | RM | Valid | Valid | Move if carry (CF=1). |
+| REX.W + 0F 42 /r | CMOVC r64, r/m64 | RM | Valid | N.E. | Move if carry (CF=1). |
+| 0F 44 /r | CMOVE r16, r/m16 | RM | Valid | Valid | Move if equal (ZF=1). |
+| 0F 44 /r | CMOVE r32, r/m32 | RM | Valid | Valid | Move if equal (ZF=1). |
+| REX.W + 0F 44 /r | CMOVE r64, r/m64 | RM | Valid | N.E. | Move if equal (ZF=1). |
+| 0F 4F /r | CMOVG r16, r/m16 | RM | Valid | Valid | Move if greater (ZF=0 and SF=OF). |
+| 0F 4F /r | CMOVG r32, r/m32 | RM | Valid | Valid | Move if greater (ZF=0 and SF=OF). |
+| REX.W + 0F 4F /r | CMOVG r64, r/m64 | RM | Valid | N.E. | Move if greater (ZF=0 and SF=OF). |
+| 0F 4D /r | CMOVGE r16, r/m16 | RM | Valid | Valid | Move if greater or equal (SF=OF). |
+| 0F 4D /r | CMOVGE r32, r/m32 | RM | Valid | Valid | Move if greater or equal (SF=OF). |
+| REX.W + 0F 4D /r | CMOVGE r64, r/m64 | RM | Valid | N.E. | Move if greater or equal (SF=OF). |
+| 0F 4C /r | CMOVL r16, r/m16 | RM | Valid | Valid | Move if less (SF≠ OF). |
+| 0F 4C /r | CMOVL r32, r/m32 | RM | Valid | Valid | Move if less (SF≠ OF). |
+| REX.W + 0F 4C /r | CMOVL r64, r/m64 | RM | Valid | N.E. | Move if less (SF≠ OF). |
+| 0F 4E /r | CMOVLE r16, r/m16 | RM | Valid | Valid | Move if less or equal (ZF=1 or SF≠ OF). |
+| 0F 4E /r | CMOVLE r32, r/m32 | RM | Valid | Valid | Move if less or equal (ZF=1 or SF≠ OF). |
+| REX.W + 0F 4E /r | CMOVLE r64, r/m64 | RM | Valid | N.E. | Move if less or equal (ZF=1 or SF≠ OF). |
+| 0F 46 /r | CMOVNA r16, r/m16 | RM | Valid | Valid | Move if not above (CF=1 or ZF=1). |
+| 0F 46 /r | CMOVNA r32, r/m32 | RM | Valid | Valid | Move if not above (CF=1 or ZF=1). |
+| REX.W + 0F 46 /r | CMOVNA r64, r/m64 | RM | Valid | N.E. | Move if not above (CF=1 or ZF=1). |
+| 0F 42 /r | CMOVNAE r16, r/m16 | RM | Valid | Valid | Move if not above or equal (CF=1). |
+| 0F 42 /r | CMOVNAE r32, r/m32 | RM | Valid | Valid | Move if not above or equal (CF=1). |
+| REX.W + 0F 42 /r | CMOVNAE r64, r/m64 | RM | Valid | N.E. | Move if not above or equal (CF=1). |
+| 0F 43 /r | CMOVNB r16, r/m16 | RM | Valid | Valid | Move if not below (CF=0). |
+| 0F 43 /r | CMOVNB r32, r/m32 | RM | Valid | Valid | Move if not below (CF=0). |
+| REX.W + 0F 43 /r | CMOVNB r64, r/m64 | RM | Valid | N.E. | Move if not below (CF=0). |
+| 0F 47 /r | CMOVNBE r16, r/m16 | RM | Valid | Valid | Move if not below or equal (CF=0 and ZF=0). |
+| 0F 47 /r | CMOVNBE r32, r/m32 | RM | Valid | Valid | Move if not below or equal (CF=0 and ZF=0). |
+| REX.W + 0F 47 /r | CMOVNBE r64, r/m64 | RM | Valid | N.E. | Move if not below or equal (CF=0 and ZF=0). |
+| 0F 43 /r | CMOVNC r16, r/m16 | RM | Valid | Valid | Move if not carry (CF=0). |
+| 0F 43 /r | CMOVNC r32, r/m32 | RM | Valid | Valid | Move if not carry (CF=0). |
+| REX.W + 0F 43 /r | CMOVNC r64, r/m64 | RM | Valid | N.E. | Move if not carry (CF=0). |
+| 0F 45 /r | CMOVNE r16, r/m16 | RM | Valid | Valid | Move if not equal (ZF=0). |
+| 0F 45 /r | CMOVNE r32, r/m32 | RM | Valid | Valid | Move if not equal (ZF=0). |
+| REX.W + 0F 45 /r | CMOVNE r64, r/m64 | RM | Valid | N.E. | Move if not equal (ZF=0). |
+| 0F 4E /r | CMOVNG r16, r/m16 | RM | Valid | Valid | Move if not greater (ZF=1 or SF≠ OF). |
+| 0F 4E /r | CMOVNG r32, r/m32 | RM | Valid | Valid | Move if not greater (ZF=1 or SF≠ OF). |
+| REX.W + 0F 4E /r | CMOVNG r64, r/m64 | RM | Valid | N.E. | Move if not greater (ZF=1 or SF≠ OF). |
+| 0F 4C /r | CMOVNGE r16, r/m16 | RM | Valid | Valid | Move if not greater or equal (SF≠ OF). |
+| 0F 4C /r | CMOVNGE r32, r/m32 | RM | Valid | Valid | Move if not greater or equal (SF≠ OF). |
+| REX.W + 0F 4C /r | CMOVNGE r64, r/m64 | RM | Valid | N.E. | Move if not greater or equal (SF≠ OF). |
+| 0F 4D /r | CMOVNL r16, r/m16 | RM | Valid | Valid | Move if not less (SF=OF). |
+| 0F 4D /r | CMOVNL r32, r/m32 | RM | Valid | Valid | Move if not less (SF=OF). |
+| REX.W + 0F 4D /r | CMOVNL r64, r/m64 | RM | Valid | N.E. | Move if not less (SF=OF). |
+| 0F 4F /r | CMOVNLE r16, r/m16 | RM | Valid | Valid | Move if not less or equal (ZF=0 and SF=OF). |
+| 0F 4F /r | CMOVNLE r32, r/m32 | RM | Valid | Valid | Move if not less or equal (ZF=0 and SF=OF). |
+| REX.W + 0F 4F /r | CMOVNLE r64, r/m64 | RM | Valid | N.E. | Move if not less or equal (ZF=0 and SF=OF). |
+| 0F 41 /r | CMOVNO r16, r/m16 | RM | Valid | Valid | Move if not overflow (OF=0). |
+| 0F 41 /r | CMOVNO r32, r/m32 | RM | Valid | Valid | Move if not overflow (OF=0). |
+| REX.W + 0F 41 /r | CMOVNO r64, r/m64 | RM | Valid | N.E. | Move if not overflow (OF=0). |
+| 0F 4B /r | CMOVNP r16, r/m16 | RM | Valid | Valid | Move if not parity (PF=0). |
+| 0F 4B /r | CMOVNP r32, r/m32 | RM | Valid | Valid | Move if not parity (PF=0). |
+| REX.W + 0F 4B /r | CMOVNP r64, r/m64 | RM | Valid | N.E. | Move if not parity (PF=0). |
+| 0F 49 /r | CMOVNS r16, r/m16 | RM | Valid | Valid | Move if not sign (SF=0). |
+| 0F 49 /r | CMOVNS r32, r/m32 | RM | Valid | Valid | Move if not sign (SF=0). |
+| REX.W + 0F 49 /r | CMOVNS r64, r/m64 | RM | Valid | N.E. | Move if not sign (SF=0). |
+| 0F 45 /r | CMOVNZ r16, r/m16 | RM | Valid | Valid | Move if not zero (ZF=0). |
+| 0F 45 /r | CMOVNZ r32, r/m32 | RM | Valid | Valid | Move if not zero (ZF=0). |
+| REX.W + 0F 45 /r | CMOVNZ r64, r/m64 | RM | Valid | N.E. | Move if not zero (ZF=0). |
+| 0F 40 /r | CMOVO r16, r/m16 | RM | Valid | Valid | Move if overflow (OF=1). |
+| 0F 40 /r | CMOVO r32, r/m32 | RM | Valid | Valid | Move if overflow (OF=1). |
+| REX.W + 0F 40 /r | CMOVO r64, r/m64 | RM | Valid | N.E. | Move if overflow (OF=1). |
+| 0F 4A /r | CMOVP r16, r/m16 | RM | Valid | Valid | Move if parity (PF=1). |
+| 0F 4A /r | CMOVP r32, r/m32 | RM | Valid | Valid | Move if parity (PF=1). |
+| REX.W + 0F 4A /r | CMOVP r64, r/m64 | RM | Valid | N.E. | Move if parity (PF=1). |
+| 0F 4A /r | CMOVPE r16, r/m16 | RM | Valid | Valid | Move if parity even (PF=1). |
+| 0F 4A /r | CMOVPE r32, r/m32 | RM | Valid | Valid | Move if parity even (PF=1). |
+| REX.W + 0F 4A /r | CMOVPE r64, r/m64 | RM | Valid | N.E. | Move if parity even (PF=1). |
+| 0F 4B /r | CMOVPO r16, r/m16 | RM | Valid | Valid | Move if parity odd (PF=0). |
+| 0F 4B /r | CMOVPO r32, r/m32 | RM | Valid | Valid | Move if parity odd (PF=0). |
+| REX.W + 0F 4B /r | CMOVPO r64, r/m64 | RM | Valid | N.E. | Move if parity odd (PF=0). |
+| 0F 48 /r | CMOVS r16, r/m16 | RM | Valid | Valid | Move if sign (SF=1). |
+| 0F 48 /r | CMOVS r32, r/m32 | RM | Valid | Valid | Move if sign (SF=1). |
+| REX.W + 0F 48 /r | CMOVS r64, r/m64 | RM | Valid | N.E. | Move if sign (SF=1). |
+| 0F 44 /r | CMOVZ r16, r/m16 | RM | Valid | Valid | Move if zero (ZF=1). |
+| 0F 44 /r | CMOVZ r32, r/m32 | RM | Valid | Valid | Move if zero (ZF=1). |
+| REX.W + 0F 44 /r | CMOVZ r64, r/m64 | RM | Valid | N.E. | Move if zero (ZF=1). |
+
+## Information
+
+These instructions can move 16-bit, 32-bit or 64-bit values from memory to a general-purpose register or from one general-purpose register to
+another. Conditional moves of 8-bit register operands are not supported.
+
+The condition for each CMOVcc mnemonic is given in the description column of the above table. The terms "less" and "greater" are used for
+comparisons of signed integers and the terms "above" and "below" are used for unsigned integers.
+
+Because a particular state of the status flags can sometimes be interpreted in two ways, two mnemonics are defined for some opcodes. For
+example, the CMOVA (conditional move if above) instruction and the CMOVNBE (conditional move if not below or equal) instruction are alternate
+mnemonics for the opcode 0F 47H.
+
+The CMOVcc instructions were introduced in P6 family processors; however, these instructions may not be supported by all IA-32 processors.
+Software can determine if the CMOVcc instructions are supported by checking the processor's feature information with the CPUID instruction.
+
+In 64-bit mode, the instruction's default operation size is 32 bits. Use of the REX.R prefix permits access to addi- tional registers (R8-R15).
+Use of the REX.W prefix promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.
--- /dev/null
+# CMP — Compare Two Operands
+
+## Description
+
+Compares the first source operand with the second source operand and sets the status flags in the EFLAGS register according to the results. The
+comparison is performed by subtracting the second operand from the first operand and then setting the status flags in the same manner as the
+SUB instruction. When an immediate value is used as an operand, it is sign-extended to the length of the first operand.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|------------------|-------|-------------|-------------|--------------------------------------------------------------------|
+| 3C ib | CMP AL, imm8 | I | Valid | Valid | Compare imm8 with AL. |
+| 3D iw | CMP AX, imm16 | I | Valid | Valid | Compare imm16 with AX. |
+| 3D id | CMP EAX, imm32 | I | Valid | Valid | Compare imm32 with EAX. |
+| REX.W + 3D id | CMP RAX, imm32 | I | Valid | N.E. | Compare imm32 sign-extended to 64-bits with RAX. |
+| 80 /7 ib | CMP r/m8, imm8 | MI | Valid | Valid | Compare imm8 with r/m8. |
+| REX + 80 /7 ib | CMP r/m8*, imm8 | MI | Valid | N.E. | Compare imm8 with r/m8. |
+| 81 /7 iw | CMP r/m16, imm16 | MI | Valid | Valid | Compare imm16 with r/m16. |
+| 81 /7 id | CMP r/m32, imm32 | MI | Valid | Valid | Compare imm32 with r/m32. |
+| REX.W + 81 /7 id | CMP r/m64, imm32 | MI | Valid | N.E. | Compare imm32 sign-extended to 64-bits with r/m64. |
+| 83 /7 ib | CMP r/m16, imm8 | MI | Valid | Valid | Compare imm8 with r/m16. |
+| 83 /7 ib | CMP r/m32, imm8 | MI | Valid | Valid | Compare imm8 with r/m32. |
+| REX.W + 83 /7 ib | CMP r/m64, imm8 | MI | Valid | N.E. | Compare imm8 with r/m64. |
+| 38 /r | CMP r/m8, r8 | MR | Valid | Valid | Compare r8 with r/m8. |
+| REX + 38 /r | CMP r/m8*, r8* | MR | Valid | N.E. | Compare r8 with r/m8. |
+| 39 /r | CMP r/m16, r16 | MR | Valid | Valid | Compare r16 with r/m16. |
+| 39 /r | CMP r/m32, r32 | MR | Valid | Valid | Compare r32 with r/m32. |
+| REX.W + 39 /r | CMP r/m64,r64 | MR | Valid | N.E. | Compare r64 with r/m64. |
+| 3A /r | CMP r8, r/m8 | RM | Valid | Valid | Compare r/m8 with r8. |
+| REX + 3A /r | CMP r8*, r/m8* | RM | Valid | N.E. | Compare r/m8 with r8. |
+| 3B /r | CMP r16, r/m16 | RM | Valid | Valid | Compare r/m16 with r16. |
+| 3B /r | CMP r32, r/m32 | RM | Valid | Valid | Compare r/m32 with r32. |
+| REX.W + 3B /r | CMP r64, r/m64 | RM | Valid | N.E. | Compare r/m64 with r64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+The condition codes used by the Jcc, CMOVcc, and SETcc instructions are based on the results of a CMP instruction. Appendix B, "EFLAGS
+Condition Codes", in the Intel® 64 and IA-32 Architectures Software Developer's Manual, Volume 1, shows the relationship of the status flags
+and the condition codes.
+
+In 64-bit mode, the instruction's default operation size is 32 bits. Use of the REX.R prefix permits access to additional registers (R8-R15).
+Use of the REX.W prefix promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.
--- /dev/null
+# DEC — Decrement by 1
+
+## Description
+
+Subtracts 1 from the destination operand, while preserving the state of the CF flag. The destination operand can be a register or a memory
+location. This instruction allows a loop counter to be updated without disturbing the CF flag. To perform a decrement operation that updates
+the CF flag, use a SUB instruction with an immediate operand of 1.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|-----------|-------|-------------|-------------|------------------------------------------------------------------------------|
+| FE /1 | DEC r/m8 | M | Valid | Valid | Decrement r/m byte by 1. |
+| REX + FE /1 | DEC r/m8* | M | Valid | N.E. | Decrement r/m byte by 1. |
+| FF /1 | DEC r/m16 | M | Valid | Valid | Decrement r/m word by 1. |
+| FF /1 | DEC r/m32 | M | Valid | Valid | Decrement r/m doubleword by 1. |
+| REX.W + FF /1 | DEC r/m64 | M | Valid | N.E. | Decrement r/m quadword by 1. |
+| 48+ rw** | DEC r16 | O | N.E. | Valid | Decrement word register by 1. |
+| 48+ rd | DEC r32 | O | N.E. | Valid | Decrement doubleword register by 1. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+- 40H through 47H are REX prefixes in 64-bit mode.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+n 64-bit mode, DEC r16 and DEC r32 are not encodable (because opcodes 48H through 4FH are REX prefixes). Otherwise, the instruction’s 64-bit
+mode default operation size is 32 bits. Use of the REX.R prefix permits access to additional registers (R8-R15). Use of the REX.W prefix
+promotes operation to 64 bits.
--- /dev/null
+# DIV - Unsigned Divide
+
+## Description
+
+Divides unsigned the value in the AX, DX:AX, EDX:EAX, or RDX:RAX registers (dividend) by the source operand (divisor) and stores the result in
+the AX (AH:AL), DX:AX, EDX:EAX, or RDX:RAX registers. The source operand can be a general-purpose register or a memory location. The action of
+this instruction depends on the operand size (dividend/divisor). Division using 64-bit operand is available only in 64-bit mode.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|-----------|-------|-------------|-------------|------------------------------------------------------------------------------|
+| F6 /6 | DIV r/m8 | M | Valid | Valid | Unsigned divide AX by r/m8, result in AL=Quotient, AH=Remainder. |
+| REX + F6 /6 | DIV r/m8* | M | Valid | N.E. | Unsigned divide AX by r/m8, result in AL=Quotient, AH=Remainder. |
+| F7 /6 | DIV r/m16 | M | Valid | Valid | Unsigned divide DX:AX by r/m16, result in AX=Quotient, DX=Remainder. |
+| F7 /6 | DIV r/m32 | M | Valid | Valid | Unsigned divide EDX:EAX by r/m32, result in EAX=Quotient, EDX=Remainder. |
+| REX.W + F7 /6 | DIV r/m64 | M | Valid | N.E. | Unsigned divide RDX:RAX by r/m64, result in RAX=Quotient, RDX=Remainder. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+Non-integral results are truncated (chopped) towards 0. The remainder is always less than the divisor in magnitude. Overflow is indicated with
+the #DE (divide error) exception rather than with the CF flag.
+
+In 64-bit mode, the instruction’s default operation size is 32 bits. Use of the REX.R prefix permits access to additional registers (R8-R15).
+Use of the REX.W prefix promotes operation to 64 bits. In 64-bit mode when REX.W is applied, the instruction divides the unsigned value in
+RDX:RAX by the source operand and stores the quotient in RAX, the remainder in RDX.
--- /dev/null
+# ENTER — Make Stack Frame for Procedure Parameters
+
+## Description
+
+Creates a stack frame (comprising of space for dynamic storage and 1-32 frame pointer storage) for a procedure. The first operand (imm16)
+specifies the size of the dynamic storage in the stack frame (that is, the number of bytes of dynamically allocated on the stack for the
+procedure). The second operand (imm8) gives the lexical nesting level (0 to 31) of the procedure. The nesting level (imm8 mod 32) and the
+OperandSize attribute determine the size in bytes of the storage space for frame pointers.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|----------|-------------------|-------|-------------|-------------|---------------------------------------------------------------------------|
+| C8 iw 00 | ENTER imm16, 0 | II | Valid | Valid | Create a stack frame for a procedure. |
+| C8 iw 01 | ENTER imm16,1 | II | Valid | Valid | Create a stack frame with a nested pointer for a procedure. |
+| C8 iw ib | ENTER imm16, imm8 | II | Valid | Valid | Create a stack frame with nested pointers for a procedure. |
+
+## Information
+
+The nesting level determines the number of frame pointers that are copied into the "display area" of the new stack frame from the preceding
+frame. The default size of the frame pointer is the StackAddrSize attribute, but can be overridden using the 66H prefix. Thus, the OperandSize
+attribute determines the size of each frame pointer that will be copied into the stack frame and the data being transferred from SP/ESP/RSP
+register into the BP/EBP/RBP register.
+
+The ENTER and companion LEAVE instructions are provided to support block structured languages. The ENTER instruction (when used) is typically
+the first instruction in a procedure and is used to set up a new stack frame for a procedure. The LEAVE instruction is then used at the end of
+the procedure (just before the RET instruction) to release the stack frame.
+
+If the nesting level is 0, the processor pushes the frame pointer from the BP/EBP/RBP register onto the stack, copies the current stack pointer
+from the SP/ESP/RSP register into the BP/EBP/RBP register, and loads the SP/ESP/RSP register with the current stack-pointer value minus the
+value in the size operand. For nesting levels of 1 or greater, the processor pushes additional frame pointers on the stack before adjusting the
+stack pointer. These additional frame pointers provide the called procedure with access points to other nested frames on the stack.
+
+The ENTER instruction causes a page fault whenever a write using the final value of the stack pointer (within the current stack segment) would
+do so.
+
+In 64-bit mode, default operation size is 64 bits; 32-bit operation size cannot be encoded. Use of 66H prefix changes frame pointer operand
+size to 16 bits.
+
+When the 66H prefix is used and causing the OperandSize attribute to be less than the StackAddrSize, software is responsible for the following:
+
+• The companion LEAVE instruction must also use the 66H prefix.
+
+• The value in the RBP/EBP register prior to executing "66H ENTER" must be within the same 16KByte region of the current stack pointer
+(RSP/ESP), such that the value of RBP/EBP after "66H ENTER" remains a valid address in the stack. This ensures "66H LEAVE" can restore 16-bits
+of data from the stack.
--- /dev/null
+# IDIV - Signed Divide
+
+## Description
+
+Divides the (signed) value in the AX, DX:AX, or EDX:EAX (dividend) by the source operand (divisor) and stores the result in the AX (AH:AL),
+DX:AX, or EDX:EAX registers. The source operand can be a general-purpose register or a memory location. The action of this instruction depends
+on the operand size (dividend/divisor).
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|------------|-------|-------------|-------------|-----------------------------------------------------------------------------|
+| F6 /7 | IDIV r/m8 | M | Valid | Valid | Signed divide AX by r/m8, result in: AL=Quotient, AH=Remainder. |
+| REX + F6 /7 | IDIV r/m8* | M | Valid | N.E. | Signed divide AX by r/m8, result in AL=Quotient, AH=Remainder. |
+| F7 /7 | IDIV r/m16 | M | Valid | Valid | Signed divide DX:AX by r/m16, result in AX=Quotient, DX=Remainder. |
+| F7 /7 | IDIV r/m32 | M | Valid | Valid | Signed divide EDX:EAX by r/m32, result in EAX=Quotient, EDX=Remainder. |
+| REX.W + F7 /7 | IDIV r/m64 | M | Valid | N.E. | Signed divide RDX:RAX by r/m64, result in RAX=Quotient, RDX=Remainder. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+Non-integral results are truncated (chopped) towards 0. The remainder is always less than the divisor in magni- tude. Overflow is indicated
+with the #DE (divide error) exception rather than with the CF flag.
+
+In 64-bit mode, the instruction’s default operation size is 32 bits. Use of the REX.R prefix permits access to additional registers (R8-R15).
+Use of the REX.W prefix promotes operation to 64 bits. In 64-bit mode when REX.W is applied, the instruction divides the signed value in
+RDX:RAX by the source operand. RAX contains a 64-bit quotient; RDX contains a 64-bit remainder.
--- /dev/null
+# IMUL - Signed Multiply
+
+## Description
+
+Performs a signed multiplication of two operands. This instruction has three forms, depending on the number of operands. It's very different
+from its unsigned version, which is similar to signed and unsigned division.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|------------------------|-------|-------------|-------------|--------------------------------------------------------------|
+| F6 /5 | IMUL r/m8* | M | Valid | Valid | AX=AL*r/m byte. |
+| F7 /5 | IMUL r/m16 | M | Valid | Valid | DX:AX=AX*r/m word. |
+| F7 /5 | IMUL r/m32 | M | Valid | Valid | EDX:EAX=EAX*r/m32. |
+| REX.W + F7 /5 | IMUL r/m64 | M | Valid | N.E. | RDX:RAX=RAX*r/m64. |
+| 0F AF /r | IMUL r16, r/m16 | RM | Valid | Valid | Word stores word register*r/m16. |
+| 0F AF /r | IMUL r32, r/m32 | RM | Valid | Valid | Doubleword stores doubleword register*r/m32. |
+| REX.W + 0F AF /r | IMUL r64, r/m64 | RM | Valid | N.E. | Quadword stores Quadword register*r/m64. |
+| 6B /r ib | IMUL r16, r/m16, imm8 | RMI | Valid | Valid | Word stores r/m16*sign-extended immediate byte. |
+| 6B /r ib | IMUL r32, r/m32, imm8 | RMI | Valid | Valid | doubleword stores r/m32*sign-extended immediate byte. |
+| REX.W + 6B /r ib | IMUL r64, r/m64, imm8 | RMI | Valid | N.E. | Quadword stores r/m64*sign-extended immediate byte. |
+| 69 /r iw | IMUL r16, r/m16, imm16 | RMI | Valid | Valid | Word stores r/m16*immediate word. |
+| 69 /r id | IMUL r32, r/m32, imm32 | RMI | Valid | Valid | Doubleword stores r/m32*immediate doubleword. |
+| REX.W + 69 /r id | IMUL r64, r/m64, imm32 | RMI | Valid | N.E. | Quadword stores r/m64*immediate doubleword. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+- One-operand form — This form is identical to that used by the MUL instruction. Here, the source operand (in a general-purpose register or
+memory location) is multiplied by the value in the AL, AX, EAX, or RAX register (depending on the operand size) and the product (twice the size
+of the input operand) is stored in the AX, DX:AX, EDX:EAX, or RDX:RAX registers, respectively.
+
+- Two-operand form — With this form the destination operand (the first operand) is multiplied by the source operand (second operand). The
+destination operand is a general-purpose register and the source operand is an immediate value, a general-purpose register, or a memory
+location. The intermediate product (twice the size of the input operand) is truncated and stored in the destination operand location.
+
+- Three-operand form — This form requires a destination operand (the first operand) and two source operands (the second and the third
+operands). Here, the first source operand (which can be a general-purpose register or a memory location) is multiplied by the second source
+operand (an immediate value). The intermediate product (twice the size of the first source operand) is truncated and stored in the destination
+operand (a general-purpose register).
+
+When an immediate value is used as an operand, it is sign-extended to the length of the destination operand format.
+
+The CF and OF flags are set when the signed integer value of the intermediate product differs from the sign extended operand-size-truncated
+product, otherwise the CF and OF flags are cleared.
+
+The three forms of the IMUL instruction are similar in that the length of the product is calculated to twice the length of the operands. With
+the one-operand form, the product is stored exactly in the destination. With the two- and three- operand forms, however, the result is
+truncated to the length of the destination before it is stored in the destination register. Because of this truncation, the CF or OF flag
+should be tested to ensure that no significant bits are lost.
+
+The two- and three-operand forms may also be used with unsigned operands because the lower half of the product is the same regardless if the
+operands are signed or unsigned. The CF and OF flags, however, cannot be used to determine if the upper half of the result is non-zero.
+
+In 64-bit mode, the instruction’s default operation size is 32 bits. Use of the REX.R prefix permits access to additional registers (R8-R15).
+Use of the REX.W prefix promotes operation to 64 bits. Use of REX.W modifies the three forms of the instruction as follows.
+
+- One-operand form —The source operand (in a 64-bit general-purpose register or memory location) is multiplied by the value in the RAX register
+and the product is stored in the RDX:RAX registers.
+
+- Two-operand form — The source operand is promoted to 64 bits if it is a register or a memory location. The destination operand is promoted to
+64 bits.
+
+- Three-operand form — The first source operand (either a register or a memory location) and destination operand are promoted to 64 bits. If
+the source operand is an immediate, it is sign extended to 64 bits.
--- /dev/null
+# INC — Increment by 1
+
+## Description
+
+Adds 1 to the destination operand, while preserving the state of the CF flag. The destination operand can be a register or a memory location.
+This instruction allows a loop counter to be updated without disturbing the CF flag. Use a ADD instruction with an immediate operand of 1 to
+perform an increment operation that does updates the CF flag.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|-----------|-------|-------------|-------------|------------------------------------------------------------------------------|
+| FE /0 | INC r/m8 | M | Valid | Valid | Increment r/m byte by 1. |
+| REX + FE /0 | INC r/m8* | M | Valid | N.E. | Increment r/m byte by 1. |
+| FF /0 | INC r/m16 | M | Valid | Valid | Increment r/m word by 1. |
+| FF /0 | INC r/m32 | M | Valid | Valid | Increment r/m doubleword by 1. |
+| REX.W + FF /0 | INC r/m64 | M | Valid | N.E. | Increment r/m quadword by 1. |
+| 40+ rw** | INC r16 | O | N.E. | Valid | Increment word register by 1. |
+| 40+ rd | INC r32 | O | N.E. | Valid | Increment doubleword register by 1. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+- 40H through 47H are REX prefixes in 64-bit mode.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+In 64-bit mode, INC r16 and INC r32 are not encodable (because opcodes 40H through 47H are REX prefixes). Otherwise, the instruction’s 64-bit
+mode default operation size is 32 bits. Use of the REX.R prefix permits access to additional registers (R8-R15). Use of the REX.W prefix
+promotes operation to 64 bits.
--- /dev/null
+# Jcc — Jump if Condition Is Met
+
+## Description
+
+Checks the state of one or more of the status flags in the EFLAGS register (CF, OF, PF, SF, and ZF) and, if the flags are in the specified
+state (condition), performs a jump to the target instruction specified by the destination operand. A condition code (cc) is associated with
+each instruction to indicate the condition being tested for. If the condition is not satisfied, the jump is not performed and execution
+continues with the instruction following the Jcc instruction.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|----------|-------------|-------|-------------|-------------|---------------------------------------------------------------------------------|
+| 77 cb | JA rel8 | D | Valid | Valid | Jump short if above (CF=0 and ZF=0). |
+| 73 cb | JAE rel8 | D | Valid | Valid | Jump short if above or equal (CF=0). |
+| 72 cb | JB rel8 | D | Valid | Valid | Jump short if below (CF=1). |
+| 76 cb | JBE rel8 | D | Valid | Valid | Jump short if below or equal (CF=1 or ZF=1). |
+| 72 cb | JC rel8 | D | Valid | Valid | Jump short if carry (CF=1). |
+| E3 cb | JCXZ rel8 | D | N.E. | Valid | Jump short if CX register is 0. |
+| E3 cb | JECXZ rel8 | D | Valid | Valid | Jump short if ECX register is 0. |
+| E3 cb | JRCXZ rel8 | D | Valid | N.E. | Jump short if RCX register is 0. |
+| 74 cb | JE rel8 | D | Valid | Valid | Jump short if equal (ZF=1). |
+| 7F cb | JG rel8 | D | Valid | Valid | Jump short if greater (ZF=0 and SF=OF). |
+| 7D cb | JGE rel8 | D | Valid | Valid | Jump short if greater or equal (SF=OF). |
+| 7C cb | JL rel8 | D | Valid | Valid | Jump short if less (SF≠ OF). |
+| 7E cb | JLE rel8 | D | Valid | Valid | Jump short if less or equal (ZF=1 or SF≠ OF). |
+| 76 cb | JNA rel8 | D | Valid | Valid | Jump short if not above (CF=1 or ZF=1). |
+| 72 cb | JNAE rel8 | D | Valid | Valid | Jump short if not above or equal (CF=1). |
+| 73 cb | JNB rel8 | D | Valid | Valid | Jump short if not below (CF=0). |
+| 77 cb | JNBE rel8 | D | Valid | Valid | Jump short if not below or equal (CF=0 and ZF=0). |
+| 73 cb | JNC rel8 | D | Valid | Valid | Jump short if not carry (CF=0). |
+| 75 cb | JNE rel8 | D | Valid | Valid | Jump short if not equal (ZF=0). |
+| 7E cb | JNG rel8 | D | Valid | Valid | Jump short if not greater (ZF=1 or SF≠ OF). |
+| 7C cb | JNGE rel8 | D | Valid | Valid | Jump short if not greater or equal (SF≠ OF). |
+| 7D cb | JNL rel8 | D | Valid | Valid | Jump short if not less (SF=OF). |
+| 7F cb | JNLE rel8 | D | Valid | Valid | Jump short if not less or equal (ZF=0 and SF=OF). |
+| 71 cb | JNO rel8 | D | Valid | Valid | Jump short if not overflow (OF=0). |
+| 7B cb | JNP rel8 | D | Valid | Valid | Jump short if not parity (PF=0). |
+| 79 cb | JNS rel8 | D | Valid | Valid | Jump short if not sign (SF=0). |
+| 75 cb | JNZ rel8 | D | Valid | Valid | Jump short if not zero (ZF=0). |
+| 70 cb | JO rel8 | D | Valid | Valid | Jump short if overflow (OF=1). |
+| 7A cb | JP rel8 | D | Valid | Valid | Jump short if parity (PF=1). |
+| 7A cb | JPE rel8 | D | Valid | Valid | Jump short if parity even (PF=1). |
+| 7B cb | JPO rel8 | D | Valid | Valid | Jump short if parity odd (PF=0). |
+| 78 cb | JS rel8 | D | Valid | Valid | Jump short if sign (SF=1). |
+| 74 cb | JZ rel8 | D | Valid | Valid | Jump short if zero (ZF = 1). |
+| 0F 87 cw | JA rel16 | D | N.S. | Valid | Jump near if above (CF=0 and ZF=0). |
+| 0F 87 cd | JA rel32 | D | Valid | Valid | Jump near if above (CF=0 and ZF=0). |
+| 0F 83 cw | JAE rel16 | D | N.S. | Valid | Jump near if above or equal (CF=0). |
+| 0F 83 cd | JAE rel32 | D | Valid | Valid | Jump near if above or equal (CF=0). |
+| 0F 82 cw | JB rel16 | D | N.S. | Valid | Jump near if below (CF=1). |
+| 0F 82 cd | JB rel32 | D | Valid | Valid | Jump near if below (CF=1). |
+| 0F 86 cw | JBE rel16 | D | N.S. | Valid | Jump near if below or equal (CF=1 or ZF=1). |
+| 0F 86 cd | JBE rel32 | D | Valid | Valid | Jump near if below or equal (CF=1 or ZF=1). |
+| 0F 82 cw | JC rel16 | D | N.S. | Valid | Jump near if carry (CF=1). |
+| 0F 82 cd | JC rel32 | D | Valid | Valid | Jump near if carry (CF=1). |
+| 0F 84 cw | JE rel16 | D | N.S. | Valid | Jump near if equal (ZF=1). |
+| 0F 84 cd | JE rel32 | D | Valid | Valid | Jump near if equal (ZF=1). |
+| 0F 84 cw | JZ rel16 | D | N.S. | Valid | Jump near if 0 (ZF=1). |
+| 0F 84 cd | JZ rel32 | D | Valid | Valid | Jump near if 0 (ZF=1). |
+| 0F 8F cw | JG rel16 | D | N.S. | Valid | Jump near if greater (ZF=0 and SF=OF). |
+| 0F 8F cd | JG rel32 | D | Valid | Valid | Jump near if greater (ZF=0 and SF=OF). |
+| 0F 8D cw | JGE rel16 | D | N.S. | Valid | Jump near if greater or equal (SF=OF). |
+| 0F 8D cd | JGE rel32 | D | Valid | Valid | Jump near if greater or equal (SF=OF). |
+| 0F 8C cw | JL rel16 | D | N.S. | Valid | Jump near if less (SF≠ OF). |
+| 0F 8C cd | JL rel32 | D | Valid | Valid | Jump near if less (SF≠ OF). |
+| 0F 8E cw | JLE rel16 | D | N.S. | Valid | Jump near if less or equal (ZF=1 or SF≠ OF). |
+| 0F 8E cd | JLE rel32 | D | Valid | Valid | Jump near if less or equal (ZF=1 or SF≠ OF). |
+| 0F 86 cw | JNA rel16 | D | N.S. | Valid | Jump near if not above (CF=1 or ZF=1). |
+| 0F 86 cd | JNA rel32 | D | Valid | Valid | Jump near if not above (CF=1 or ZF=1). |
+| 0F 82 cw | JNAE rel16 | D | N.S. | Valid | Jump near if not above or equal (CF=1). |
+| 0F 82 cd | JNAE rel32 | D | Valid | Valid | Jump near if not above or equal (CF=1). |
+| 0F 83 cw | JNB rel16 | D | N.S. | Valid | Jump near if not below (CF=0). |
+| 0F 83 cd | JNB rel32 | D | Valid | Valid | Jump near if not below (CF=0). |
+| 0F 87 cw | JNBE rel16 | D | N.S. | Valid | Jump near if not below or equal (CF=0 and ZF=0). |
+| 0F 87 cd | JNBE rel32 | D | Valid | Valid | Jump near if not below or equal (CF=0 and ZF=0). |
+| 0F 83 cw | JNC rel16 | D | N.S. | Valid | Jump near if not carry (CF=0). |
+| 0F 83 cd | JNC rel32 | D | Valid | Valid | Jump near if not carry (CF=0). |
+| 0F 85 cw | JNE rel16 | D | N.S. | Valid | Jump near if not equal (ZF=0). |
+| 0F 85 cd | JNE rel32 | D | Valid | Valid | Jump near if not equal (ZF=0). |
+| 0F 8E cw | JNG rel16 | D | N.S. | Valid | Jump near if not greater (ZF=1 or SF≠ OF). |
+| 0F 8E cd | JNG rel32 | D | Valid | Valid | Jump near if not greater (ZF=1 or SF≠ OF). |
+| 0F 8C cw | JNGE rel16 | D | N.S. | Valid | Jump near if not greater or equal (SF≠ OF). |
+| 0F 8C cd | JNGE rel32 | D | Valid | Valid | Jump near if not greater or equal (SF≠ OF). |
+| 0F 8D cw | JNL rel16 | D | N.S. | Valid | Jump near if not less (SF=OF). |
+| 0F 8D cd | JNL rel32 | D | Valid | Valid | Jump near if not less (SF=OF). |
+| 0F 8F cw | JNLE rel16 | D | N.S. | Valid | Jump near if not less or equal (ZF=0 and SF=OF). |
+| 0F 8F cd | JNLE rel32 | D | Valid | Valid | Jump near if not less or equal (ZF=0 and SF=OF). |
+| 0F 81 cw | JNO rel16 | D | N.S. | Valid | Jump near if not overflow (OF=0). |
+| 0F 81 cd | JNO rel32 | D | Valid | Valid | Jump near if not overflow (OF=0). |
+| 0F 8B cw | JNP rel16 | D | N.S. | Valid | Jump near if not parity (PF=0). |
+| 0F 8B cd | JNP rel32 | D | Valid | Valid | Jump near if not parity (PF=0). |
+| 0F 89 cw | JNS rel16 | D | N.S. | Valid | Jump near if not sign (SF=0). |
+| 0F 89 cd | JNS rel32 | D | Valid | Valid | Jump near if not sign (SF=0). |
+| 0F 85 cw | JNZ rel16 | D | N.S. | Valid | Jump near if not zero (ZF=0). |
+| 0F 85 cd | JNZ rel32 | D | Valid | Valid | Jump near if not zero (ZF=0). |
+| 0F 80 cw | JO rel16 | D | N.S. | Valid | Jump near if overflow (OF=1). |
+| 0F 80 cd | JO rel32 | D | Valid | Valid | Jump near if overflow (OF=1). |
+| 0F 8A cw | JP rel16 | D | N.S. | Valid | Jump near if parity (PF=1). |
+| 0F 8A cd | JP rel32 | D | Valid | Valid | Jump near if parity (PF=1) |
+| 0F 8A cw | JPE rel16 | D | N.S. | Valid | Jump near if parity even (PF=1). |
+| 0F 8A cd | JPE rel32 | D | Valid | Valid | Jump near if parity even (PF=1). |
+| 0F 8B cw | JPO rel16 | D | N.S. | Valid | Jump near if parity odd (PF=0). |
+| 0F 8B cd | JPO rel32 | D | Valid | Valid | Jump near if parity odd (PF=0). |
+| 0F 88 cw | JS rel16 | D | N.S. | Valid | Jump near if sign (SF=1). |
+| 0F 88 cd | JS rel32 | D | Valid | Valid | Jump near if sign (SF=1). |
+| 0F 84 cw | JZ rel16 | D | N.S. | Valid | Jump near if 0 (ZF=1). |
+| 0F 84 cd | JZ rel32 | D | Valid | Valid | Jump near if 0 (ZF=1). |
+
+## Information
+
+The target instruction is specified with a relative offset (a signed offset relative to the current value of the instruction pointer in the EIP
+register). A relative offset (rel8, rel16, or rel32) is generally specified as a label in assembly code, but at the machine code level, it is
+encoded as a signed, 8-bit or 32-bit immediate value, which is added to the instruction pointer. Instruction coding is most efficient for
+offsets of –128 to +127. If the operand-size attribute is 16, the upper two bytes of the EIP register are cleared, resulting in a maximum
+instruction pointer size of 16 bits. The conditions for each Jcc mnemonic are given in the “Description” column of the table on the preceding
+page. The terms “less” and “greater” are used for comparisons of signed integers and the terms “above” and “below” are used for unsigned
+integers.
+
+Because a particular state of the status flags can sometimes be interpreted in two ways, two mnemonics are defined for some opcodes. For
+example, the JA (jump if above) instruction and the JNBE (jump if not below or equal) instruction are alternate mnemonics for the opcode 77H.
+
+The Jcc instruction does not support far jumps (jumps to other code segments). When the target for the conditional jump is in a different
+segment, use the opposite condition from the condition being tested for the Jcc instruction, and then access the target with an unconditional
+far jump (JMP instruction) to the other segment. For example, the following conditional far jump is illegal:
+
+```
+JZ FARLABEL;
+```
+
+To accomplish this far jump, use the following two instructions:
+
+```
+JNZ BEYOND;
+JMP FARLABEL;
+BEYOND:
+```
+
+The JRCXZ, JECXZ and JCXZ instructions differ from other Jcc instructions because they do not check status flags. Instead, they check RCX, ECX
+or CX for 0. The register checked is determined by the address-size attribute. These instructions are useful when used at the beginning of a
+loop that terminates with a conditional loop instruction (such as LOOPNE). They can be used to prevent an instruction sequence from entering a
+loop when RCX, ECX or CX is 0. This would cause the loop to execute 264, 2 32 or 64K times (not zero times).
+
+All conditional jumps are converted to code fetches of one or two cache lines, regardless of jump address or cache-ability.
+
+In 64-bit mode, operand size is fixed at 64 bits. JMP Short is RIP = RIP + 8-bit offset sign extended to 64 bits. JMP Near is RIP = RIP +
+32-bit offset sign extended to 64-bits.
--- /dev/null
+# JMP - Jump
+
+## Description
+
+Transfers program control to a different point in the instruction stream without recording return information. The destination (target) operand
+specifies the address of the instruction being jumped to. This operand can be an immediate value, a general-purpose register, or a memory
+location.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|--------------|-------|-------------|-------------|---------------------------------------------------------------------------|
+| EB cb | JMP rel8 | D | Valid | Valid | Jump short, RIP = RIP + 8-bit displacement sign extended. |
+| E9 cw | JMP rel16 | D | N.S. | Valid | Jump near, relative, displacement relative to next instruction. |
+| E9 cd | JMP rel32 | D | Valid | Valid | Jump near, relative, RIP = RIP + 32-bit displacement sign extended |
+| FF /4 | JMP r/m16 | M | N.S. | Valid | Jump near, absolute indirect, address = zero- extended r/m16. |
+| FF /4 | JMP r/m32 | M | N.S. | Valid | Jump near, absolute indirect, address given in r/m32. |
+| FF /4 | JMP r/m64 | M | Valid | N.E. | Jump near, absolute indirect, RIP = 64-bit from register or memory. |
+| EA cd | JMP ptr16:16 | D | Invalid | Valid | Jump far, absolute, address given in operand. |
+| EA cp | JMP ptr16:32 | D | Invalid | Valid | Jump far, absolute, address given in operand. |
+| FF /5 | JMP m16:16 | D | Valid | Valid | Jump far, absolute indirect, address given in m16:16. |
+| FF /5 | JMP m16:32 | D | Valid | Valid | Jump far, absolute indirect, address given in m16:32. |
+| REX.W + FF /5 | JMP m16:64 | D | Valid | N.E. | Jump far, absolute indirect, address given in m16:64. |
+
+## Information
+
+This instruction can be used to execute four different types of jumps:
+
+- Near jump — A jump to an instruction within the current code segment (the segment currently pointed to by the CS register), sometimes referred
+to as an intrasegment jump.
+
+- Short jump — A near jump where the jump range is limited to –128 to +127 from the current EIP value.
+
+- Far jump — A jump to an instruction located in a different segment than the current code segment but at the same privilege level, sometimes
+referred to as an intersegment jump.
+
+- Task switch — A jump to an instruction located in a different task.
+
+A task switch can only be executed in protected mode.
+
+Near and Short Jumps. When executing a near jump, the processor jumps to the address (within the current code segment) that is specified with
+the target operand. The target operand specifies either an absolute offset (that is an offset from the base of the code segment) or a relative
+offset (a signed displacement relative to the current value of the instruction pointer in the EIP register). A near jump to a relative offset
+of 8-bits (rel8) is referred to as a short jump. The CS register is not changed on near and short jumps.
+
+An absolute offset is specified indirectly in a general-purpose register or a memory location (r/m16 or r/m32). The operand-size attribute
+determines the size of the target operand (16 or 32 bits). Absolute offsets are loaded directly into the EIP register. If the operand-size
+attribute is 16, the upper two bytes of the EIP register are cleared, resulting in a maximum instruction pointer size of 16 bits.
+
+A relative offset (rel8, rel16, or rel32) is generally specified as a label in assembly code, but at the machine code level, it is encoded as a
+signed 8-, 16-, or 32-bit immediate value. This value is added to the value in the EIP register. (Here, the EIP register contains the address
+of the instruction following the JMP instruction). When using relative offsets, the opcode (for short vs. near jumps) and the operand-size
+attribute (for near relative jumps) determines the size of the target operand (8, 16, or 32 bits).
+
+Far Jumps in Real-Address or Virtual-8086 Mode. When executing a far jump in real-address or virtual-8086 mode, the processor jumps to the code
+segment and offset specified with the target operand. Here the target operand specifies an absolute far address either directly with a pointer
+(ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or m16:32). With the pointer method, the segment and address of the called
+procedure is encoded in the instruction, using a 4-byte (16-bit operand size) or 6-byte (32-bit operand size) far address immediate. With the
+indirect method, the target operand specifies a memory location that contains a 4-byte (16-bit operand size) or 6-byte (32-bit operand size)
+far address. The far address is loaded directly into the CS and EIP registers. If the operand-size attribute is 16, the upper two bytes of the
+EIP register are cleared.
+
+Far Jumps in Protected Mode. When the processor is operating in protected mode, the JMP instruction can be used to perform the following three
+types of far jumps:
+
+- A far jump to a conforming or non-conforming code segment.
+- A far jump through a call gate.
+- A task switch.
+
+The JMP instruction cannot be used to perform inter-privilege-level far jumps.
+
+In protected mode, the processor always uses the segment selector part of the far address to access the corresponding descriptor in the GDT or
+LDT. The descriptor type (code segment, call gate, task gate, or TSS) and access rights determine the type of jump to be performed.
+
+If the selected descriptor is for a code segment, a far jump to a code segment at the same privilege level is performed. (If the selected code
+segment is at a different privilege level and the code segment is non-conforming, a general-protection exception is generated.) A far jump to
+the same privilege level in protected mode is very similar to one carried out in real-address or virtual-8086 mode. The target operand
+specifies an absolute far address either directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or
+m16:32). The operand-size attribute determines the size of the offset (16 or 32 bits) in the far address. The new code segment selector and its
+descriptor are loaded into CS register, and the offset from the instruction is loaded into the EIP register. Note that a call gate (described
+in the next paragraph) can also be used to perform far call to a code segment at the same privilege level. Using this mechanism provides an
+extra level of indirection and is the preferred method of making jumps between 16-bit and 32-bit code segments.
+
+When executing a far jump through a call gate, the segment selector specified by the target operand identifies the call gate. The offset part
+of the target operand is ignored. The processor then jumps to the code segment specified in the call gate descriptor and begins executing the
+instruction at the offset specified in the call gate. No stack switch occurs. Here again, the target operand can specify the far address of the
+call gate either directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or m16:32).
+
+Executing a task switch with the JMP instruction is somewhat similar to executing a jump through a call gate. Here the target operand specifies
+the segment selector of the task gate for the task being switched to (and the offset part of the target operand is ignored). The task gate in
+turn points to the TSS for the task, which contains the segment selectors for the task’s code and stack segments. The TSS also contains the EIP
+value for the next instruction that was to be executed before the task was suspended. This instruction pointer value is loaded into the EIP
+register so that the task begins executing again at this next instruction.
+
+The JMP instruction can also specify the segment selector of the TSS directly, which eliminates the indirection of the task gate.
+
+Note that when you execute at task switch with a JMP instruction, the nested task flag (NT) is not set in the EFLAGS register and the new TSS’s
+previous task link field is not loaded with the old task’s TSS selector. A return to the previous task can thus not be carried out by executing
+the IRET instruction. Switching tasks with the JMP instruction differs in this regard from the CALL instruction which does set the NT flag and
+save the previous task link information, allowing a return to the calling task with an IRET instruction.
+
+In 64-Bit Mode — The instruction’s operation size is fixed at 64 bits. If a selector points to a gate, then RIP equals the 64-bit displacement
+taken from gate; else RIP equals the zero-extended offset from the far pointer referenced in the instruction.
--- /dev/null
+# LEAVE — High Level Procedure Exit
+
+## Description
+
+Releases the stack frame set up by an earlier ENTER instruction. The LEAVE instruction copies the frame pointer (in the EBP register) into the
+stack pointer register (ESP), which releases the stack space allocated to the stack frame. The old frame pointer (the frame pointer for the
+calling procedure that was saved by the ENTER instruction) is then popped from the stack into the EBP register, restoring the calling
+procedure's stack frame.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|--------|----------|-------|-------------|-------------|--------------------------------------------------------------------------------------|
+| C9 | LEAVE | NP | Valid | Valid | Set SP to BP, then pop BP. |
+| C9 | LEAVE | NP | N.E. | Valid | Set ESP to EBP, then pop EBP. |
+| C9 | LEAVE | NP | Valid | N.E. | Set RSP to RBP, then pop RBP. |
+
+## Information
+
+A RET instruction is commonly executed following a LEAVE instruction to return program control to the calling procedure.
--- /dev/null
+# MOV — Move
+
+## Description
+
+Copies the second operand (source operand) to the first operand (destination operand). The source operand can be an immediate value,
+general-purpose register, segment register, or memory location; the destination register can be a general-purpose register, segment register,
+or memory location. Both operands must be the same size, which can be a byte, a word, a doubleword, or a quadword.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|-------------------|-------------------|-------|-------------|-------------|------------------------------------------------------------------|
+| 88 /r | MOV r/m8,r8 | MR | Valid | Valid | Move r8 to r/m8. |
+| REX + 88 /r | MOV r/m8***,r8*** | MR | Valid | N.E. | Move r8 to r/m8. |
+| 89 /r | MOV r/m16,r16 | MR | Valid | Valid | Move r16 to r/m16. |
+| 89 /r | MOV r/m32,r32 | MR | Valid | Valid | Move r32 to r/m32. |
+| REX.W + 89 /r | MOV r/m64,r64 | MR | Valid | N.E. | Move r64 to r/m64. |
+| 8A /r | MOV r8,r/m8 | RM | Valid | Valid | Move r/m8 to r8. |
+| REX + 8A /r | MOV r8***,r/m8*** | RM | Valid | N.E. | Move r/m8 to r8. |
+| 8B /r | MOV r16,r/m16 | RM | Valid | Valid | Move r/m16 to r16. |
+| 8B /r | MOV r32,r/m32 | RM | Valid | Valid | Move r/m32 to r32. |
+| REX.W + 8B /r | MOV r64,r/m64 | RM | Valid | N.E. | Move r/m64 to r64. |
+| 8C /r | MOV r/m16,Sreg** | MR | Valid | Valid | Move segment register to r/m16. |
+| REX.W + 8C /r | MOV r/m64,Sreg** | MR | Valid | Valid | Move zero extended 16-bit segment register to r/m64. |
+| 8E /r | MOV Sreg,r/m16** | RM | Valid | Valid | Move r/m16 to segment register. |
+| REX.W + 8E /r | MOV Sreg,r/m64** | RM | Valid | Valid | Move lower 16 bits of r/m64 to segment register. |
+| A0 | MOV AL,moffs8* | FD | Valid | Valid | Move byte at (seg:offset) to AL. |
+| REX.W + A0 | MOV AL,moffs8* | FD | Valid | N.E. | Move byte at (offset) to AL. |
+| A1 | MOV AX,moffs16* | FD | Valid | Valid | Move word at (seg:offset) to AX. |
+| A1 | MOV EAX,moffs32* | FD | Valid | Valid | Move doubleword at (seg:offset) to EAX. |
+| REX.W + A1 | MOV RAX,moffs64* | FD | Valid | N.E. | Move quadword at (offset) to RAX. |
+| A2 | MOV moffs8,AL | TD | Valid | Valid | Move AL to (seg:offset). |
+| REX.W + A2 | MOV moffs8***,AL | TD | Valid | N.E. | Move AL to (offset). |
+| A3 | MOV moffs16*,AX | TD | Valid | Valid | Move AX to (seg:offset). |
+| A3 | MOV moffs32*,EAX | TD | Valid | Valid | Move EAX to (seg:offset). |
+| REX.W + A3 | MOV moffs64*,RAX | TD | Valid | N.E. | Move RAX to (offset). |
+| B0+ rb ib | MOV r8, imm8 | OI | Valid | Valid | Move imm8 to r8. |
+| REX + B0+ rb ib | MOV r8***, imm8 | OI | Valid | N.E. | Move imm8 to r8. |
+| B8+ rw iw | MOV r16, imm16 | OI | Valid | Valid | Move imm16 to r16. |
+| B8+ rd id | MOV r32, imm32 | OI | Valid | Valid | Move imm32 to r32. |
+| REX.W + B8+ rd io | MOV r64, imm64 | OI | Valid | N.E. | Move imm64 to r64. |
+| C6 /0 ib | MOV r/m8, imm8 | MI | Valid | Valid | Move imm8 to r/m8. |
+| REX + C6 /0 ib | MOV r/m8***, imm8 | MI | Valid | N.E. | Move imm8 to r/m8. |
+| C7 /0 iw | MOV r/m16, imm16 | MI | Valid | Valid | Move imm16 to r/m16. |
+| C7 /0 id | MOV r/m32, imm32 | MI | Valid | Valid | Move imm32 to r/m32. |
+| REX.W + C7 /0 id | MOV r/m64, imm32 | MI | Valid | N.E. | Move imm32 sign extended to 64-bits to r/m64. |
+
+- The moffs8, moffs16, moffs32 and moffs64 operands specify a simple offset relative to the segment base, where 8, 16, 32 and 64 refer to the
+size of the data. The address-size attribute of the instruction determines the size of the offset, either 16, 32 or 64 bits.
+
+- In 32-bit mode, the assembler may insert the 16-bit operand-size prefix with this instruction.
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+The MOV instruction cannot be used to load the CS register. Attempting to do so results in an invalid opcode exception (#UD). To load the CS
+register, use the far JMP, CALL, or RET instruction.
+
+If the destination operand is a segment register (DS, ES, FS, GS, or SS), the source operand must be a valid segment selector. In protected
+mode, moving a segment selector into a segment register automatically causes the segment descriptor information associated with that segment
+selector to be loaded into the hidden (shadow) part of the segment register. While loading this information, the segment selector and segment
+descriptor information is validated (see the "Operation" algorithm below). The segment descriptor data is obtained from the GDT or LDT entry
+for the specified segment selector.
+
+A NULL segment selector (values 0000-0003) can be loaded into the DS, ES, FS, and GS registers without causing a protection exception. However,
+any subsequent attempt to reference a segment whose corresponding segment register is loaded with a NULL value causes a general protection
+exception (#GP) and no memory reference occurs. Loading the SS register with a MOV instruction inhibits all interrupts until after the
+execution of the next instruc- tion. This operation allows a stack pointer to be loaded into the ESP register with the next instruction (MOV
+ESP, stack-pointer value) before an interrupt occurs. Be aware that the LSS instruction offers a more efficient method of loading the SS and
+ESP registers.
+
+When executing MOV Reg, Sreg, the processor copies the content of Sreg to the 16 least significant bits of the general-purpose register. The
+upper bits of the destination register are zero for most IA-32 processors (Pentium Pro processors and later) and all Intel 64 processors, with
+the exception that bits 31:16 are undefined for Intel Quark X1000 processors, Pentium and earlier processors.
+
+In 64-bit mode, the instruction's default operation size is 32 bits. Use of the REX.R prefix permits access to additional registers (R8-R15).
+Use of the REX.W prefix promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.
--- /dev/null
+ MUL - Unsigned Multiply
+
+## Description
+
+Performs an unsigned multiplication of the first operand (destination operand) and the second operand (source operand) and stores the result in
+the destination operand. The destination operand is an implied operand located in register AL, AX or EAX (depending on the size of the operand).
+The source operand is located in a general-purpose register or a memory location.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|-----------|-------|-------------|-------------|------------------------------------------------------------------------------|
+| F6 /4 | MUL r/m8 | M | Valid | Valid | Unsigned multiply (AX=AL*r/m8). |
+| REX + F6 /4 | MUL r/m8* | M | Valid | N.E. | Unsigned multiply (AX=AL*r/m8). |
+| F7 /4 | MUL r/m16 | M | Valid | Valid | Unsigned multiply (DX:AX=AX*r/m16). |
+| F7 /4 | MUL r/m32 | M | Valid | Valid | Unsigned multiply (EDX:EAX=EAX*r/m32). |
+| REX.W + F7 /4 | MUL r/m64 | M | Valid | N.E. | Unsigned multiply (RDX:RAX=RAX*r/m64). |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+The result is stored in register AX, register pair DX:AX, or register pair EDX:EAX (depending on the operand size), with the high-order bits of
+the product contained in register AH, DX, or EDX, respectively. If the high-order bits of the product are 0, the CF and OF flags are cleared;
+otherwise, the flags are set.
+
+In 64-bit mode, the instruction’s default operation size is 32 bits. Use of the REX.R prefix permits access to additional registers (R8-R15).
+Use of the REX.W prefix promotes operation to 64 bits.
--- /dev/null
+# NEG — Two's Complement Negation
+
+## Description
+
+Replaces the value of operand (the destination operand) with its two's complement. This operation is equivalent to subtracting the operand
+from 0. The destination operand is located in a general-purpose register or a memory location.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|------------|-------|-------------|-------------|-----------------------------------------------------------------------------|
+| F6 /3 | NEG r/m8 | M | Valid | Valid | Two's complement negate r/m8. |
+| REX + F6 /3 | NEG r/m8* | M | Valid | N.E. | Two's complement negate r/m8. |
+| F7 /3 | NEG r/m16 | M | Valid | Valid | Two's complement negate r/m16. |
+| F7 /3 | NEG r/m32 | M | Valid | Valid | Two's complement negate r/m32. |
+| REX.W + F7 /3 | NEG r/m64 | M | Valid | N.E. | Two's complement negate r/m64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+In 64-bit mode, the instruction’s default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional
+registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this
+section for encoding data and limits.
--- /dev/null
+# NOP - No Operation
+
+## Description
+
+This instruction performs no operation. It is a one-byte or multi-byte NOP that takes up space in the instruction stream but does not impact
+machine context, except for the EIP register.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|----------|-------------|-------|-------------|-------------|---------------------------------------------------------------------------------|
+| 90 | NOP | NP | Valid | Valid | One byte no-operation instruction. |
+| 0F 1F /0 | NOP r/m16 | M | Valid | Valid | Multi-byte no-operation instruction. |
+| 0F 1F /0 | NOP r/m32 | M | Valid | Valid | Multi-byte no-operation instruction. |
+
+## Information
+
+The multi-byte form of NOP is available on processors with model encoding:
+
+- CPUID.01H.EAX (Bytes 11:8) = 0110B or 1111B
+
+The multi-byte NOP instruction does not alter the content of a register and will not issue a memory operation. The instruction’s operation is
+the same in non-64-bit modes and 64-bit mode.
+
+## Operation
+
+The one-byte NOP instruction is an alias mnemonic for the XCHG (E)AX, (E)AX instruction. The multi-byte NOP instruction performs no operation
+on supported processors and generates undefined opcode exception on processors that do not support the multi-byte NOP instruction.
+
+The memory operand form of the instruction allows software to create a byte sequence of “no operation” as one instruction. For situations where
+multiple-byte NOPs are needed, the recommended operations (32-bit mode and 64-bit mode) are:
+
+- 2 bytes `66 NOP 66 90H`
+- 3 bytes `NOP DWORD ptr (EAX) 0F 1F 00H`
+- 4 bytes `NOP DWORD ptr (EAX + 00H) 0F 1F 40 00H`
+- 5 bytes `NOP DWORD ptr (EAX + EAX*1 + 00H) 0F 1F 44 00 00H`
+- 6 bytes `66 NOP DWORD ptr (EAX + EAX*1 + 00H) 66 0F 1F 44 00 00H`
+- 7 bytes `NOP DWORD ptr (EAX + 00000000H) 0F 1F 80 00 00 00 00H`
+- 8 bytes `NOP DWORD ptr (EAX + EAX*1 + 00000000H) 0F 1F 84 00 00 00 00 00H`
+- 9 bytes `66 NOP DWORD ptr (EAX + EAX*1 + 00000000H) 66 0F 1F 84 00 00 00 00 00H`
--- /dev/null
+# NOT — One's Complement Negation
+
+## Description
+
+Performs a bitwise NOT operation (each 1 is set to 0, and each 0 is set to 1) on the destination operand and stores the result in the
+destination operand location. The destination operand can be a register or a memory location.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|------------|-------|-------------|-------------|-----------------------------------------------------------------------------|
+| F6 /2 | NOT r/m8 | M | Valid | Valid | Reverse each bit of r/m8. |
+| REX + F6 /2 | NOT r/m8* | M | Valid | N.E. | Reverse each bit of r/m8. |
+| F7 /2 | NOT r/m16 | M | Valid | Valid | Reverse each bit of r/m16. |
+| F7 /2 | NOT r/m32 | M | Valid | Valid | Reverse each bit of r/m32. |
+| REX.W + F7 /2 | NOT r/m64 | M | Valid | N.E. | Reverse each bit of r/m64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+In 64-bit mode, the instruction’s default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional
+registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this
+section for encoding data and limits.
--- /dev/null
+# OR — Logical Inclusive Or
+
+## Description
+
+Performs a bitwise inclusive OR operation between the destination (first) and source (second) operands and stores the result in the destination
+operand location. The source operand can be an immediate, a register, or a memory location; the destination operand can be a register or a
+memory location. However, two memory operands cannot be used in one instruction. Each bit of the result of the OR instruction is set to 0 if
+both corresponding bits of the first and second operands are 0; otherwise, each bit is set to 1.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|-----------------|-------|-------------|-------------|---------------------------------------------------------------------|
+| 0C ib | OR AL, imm8 | I | Valid | Valid | AL OR imm8. |
+| 0D iw | OR AX, imm16 | I | Valid | Valid | AX OR imm16. |
+| 0D id | OR EAX, imm32 | I | Valid | Valid | EAX OR imm32. |
+| REX.W + 0D id | OR RAX, imm32 | I | Valid | N.E. | RAX OR imm32 (sign-extended). |
+| 80 /1 ib | OR r/m8, imm8 | MI | Valid | Valid | r/m8 OR imm8. |
+| REX + 80 /1 ib | OR r/m8*, imm8 | MI | Valid | N.E. | r/m8 OR imm8. |
+| 81 /1 iw | OR r/m16, imm16 | MI | Valid | Valid | r/m16 OR imm16. |
+| 81 /1 id | OR r/m32, imm32 | MI | Valid | Valid | r/m32 OR imm32. |
+| REX.W + 81 /1 id | OR r/m64, imm32 | MI | Valid | N.E. | r/m64 OR imm32 (sign-extended). |
+| 83 /1 ib | OR r/m16, imm8 | MI | Valid | Valid | r/m16 OR imm8 (sign-extended). |
+| 83 /1 ib | OR r/m32, imm8 | MI | Valid | Valid | r/m32 OR imm8 (sign-extended). |
+| REX.W + 83 /1 ib | OR r/m64, imm8 | MI | Valid | N.E. | r/m64 OR imm8 (sign-extended). |
+| 08 /r | OR r/m8, r8 | MR | Valid | Valid | r/m8 OR r8. |
+| REX + 08 /r | OR r/m8*, r8* | MR | Valid | N.E. | r/m8 OR r8. |
+| 09 /r | OR r/m16, r16 | MR | Valid | Valid | r/m16 OR r16. |
+| 09 /r | OR r/m32, r32 | MR | Valid | Valid | r/m32 OR r32. |
+| REX.W + 09 /r | OR r/m64, r64 | MR | Valid | N.E. | r/m64 OR r64. |
+| 0A /r | OR r8, r/m8 | RM | Valid | Valid | r8 OR r/m8. |
+| REX + 0A /r | OR r8*, r/m8* | RM | Valid | N.E. | r8 OR r/m8. |
+| 0B /r | OR r16, r/m16 | RM | Valid | Valid | r16 OR r/m16. |
+| 0B /r | OR r32, r/m32 | RM | Valid | Valid | r32 OR r/m32. |
+| REX.W + 0B /r | OR r64, r/m64 | RM | Valid | N.E. | r64 OR r/m64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+In 64-bit mode, the instruction's default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional
+registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this
+section for encoding data and limits.
--- /dev/null
+# POP — Pop a Value from the Stack
+
+## Description
+
+Loads the value from the top of the stack to the location specified with the destination operand (or explicit opcode) and then increments the
+stack pointer. The destination operand can be a general-purpose register, memory location, or segment register.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|--------|-------------|-------|-------------|-------------|-----------------------------------------------------------------------------------|
+| 8F /0 | POP r/m16 | M | Valid | Valid | Pop top of stack into m16, increment stack pointer. |
+| 8F /0 | POP r/m32 | M | N.E. | Valid | Pop top of stack into m32, increment stack pointer. |
+| 8F /0 | POP r/m64 | M | Valid | N.E. | Pop top of stack into m64, increment stack pointer. |
+| 58+rw | POP r16 | O | Valid | Valid | Pop top of stack into r16, increment stack pointer. |
+| 58+rd | POP r32 | O | N.E. | Valid | Pop top of stack into r32, increment stack pointer. |
+| 58+rd | POP r64 | O | Valid | N.E. | Pop top of stack into r64, increment stack pointer. |
+| 1F | POP DS | NP | Invalid | Valid | Pop top of stack into DS, increment stack pointer. |
+| 07 | POP ES | NP | Invalid | Valid | Pop top of stack into ES, increment stack pointer. |
+| 17 | POP SS | NP | Invalid | Valid | Pop top of stack into SS, increment stack pointer. |
+| 0F A1 | POP FS | NP | Valid | Valid | Pop top of stack into FS, increment stack pointer by 16 bits. |
+| 0F A1 | POP FS | NP | N.E. | Valid | Pop top of stack into FS, increment stack pointer by 32 bits. |
+| 0F A1 | POP FS | NP | Valid | N.E. | Pop top of stack into FS, increment stack pointer by 64 bits. |
+| 0F A9 | POP GS | NP | Valid | Valid | Pop top of stack into GS, increment stack pointer by 16 bits. |
+| 0F A9 | POP GS | NP | N.E. | Valid | Pop top of stack into GS, increment stack pointer by 32 bits. |
+| 0F A9 | POP GS | NP | Valid | N.E. | Pop top of stack into GS, increment stack pointer by 64 bits. |
+
+## Information
+
+Address and operand sizes are determined and used as follows:
+
+- Address size: The D flag in the current code-segment descriptor determines the default address size; it may be overridden by an instruction
+prefix (67H). The address size is used only when writing to a destination operand in memory.
+
+- Operand size: The D flag in the current code-segment descriptor determines the default operand size; it may be overridden by instruction
+prefixes (66H or REX.W). The operand size (16, 32, or 64 bits) determines the amount by which the stack pointer is incremented (2, 4 or 8).
+
+- Stack-address size: Outside of 64-bit mode, the B flag in the current stack-segment descriptor determines the size of the stack pointer (16
+or 32 bits); in 64-bit mode, the size of the stack pointer is always 64 bits.The stack-address size determines the width of the stack pointer
+when reading from the stack in memory and when incrementing the stack pointer. (As stated above, the amount by which the stack pointer is
+incremented is determined by the operand size.)
+
+If the destination operand is one of the segment registers DS, ES, FS, GS, or SS, the value loaded into the register must be a valid segment
+selector. In protected mode, popping a segment selector into a segment register automat- ically causes the descriptor information associated
+with that segment selector to be loaded into the hidden (shadow) part of the segment register and causes the selector and the descriptor
+information to be validated (see the "Operation" section below).
+
+A NULL value (0000-0003) may be popped into the DS, ES, FS, or GS register without causing a general protection fault. However, any subsequent
+attempt to reference a segment whose corresponding segment register is loaded with a NULL value causes a general protection exception (#GP). In
+this situation, no memory reference occurs and the saved value of the segment register is NULL.
+
+The POP instruction cannot pop a value into the CS register. To load the CS register from the stack, use the RET instruction.
+
+If the ESP register is used as a base register for addressing a destination operand in memory, the POP instruction computes the effective
+address of the operand after it increments the ESP register. For the case of a 16-bit stack where ESP wraps to 0H as a result of the POP
+instruction, the resulting location of the memory write is processor- family-specific.
+
+The POP ESP instruction increments the stack pointer (ESP) before data at the old top of stack is written into the destination.
+
+A POP SS instruction inhibits all interrupts, including the NMI interrupt, until after execution of the next instruction. This action allows
+sequential execution of POP SS and MOV ESP, EBP instructions without the danger of having an invalid stack during an interrupt1 . However, use
+of the LSS instruction is the preferred method of loading the SS and ESP registers.
+
+In 64-bit mode, using a REX prefix in the form of REX.R permits access to additional registers (R8-R15). When in 64-bit mode, POPs using 32-bit
+operands are not encodable and POPs to DS, ES, SS are not valid. See the summary chart at the beginning of this section for encoding data and
+limits.
--- /dev/null
+# PUSH — Push Word, Doubleword or Quadword Onto the Stack
+
+## Description
+
+Decrements the stack pointer and then stores the source operand on the top of the stack.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|--------|-------------|-------|-------------|-------------|-----------------------------------------------------------------------------------|
+| FF /6 | PUSH r/m16 | M | Valid | Valid | Decrement stack pointer, push r/m16 onto top of stack. |
+| FF /6 | PUSH r/m32 | M | N.E. | Valid | Decrement stack pointer, push r/m32 onto top of stack. |
+| FF /6 | PUSH r/m64 | M | Valid | N.E. | Decrement stack pointer, push r/m64 onto top of stack. |
+| 50+rw | PUSH r16 | O | Valid | Valid | Decrement stack pointer, push r16 onto top of stack. |
+| 50+rd | PUSH r32 | O | N.E. | Valid | Decrement stack pointer, push r32 onto top of stack. |
+| 50+rd | PUSH r64 | O | Valid | N.E. | Decrement stack pointer, push r64 onto top of stack. |
+| 6A ib | PUSH imm8 | I | Valid | Valid | Decrement stack pointer, push imm8 onto top of stack. |
+| 68 iw | PUSH imm16 | I | Valid | Valid | Decrement stack pointer, push imm16 onto top of stack. |
+| 68 id | PUSH imm32 | I | Valid | Valid | Decrement stack pointer, push imm32 onto top of stack. |
+| 0E | PUSH CS | NP | Invalid | Valid | Decrement stack pointer, push CS onto top of stack. |
+| 16 | PUSH SS | NP | Invalid | Valid | Decrement stack pointer, push SS onto top of stack. |
+| 1E | PUSH DS | NP | Invalid | Valid | Decrement stack pointer, push DS onto top of stack. |
+| 06 | PUSH ES | NP | Invalid | Valid | Decrement stack pointer, push ES onto top of stack. |
+| 0F A0 | PUSH FS | NP | Valid | Valid | Decrement stack pointer, push FS onto top of stack. |
+| 0F A8 | PUSH GS | NP | Valid | Valid | Decrement stack pointer, push GS onto top of stack. |
+
+## Information
+
+Address and operand sizes are determined and used as follows:
+
+- Address size: The D flag in the current code-segment descriptor determines the default address size; it may be overridden by an instruction
+prefix (67H). The address size is used only when referencing a source operand in memory.
+
+- Operand size: The D flag in the current code-segment descriptor determines the default operand size; it may be overridden by instruction
+prefixes (66H or REX.W). The operand size (16, 32, or 64 bits) determines the amount by which the stack pointer is decremented (2, 4 or 8). If
+the source operand is an immediate of size less than the operand size, a sign-extended value is pushed on the stack. If the source operand is a
+segment register (16 bits) and the operand size is 64-bits, a zero- extended value is pushed on the stack; if the operand size is 32-bits,
+either a zero-extended value is pushed on the stack or the segment selector is written on the stack using a 16-bit move. For the last case, all
+recent Core and Atom processors perform a 16-bit move, leaving the upper portion of the stack location unmodified.
+
+- Stack-address size: Outside of 64-bit mode, the B flag in the current stack-segment descriptor determines the size of the stack pointer (16
+or 32 bits); in 64-bit mode, the size of the stack pointer is always 64 bits. The stack-address size determines the width of the stack pointer
+when writing to the stack in memory and when decrementing the stack pointer. (As stated above, the amount by which the stack pointer is
+decremented is determined by the operand size.) If the operand size is less than the stack-address size, the PUSH instruction may result in a
+misaligned stack pointer (a stack pointer that is not aligned on a doubleword or quadword boundary).
+
+The PUSH ESP instruction pushes the value of the ESP register as it existed before the instruction was executed. If a PUSH instruction uses a
+memory operand in which the ESP register is used for computing the operand address, the address of the operand is computed before the ESP
+register is decremented.
+
+If the ESP or SP register is 1 when the PUSH instruction is executed in real-address mode, a stack-fault exception (#SS) is generated (because
+the limit of the stack segment is violated). Its delivery encounters a second stack- fault exception (for the same reason), causing generation
+of a double-fault exception (#DF). Delivery of the double-fault exception encounters a third stack-fault exception, and the logical processor
+enters shutdown mode. See the discussion of the double-fault exception in Chapter 6 of the Intel® 64 and IA-32 Architectures Software
+Developer's Manual, Volume 3A.
--- /dev/null
+# RET — Return from Procedure
+
+## Description
+
+Transfers program control to a return address located on the top of the stack. The address is usually placed on the stack by a CALL
+instruction, and the return is made to the instruction that follows the CALL instruction.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|--------|-----------|-------|-------------|-------------|-------------------------------------------------------------------------------------|
+| C3 | RET | NP | Valid | Valid | Near return to calling procedure. |
+| CB | RET | NP | Valid | Valid | Far return to calling procedure. |
+| C2 iw | RET imm16 | I | Valid | Valid | Near return to calling procedure and pop imm16 bytes from stack. |
+| CA iw | RET imm16 | I | Valid | Valid | Far return to calling procedure and pop imm16 bytes from stack. |
+
+## Information
+
+The optional source operand specifies the number of stack bytes to be released after the return address is popped; the default is none. This
+operand can be used to release parameters from the stack that were passed to the called procedure and are no longer needed. It must be used
+when the CALL instruction used to switch to a new procedure uses a call gate with a non-zero word count to access the new procedure. Here, the
+source operand for the RET instruction must specify the same number of bytes as is specified in the word count field of the call gate.
+
+The RET instruction can be used to execute three different types of returns:
+
+• Near return — A return to a calling procedure within the current code segment (the segment currently pointed to by the CS register),
+sometimes referred to as an intrasegment return.
+
+• Far return — A return to a calling procedure located in a different segment than the current code segment, sometimes referred to as an
+intersegment return.
+
+• Inter-privilege-level far return — A far return to a different privilege level than that of the currently executing program or procedure.
+
+The inter-privilege-level return type can only be executed in protected mode. See the section titled "Calling Procedures Using Call and RET" in
+Chapter 6 of the Intel® 64 and IA-32 Architectures Software Developer's Manual, Volume 1, for detailed information on near, far, and inter
+privilege level returns.
+
+When executing a near return, the processor pops the return instruction pointer (offset) from the top of the stack into the EIP register and
+begins program execution at the new instruction pointer. The CS register is unchanged. When executing a far return, the processor pops the
+return instruction pointer from the top of the stack into the EIP register, then pops the segment selector from the top of the stack into the
+CS register. The processor then begins program execution in the new code segment at the new instruction pointer.
+
+The mechanics of an inter-privilege-level far return are similar to an intersegment return, except that the processor examines the privilege
+levels and access rights of the code and stack segments being returned to determine if the control transfer is allowed to be made. The DS, ES,
+FS, and GS segment registers are cleared by the RET instruction during an inter-privilege-level return if they refer to segments that are not
+allowed to be accessed at the new privilege level. Since a stack switch also occurs on an inter-privilege level return, the ESP and SS
+registers are loaded from the stack.
+
+If parameters are passed to the called procedure during an inter-privilege level call, the optional source operand must be used with the RET
+instruction to release the parameters on the return. Here, the parameters are released both from the called procedure's stack and the calling
+procedure's stack (that is, the stack being returned to). In 64-bit mode, the default operation size of this instruction is the stack-address
+size, i.e. 64 bits. This applies to near returns, not far returns; the default operation size of far returns is 32 bits.
--- /dev/null
+# RCL/RCR/ROL/ROR — Rotate
+
+## Description
+
+Shifts (rotates) the bits of the first operand (destination operand) the number of bit positions specified in the second operand (count
+operand) and stores the result in the destination operand. The destination operand can be a register or a memory location; the count operand is
+an unsigned integer that can be an immediate or a value in the CL register. The count is masked to 5 bits (or 6 bits if in 64-bit mode and
+REX.W = 1).
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|-----------------|-------|-------------|-------------|---------------------------------------------------------------------|
+| D0 /2 | RCL r/m8, 1 | M1 | Valid | Valid | Rotate 9 bits (CF, r/m8) left once. |
+| REX + D0 /2 | RCL r/m8*, 1 | M1 | Valid | N.E. | Rotate 9 bits (CF, r/m8) left once. |
+| D2 /2 | RCL r/m8, CL | MC | Valid | Valid | Rotate 9 bits (CF, r/m8) left CL times. |
+| REX + D2 /2 | RCL r/m8*, CL | MC | Valid | N.E. | Rotate 9 bits (CF, r/m8) left CL times. |
+| C0 /2 ib | RCL r/m8, imm8 | MI | Valid | Valid | Rotate 9 bits (CF, r/m8) left imm8 times. |
+| REX + C0 /2 ib | RCL r/m8*, imm8 | MI | Valid | N.E. | Rotate 9 bits (CF, r/m8) left imm8 times. |
+| D1 /2 | RCL r/m16, 1 | M1 | Valid | Valid | Rotate 17 bits (CF, r/m16) left once. |
+| D3 /2 | RCL r/m16, CL | MC | Valid | Valid | Rotate 17 bits (CF, r/m16) left CL times. |
+| C1 /2 ib | RCL r/m16, imm8 | MI | Valid | Valid | Rotate 17 bits (CF, r/m16) left imm8 times. |
+| D1 /2 | RCL r/m32, 1 | M1 | Valid | Valid | Rotate 33 bits (CF, r/m32) left once. |
+| REX.W + D1 /2 | RCL r/m64, 1 | M1 | Valid | N.E. | Rotate 65 bits (CF, r/m64) left once. |
+| D3 /2 | RCL r/m32, CL | MC | Valid | Valid | Rotate 33 bits (CF, r/m32) left CL times. |
+| REX.W + D3 /2 | RCL r/m64, CL | MC | Valid | N.E. | Rotate 65 bits (CF, r/m64) left CL times. |
+| C1 /2 ib | RCL r/m32, imm8 | MI | Valid | Valid | Rotate 33 bits (CF, r/m32) left imm8 times. |
+| REX.W + C1 /2 ib | RCL r/m64, imm8 | MI | Valid | N.E. | Rotate 65 bits (CF, r/m64) left imm8 times. |
+| D0 /3 | RCR r/m8, 1 | M1 | Valid | Valid | Rotate 9 bits (CF, r/m8) right once. |
+| REX + D0 /3 | RCR r/m8*, 1 | M1 | Valid | N.E. | Rotate 9 bits (CF, r/m8) right once. |
+| D2 /3 | RCR r/m8, CL | MC | Valid | Valid | Rotate 9 bits (CF, r/m8) right CL times. |
+| REX + D2 /3 | RCR r/m8*, CL | MC | Valid | N.E. | Rotate 9 bits (CF, r/m8) right CL times. |
+| C0 /3 ib | RCR r/m8, imm8 | MI | Valid | Valid | Rotate 9 bits (CF, r/m8) right imm8 times. |
+| REX + C0 /3 ib | RCR r/m8*, imm8 | MI | Valid | N.E. | Rotate 9 bits (CF, r/m8) right imm8 times. |
+| D1 /3 | RCR r/m16, 1 | M1 | Valid | Valid | Rotate 17 bits (CF, r/m16) right once. |
+| D3 /3 | RCR r/m16, CL | MC | Valid | Valid | Rotate 17 bits (CF, r/m16) right CL times. |
+| C1 /3 ib | RCR r/m16, imm8 | MI | Valid | Valid | Rotate 17 bits (CF, r/m16) right imm8 times. |
+| D1 /3 | RCR r/m32, 1 | M1 | Valid | Valid | Rotate 33 bits (CF, r/m32) right once. |
+| REX.W + D1 /3 | RCR r/m64, 1 | M1 | Valid | N.E. | Rotate 65 bits (CF, r/m64) right once. |
+| D3 /3 | RCR r/m32, CL | MC | Valid | Valid | Rotate 33 bits (CF, r/m32) right CL times. |
+| REX.W + D3 /3 | RCR r/m64, CL | MC | Valid | N.E. | Rotate 65 bits (CF, r/m64) right CL times. |
+| C1 /3 ib | RCR r/m32, imm8 | MI | Valid | Valid | Rotate 33 bits (CF, r/m32) right imm8 times. |
+| REX.W + C1 /3 ib | RCR r/m64, imm8 | MI | Valid | N.E. | Rotate 65 bits (CF, r/m64) right imm8 times. |
+| D0 /0 | ROL r/m8, 1 | M1 | Valid | Valid | Rotate 8 bits r/m8 left once. |
+| REX + D0 /0 | ROL r/m8*, 1 | M1 | Valid | N.E. | Rotate 8 bits r/m8 left once |
+| D2 /0 | ROL r/m8, CL | MC | Valid | Valid | Rotate 8 bits r/m8 left CL times. |
+| REX + D2 /0 | ROL r/m8*, CL | MC | Valid | N.E. | Rotate 8 bits r/m8 left CL times. |
+| C0 /0 ib | ROL r/m8, imm8 | MI | Valid | Valid | Rotate 8 bits r/m8 left imm8 times. |
+| REX + C0 /0 ib | ROL r/m8*, imm8 | MI | Valid | N.E. | Rotate 8 bits r/m8 left imm8 times. |
+| D1 /0 | ROL r/m16, 1 | M1 | Valid | Valid | Rotate 16 bits r/m16 left once. |
+| D3 /0 | ROL r/m16, CL | MC | Valid | Valid | Rotate 16 bits r/m16 left CL times. |
+| C1 /0 ib | ROL r/m16, imm8 | MI | Valid | Valid | Rotate 16 bits r/m16 left imm8 times. |
+| D1 /0 | ROL r/m32, 1 | M1 | Valid | Valid | Rotate 32 bits r/m32 left once. |
+| REX.W + D1 /0 | ROL r/m64, 1 | M1 | Valid | N.E. | Rotate 64 bits r/m64 left once. |
+| D3 /0 | ROL r/m32, CL | MC | Valid | Valid | Rotate 32 bits r/m32 left CL times. |
+| REX.W + D3 /0 | ROL r/m64, CL | MC | Valid | N.E. | Rotate 64 bits r/m64 left CL times. |
+| C1 /0 ib | ROL r/m32, imm8 | MI | Valid | Valid | Rotate 32 bits r/m32 left imm8 times. |
+| REX.W + C1 /0 ib | ROL r/m64, imm8 | MI | Valid | N.E. | Rotate 64 bits r/m64 left imm8 times. |
+| D0 /1 | ROR r/m8, 1 | M1 | Valid | Valid | Rotate 8 bits r/m8 right once. |
+| REX + D0 /1 | ROR r/m8*, 1 | M1 | Valid | N.E. | Rotate 8 bits r/m8 right once. |
+| D2 /1 | ROR r/m8, CL | MC | Valid | Valid | Rotate 8 bits r/m8 right CL times. |
+| REX + D2 /1 | ROR r/m8*, CL | MC | Valid | N.E. | Rotate 8 bits r/m8 right CL times. |
+| C0 /1 ib | ROR r/m8, imm8 | MI | Valid | Valid | Rotate 8 bits r/m16 right imm8 times. |
+| REX + C0 /1 ib | ROR r/m8*, imm8 | MI | Valid | N.E. | Rotate 8 bits r/m16 right imm8 times. |
+| D1 /1 | ROR r/m16, 1 | M1 | Valid | Valid | Rotate 16 bits r/m16 right once. |
+| D3 /1 | ROR r/m16, CL | MC | Valid | Valid | Rotate 16 bits r/m16 right CL times. |
+| C1 /1 ib | ROR r/m16, imm8 | MI | Valid | Valid | Rotate 16 bits r/m16 right imm8 times. |
+| D1 /1 | ROR r/m32, 1 | M1 | Valid | Valid | Rotate 32 bits r/m32 right once. |
+| REX.W + D1 /1 | ROR r/m64, 1 | M1 | Valid | N.E. | Rotate 64 bits r/m64 right once. |
+| D3 /1 | ROR r/m32, CL | MC | Valid | Valid | Rotate 32 bits r/m32 right CL times. |
+| REX.W + D3 /1 | ROR r/m64, CL | MC | Valid | N.E. | Rotate 64 bits r/m64 right CL times. |
+| C1 /1 ib | ROR r/m32, imm8 | MI | Valid | Valid | Rotate 32 bits r/m32 right imm8 times. |
+| REX.W + C1 /1 ib | ROR r/m64, imm8 | MI | Valid | N.E. | Rotate 64 bits r/m64 right imm8 times. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+The rotate left (ROL) and rotate through carry left (RCL) instructions shift all the bits toward more-significant bit positions, except for the
+most-significant bit, which is rotated to the least-significant bit location. The rotate right (ROR) and rotate through carry right (RCR)
+instructions shift all the bits toward less significant bit positions, except for the least-significant bit, which is rotated to the
+most-significant bit location.
+
+The RCL and RCR instructions include the CF flag in the rotation. The RCL instruction shifts the CF flag into the least-significant bit and
+shifts the most-significant bit into the CF flag. The RCR instruction shifts the CF flag into the most-significant bit and shifts the
+least-significant bit into the CF flag. For the ROL and ROR instructions, the original value of the CF flag is not a part of the result, but
+the CF flag receives a copy of the bit that was shifted from one end to the other.
+
+The OF flag is defined only for the 1-bit rotates; it is undefined in all other cases (except RCL and RCR instructions only: a zero-bit rotate
+does nothing, that is affects no flags). For left rotates, the OF flag is set to the exclusive OR of the CF bit (after the rotate) and the
+most-significant bit of the result. For right rotates, the OF flag is set to the exclusive OR of the two most-significant bits of the result.
+
+In 64-bit mode, using a REX prefix in the form of REX.R permits access to additional registers (R8-R15). Use of REX.W promotes the first
+operand to 64 bits and causes the count operand to become a 6-bit counter.
--- /dev/null
+# SBB — Subtraction with Borrow
+
+## Description
+
+Adds the source operand (second operand) and the carry (CF) flag, and subtracts the result from the destination operand (first operand). The
+result of the subtraction is stored in the destination operand. The destination operand can be a register or a memory location; the source
+operand can be an immediate, a register, or a memory location. However, two memory operands cannot be used in one instruction. The state of
+the CF flag represents a borrow from a previous subtraction.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|------------------|-------|-------------|-------------|--------------------------------------------------------------------|
+| 1C ib | SBB AL, imm8 | I | Valid | Valid | Subtract with borrow imm8 from AL. |
+| 1D iw | SBB AX, imm16 | I | Valid | Valid | Subtract with borrow imm16 from AX. |
+| 1D id | SBB EAX, imm32 | I | Valid | Valid | Subtract with borrow imm32 from EAX. |
+| REX.W + 1D id | SBB RAX, imm32 | I | Valid | N.E. | Subtract with borrow sign-extended imm32 to 64-bits from RAX. |
+| 80 /3 ib | SBB r/m8, imm8 | MI | Valid | Valid | Subtract with borrow imm8 from r/m8. |
+| REX + 80 /3 ib | SBB r/m8*, imm8 | MI | Valid | N.E. | Subtract with borrow imm8 from r/m8. |
+| 81 /3 iw | SBB r/m16, imm16 | MI | Valid | Valid | Subtract with borrow imm16 from r/m16. |
+| 81 /3 id | SBB r/m32, imm32 | MI | Valid | Valid | Subtract with borrow imm32 from r/m32. |
+| REX.W + 81 /3 id | SBB r/m64, imm32 | MI | Valid | N.E. | Subtract with borrow sign-extended imm32 to 64-bits from r/m64. |
+| 83 /3 ib | SBB r/m16, imm8 | MI | Valid | Valid | Subtract with borrow sign-extended imm8 from r/m16. |
+| 83 /3 ib | SBB r/m32, imm8 | MI | Valid | Valid | Subtract with borrow sign-extended imm8 from r/m32. |
+| REX.W + 83 /3 ib | SBB r/m64, imm8 | MI | Valid | N.E. | Subtract with borrow sign-extended imm8 from r/m64. |
+| 18 /r | SBB r/m8, r8 | MR | Valid | Valid | Subtract with borrow r8 from r/m8. |
+| REX + 18 /r | SBB r/m8*, r8 | MR | Valid | N.E. | Subtract with borrow r8 from r/m8. |
+| 19 /r | SBB r/m16, r16 | MR | Valid | Valid | Subtract with borrow r16 from r/m16. |
+| 19 /r | SBB r/m32, r32 | MR | Valid | Valid | Subtract with borrow r32 from r/m32. |
+| REX.W + 19 /r | SBB r/m64, r64 | MR | Valid | N.E. | Subtract with borrow r64 from r/m64. |
+| 1A /r | SBB r8, r/m8 | RM | Valid | Valid | Subtract with borrow r/m8 from r8. |
+| REX + 1A /r | SBB r8*, r/m8* | RM | Valid | N.E. | Subtract with borrow r/m8 from r8. |
+| 1B /r | SBB r16, r/m16 | RM | Valid | Valid | Subtract with borrow r/m16 from r16. |
+| 1B /r | SBB r32, r/m32 | RM | Valid | Valid | Subtract with borrow r/m32 from r32. |
+| REX.W + 1B /r | SBB r64, r/m64 | RM | Valid | N.E. | Subtract with borrow r/m64 from r64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+When an immediate value is used as an operand, it is sign-extended to the length of the destination operand format.
+
+The SBB instruction does not distinguish between signed or unsigned operands. Instead, the processor evaluates the result for both data types
+and sets the OF and CF flags to indicate a borrow in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed
+result.
+
+The SBB instruction is usually executed as part of a multibyte or multiword subtraction in which a SUB instruction is followed by a SBB
+instruction.
+
+In 64-bit mode, the instruction's default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional
+registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this
+section for encoding data and limits.
--- /dev/null
+# SETcc — Set Byte on Condition
+
+## Description
+
+Sets the destination operand to 0 or 1 depending on the settings of the status flags (CF, SF, OF, ZF, and PF) in the EFLAGS register. The
+destination operand points to a byte register or a byte in memory. The condition code suffix (cc) indicates the condition being tested for.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|-------------|--------------|-------|-------------|-------------|-----------------------------------------------------------------------------|
+| 0F 97 | SETA r/m8 | M | Valid | Valid | Set byte if above (CF=0 and ZF=0). |
+| REX + 0F 97 | SETA r/m8* | M | Valid | N.E. | Set byte if above (CF=0 and ZF=0). |
+| 0F 93 | SETAE r/m8 | M | Valid | Valid | Set byte if above or equal (CF=0). |
+| REX + 0F 93 | SETAE r/m8* | M | Valid | N.E. | Set byte if above or equal (CF=0). |
+| 0F 92 | SETB r/m8 | M | Valid | Valid | Set byte if below (CF=1). |
+| REX + 0F 92 | SETB r/m8* | M | Valid | N.E. | Set byte if below (CF=1). |
+| 0F 96 | SETBE r/m8 | M | Valid | Valid | Set byte if below or equal (CF=1 or ZF=1). |
+| REX + 0F 96 | SETBE r/m8* | M | Valid | N.E. | Set byte if below or equal (CF=1 or ZF=1). |
+| 0F 92 | SETC r/m8 | M | Valid | Valid | Set byte if carry (CF=1). |
+| REX + 0F 92 | SETC r/m8* | M | Valid | N.E. | Set byte if carry (CF=1). |
+| 0F 94 | SETE r/m8 | M | Valid | Valid | Set byte if equal (ZF=1). |
+| REX + 0F 94 | SETE r/m8* | M | Valid | N.E. | Set byte if equal (ZF=1). |
+| 0F 9F | SETG r/m8 | M | Valid | Valid | Set byte if greater (ZF=0 and SF=OF). |
+| REX + 0F 9F | SETG r/m8* | M | Valid | N.E. | Set byte if greater (ZF=0 and SF=OF). |
+| 0F 9D | SETGE r/m8 | M | Valid | Valid | Set byte if greater or equal (SF=OF). |
+| REX + 0F 9D | SETGE r/m8* | M | Valid | N.E. | Set byte if greater or equal (SF=OF). |
+| 0F 9C | SETL r/m8 | M | Valid | Valid | Set byte if less (SF≠ OF). |
+| REX + 0F 9C | SETL r/m8* | M | Valid | N.E. | Set byte if less (SF≠ OF). |
+| 0F 9E | SETLE r/m8 | M | Valid | Valid | Set byte if less or equal (ZF=1 or SF≠ OF). |
+| REX + 0F 9E | SETLE r/m8* | M | Valid | N.E. | Set byte if less or equal (ZF=1 or SF≠ OF). |
+| 0F 96 | SETNA r/m8 | M | Valid | Valid | Set byte if not above (CF=1 or ZF=1). |
+| REX + 0F 96 | SETNA r/m8* | M | Valid | N.E. | Set byte if not above (CF=1 or ZF=1). |
+| 0F 92 | SETNAE r/m8 | M | Valid | Valid | Set byte if not above or equal (CF=1). |
+| REX + 0F 92 | SETNAE r/m8* | M | Valid | N.E. | Set byte if not above or equal (CF=1). |
+| 0F 93 | SETNB r/m8 | M | Valid | Valid | Set byte if not below (CF=0). |
+| REX + 0F 93 | SETNB r/m8* | M | Valid | N.E. | Set byte if not below (CF=0). |
+| 0F 97 | SETNBE r/m8 | M | Valid | Valid | Set byte if not below or equal (CF=0 and ZF=0). |
+| REX + 0F 97 | SETNBE r/m8* | M | Valid | N.E. | Set byte if not below or equal (CF=0 and ZF=0). |
+| 0F 93 | SETNC r/m8 | M | Valid | Valid | Set byte if not carry (CF=0). |
+| REX + 0F 93 | SETNC r/m8* | M | Valid | N.E. | Set byte if not carry (CF=0). |
+| 0F 95 | SETNE r/m8 | M | Valid | Valid | Set byte if not equal (ZF=0). |
+| REX + 0F 95 | SETNE r/m8* | M | Valid | N.E. | Set byte if not equal (ZF=0). |
+| 0F 9E | SETNG r/m8 | M | Valid | Valid | Set byte if not greater (ZF=1 or SF≠ OF) |
+| REX + 0F 9E | SETNG r/m8* | M | Valid | N.E. | Set byte if not greater (ZF=1 or SF≠ OF). |
+| 0F 9C | SETNGE r/m8 | M | Valid | Valid | Set byte if not greater or equal (SF≠ OF). |
+| REX + 0F 9C | SETNGE r/m8* | M | Valid | N.E. | Set byte if not greater or equal (SF≠ OF). |
+| 0F 9D | SETNL r/m8 | M | Valid | Valid | Set byte if not less (SF=OF). |
+| REX + 0F 9D | SETNL r/m8* | M | Valid | N.E. | Set byte if not less (SF=OF). |
+| 0F 9F | SETNLE r/m8 | M | Valid | Valid | Set byte if not less or equal (ZF=0 and SF=OF). |
+| REX + 0F 9F | SETNLE r/m8* | M | Valid | N.E. | Set byte if not less or equal (ZF=0 and SF=OF). |
+| 0F 91 | SETNO r/m8 | M | Valid | Valid | Set byte if not overflow (OF=0). |
+| REX + 0F 91 | SETNO r/m8* | M | Valid | N.E. | Set byte if not overflow (OF=0). |
+| 0F 9B | SETNP r/m8 | M | Valid | Valid | Set byte if not parity (PF=0). |
+| REX + 0F 9B | SETNP r/m8* | M | Valid | N.E. | Set byte if not parity (PF=0). |
+| 0F 99 | SETNS r/m8 | M | Valid | Valid | Set byte if not sign (SF=0). |
+| REX + 0F 99 | SETNS r/m8* | M | Valid | N.E. | Set byte if not sign (SF=0). |
+| 0F 95 | SETNZ r/m8 | M | Valid | Valid | Set byte if not zero (ZF=0). |
+| REX + 0F 95 | SETNZ r/m8* | M | Valid | N.E. | Set byte if not zero (ZF=0). |
+| 0F 90 | SETO r/m8 | M | Valid | Valid | Set byte if overflow (OF=1) |
+| REX + 0F 90 | SETO r/m8* | M | Valid | N.E. | Set byte if overflow (OF=1). |
+| 0F 9A | SETP r/m8 | M | Valid | Valid | Set byte if parity (PF=1). |
+| REX + 0F 9A | SETP r/m8* | M | Valid | N.E. | Set byte if parity (PF=1). |
+| 0F 9A | SETPE r/m8 | M | Valid | Valid | Set byte if parity even (PF=1). |
+| REX + 0F 9A | SETPE r/m8* | M | Valid | N.E. | Set byte if parity even (PF=1). |
+| 0F 9B | SETPO r/m8 | M | Valid | Valid | Set byte if parity odd (PF=0). |
+| REX + 0F 9B | SETPO r/m8* | M | Valid | N.E. | Set byte if parity odd (PF=0). |
+| 0F 98 | SETS r/m8 | M | Valid | Valid | Set byte if sign (SF=1). |
+| REX + 0F 98 | SETS r/m8* | M | Valid | N.E. | Set byte if sign (SF=1). |
+| 0F 94 | SETZ r/m8 | M | Valid | Valid | Set byte if zero (ZF=1). |
+| REX + 0F 94 | SETZ r/m8* | M | Valid | N.E. | Set byte if zero (ZF=1). |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+The terms “above” and “below” are associated with the CF flag and refer to the relationship between two unsigned integer values. The terms
+“greater” and “less” are associated with the SF and OF flags and refer to the relationship between two signed integer values.
+
+Many of the SETcc instruction opcodes have alternate mnemonics. For example, SETG (set byte if greater) and SETNLE (set if not less or equal)
+have the same opcode and test for the same condition: ZF equals 0 and SF equals OF. These alternate mnemonics are provided to make code more
+intelligible.
+
+Some languages represent a logical one as an integer with all bits set. This representation can be obtained by choosing the logically opposite
+condition for the SETcc instruction, then decrementing the result. For example, to test for overflow, use the SETNO instruction, then decrement
+the result.
+
+In IA-64 mode, the operand size is fixed at 8 bits. Use of REX prefix enable uniform addressing to additional byte registers. Otherwise, this
+instruction’s operation is the same as in legacy mode and compatibility mode.
--- /dev/null
+# SAL/SAR/SHL/SHR — Shift
+
+## Description
+
+Shifts the bits in the first operand (destination operand) to the left or right by the number of bits specified in the second operand (count
+operand). Bits shifted beyond the destination operand boundary are first shifted into the CF flag, then discarded. At the end of the shift
+operation, the CF flag contains the last bit shifted out of the destination operand.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|------------------|-------|-------------|-------------|--------------------------------------------------------------------|
+| D0 /4 | SAL r/m8, 1 | M1 | Valid | Valid | Multiply r/m8 by 2, once. |
+| REX + D0 /4 | SAL r/m8**, 1 | M1 | Valid | N.E. | Multiply r/m8 by 2, once. |
+| D2 /4 | SAL r/m8, CL | MC | Valid | Valid | Multiply r/m8 by 2, CL times. |
+| REX + D2 /4 | SAL r/m8**, CL | MC | Valid | N.E. | Multiply r/m8 by 2, CL times. |
+| C0 /4 ib | SAL r/m8, imm8 | MI | Valid | Valid | Multiply r/m8 by 2, imm8 times. |
+| REX + C0 /4 ib | SAL r/m8**, imm8 | MI | Valid | N.E. | Multiply r/m8 by 2, imm8 times. |
+| D1 /4 | SAL r/m16, 1 | M1 | Valid | Valid | Multiply r/m16 by 2, once. |
+| D3 /4 | SAL r/m16, CL | MC | Valid | Valid | Multiply r/m16 by 2, CL times. |
+| C1 /4 ib | SAL r/m16, imm8 | MI | Valid | Valid | Multiply r/m16 by 2, imm8 times. |
+| D1 /4 | SAL r/m32, 1 | M1 | Valid | Valid | Multiply r/m32 by 2, once. |
+| REX.W + D1 /4 | SAL r/m64, 1 | M1 | Valid | N.E. | Multiply r/m64 by 2, once. |
+| D3 /4 | SAL r/m32, CL | MC | Valid | Valid | Multiply r/m32 by 2, CL times. |
+| REX.W + D3 /4 | SAL r/m64, CL | MC | Valid | N.E. | Multiply r/m64 by 2, CL times. |
+| C1 /4 ib | SAL r/m32, imm8 | MI | Valid | Valid | Multiply r/m32 by 2, imm8 times. |
+| REX.W + C1 /4 ib | SAL r/m64, imm8 | MI | Valid | N.E. | Multiply r/m64 by 2, imm8 times. |
+| D0 /7 | SAR r/m8, 1 | M1 | Valid | Valid | Signed divide* r/m8 by 2, once. |
+| REX + D0 /7 | SAR r/m8**, 1 | M1 | Valid | N.E. | Signed divide* r/m8 by 2, once. |
+| D2 /7 | SAR r/m8, CL | MC | Valid | Valid | Signed divide* r/m8 by 2, CL times. |
+| REX + D2 /7 | SAR r/m8**, CL | MC | Valid | N.E. | Signed divide* r/m8 by 2, CL times. |
+| C0 /7 ib | SAR r/m8, imm8 | MI | Valid | Valid | Signed divide* r/m8 by 2, imm8 time. |
+| REX + C0 /7 ib | SAR r/m8**, imm8 | MI | Valid | N.E. | Signed divide* r/m8 by 2, imm8 times. |
+| D1 /7 | SAR r/m16,1 | M1 | Valid | Valid | Signed divide* r/m16 by 2, once. |
+| D3 /7 | SAR r/m16, CL | MC | Valid | Valid | Signed divide* r/m16 by 2, CL times. |
+| C1 /7 ib | SAR r/m16, imm8 | MI | Valid | Valid | Signed divide* r/m16 by 2, imm8 times. |
+| D1 /7 | SAR r/m32, 1 | M1 | Valid | Valid | Signed divide* r/m32 by 2, once. |
+| REX.W + D1 /7 | SAR r/m64, 1 | M1 | Valid | N.E. | Signed divide* r/m64 by 2, once. |
+| D3 /7 | SAR r/m32, CL | MC | Valid | Valid | Signed divide* r/m32 by 2, CL times. |
+| REX.W + D3 /7 | SAR r/m64, CL | MC | Valid | N.E. | Signed divide* r/m64 by 2, CL times. |
+| C1 /7 ib | SAR r/m32, imm8 | MI | Valid | Valid | Signed divide* r/m32 by 2, imm8 times. |
+| REX.W + C1 /7 ib | SAR r/m64, imm8 | MI | Valid | N.E. | Signed divide* r/m64 by 2, imm8 times |
+| D0 /4 | SHL r/m8, 1 | M1 | Valid | Valid | Multiply r/m8 by 2, once. |
+| REX + D0 /4 | SHL r/m8**, 1 | M1 | Valid | N.E. | Multiply r/m8 by 2, once. |
+| D2 /4 | SHL r/m8, CL | MC | Valid | Valid | Multiply r/m8 by 2, CL times. |
+| REX + D2 /4 | SHL r/m8**, CL | MC | Valid | N.E. | Multiply r/m8 by 2, CL times. |
+| C0 /4 ib | SHL r/m8, imm8 | MI | Valid | Valid | Multiply r/m8 by 2, imm8 times. |
+| REX + C0 /4 ib | SHL r/m8**, imm8 | MI | Valid | N.E. | Multiply r/m8 by 2, imm8 times. |
+| D1 /4 | SHL r/m16,1 | M1 | Valid | Valid | Multiply r/m16 by 2, once. |
+| D3 /4 | SHL r/m16, CL | MC | Valid | Valid | Multiply r/m16 by 2, CL times. |
+| C1 /4 ib | SHL r/m16, imm8 | MI | Valid | Valid | Multiply r/m16 by 2, imm8 times. |
+| D1 /4 | SHL r/m32,1 | M1 | Valid | Valid | Multiply r/m32 by 2, once. |
+| REX.W + D1 /4 | SHL r/m64,1 | M1 | Valid | N.E. | Multiply r/m64 by 2, once. |
+| D3 /4 | SHL r/m32, CL | MC | Valid | Valid | Multiply r/m32 by 2, CL times. |
+| REX.W + D3 /4 | SHL r/m64, CL | MC | Valid | N.E. | Multiply r/m64 by 2, CL times. |
+| C1 /4 ib | SHL r/m32, imm8 | MI | Valid | Valid | Multiply r/m32 by 2, imm8 times. |
+| REX.W + C1 /4 ib | SHL r/m64, imm8 | MI | Valid | N.E. | Multiply r/m64 by 2, imm8 times. |
+| D0 /5 | SHR r/m8,1 | M1 | Valid | Valid | Unsigned divide r/m8 by 2, once. |
+| REX + D0 /5 | SHR r/m8**, 1 | M1 | Valid | N.E. | Unsigned divide r/m8 by 2, once. |
+| D2 /5 | SHR r/m8, CL | MC | Valid | Valid | Unsigned divide r/m8 by 2, CL times. |
+| REX + D2 /5 | SHR r/m8**, CL | MC | Valid | N.E. | Unsigned divide r/m8 by 2, CL times. |
+| C0 /5 ib | SHR r/m8, imm8 | MI | Valid | Valid | Unsigned divide r/m8 by 2, imm8 times. |
+| REX + C0 /5 ib | SHR r/m8**, imm8 | MI | Valid | N.E. | Unsigned divide r/m8 by 2, imm8 times. |
+| D1 /5 | SHR r/m16, 1 | M1 | Valid | Valid | Unsigned divide r/m16 by 2, once. |
+| D3 /5 | SHR r/m16, CL | MC | Valid | Valid | Unsigned divide r/m16 by 2, CL times |
+| C1 /5 ib | SHR r/m16, imm8 | MI | Valid | Valid | Unsigned divide r/m16 by 2, imm8 times. |
+| D1 /5 | SHR r/m32, 1 | M1 | Valid | Valid | Unsigned divide r/m32 by 2, once. |
+| REX.W + D1 /5 | SHR r/m64, 1 | M1 | Valid | N.E. | Unsigned divide r/m64 by 2, once. |
+| D3 /5 | SHR r/m32, CL | MC | Valid | Valid | Unsigned divide r/m32 by 2, CL times. |
+| REX.W + D3 /5 | SHR r/m64, CL | MC | Valid | N.E. | Unsigned divide r/m64 by 2, CL times. |
+| C1 /5 ib | SHR r/m32, imm8 | MI | Valid | Valid | Unsigned divide r/m32 by 2, imm8 times. |
+| REX.W + C1 /5 ib | SHR r/m64, imm8 | MI | Valid | N.E. | Unsigned divide r/m64 by 2, imm8 times. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+- Not the same form of division as IDIV; rounding is toward negative infinity.
+
+## Information
+
+The destination operand can be a register or a memory location. The count operand can be an immediate value or the CL register. The count is
+masked to 5 bits (or 6 bits if in 64-bit mode and REX.W is used). The count range is limited to 0 to 31 (or 63 if 64-bit mode and REX.W is
+used). A special opcode encoding is provided for a count of 1.
+
+The shift arithmetic left (SAL) and shift logical left (SHL) instructions perform the same operation; they shift the bits in the destination
+operand to the left (toward more significant bit locations). For each shift count, the most significant bit of the destination operand is
+shifted into the CF flag, and the least significant bit is cleared.
+
+The shift arithmetic right (SAR) and shift logical right (SHR) instructions shift the bits of the destination operand to the right (toward less
+significant bit locations). For each shift count, the least significant bit of the destination operand is shifted into the CF flag, and the
+most significant bit is either set or cleared depending on the instruction type. The SHR instruction clears the most significant bit (see
+Figure 7-8 in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1); the SAR instruction sets or clears the most
+significant bit to correspond to the sign (most significant bit) of the original value in the destination operand. In effect, the SAR
+instruction fills the empty bit position’s shifted value with the sign of the unshifted value.
+
+The SAR and SHR instructions can be used to perform signed or unsigned division, respectively, of the destination operand by powers of 2. For
+example, using the SAR instruction to shift a signed integer 1 bit to the right divides the value by 2.
+
+Using the SAR instruction to perform a division operation does not produce the same result as the IDIV instruction. The quotient from the IDIV
+instruction is rounded toward zero, whereas the “quotient” of the SAR instruction is rounded toward negative infinity. This difference is
+apparent only for negative numbers. For example, when the IDIV instruction is used to divide -9 by 4, the result is -2 with a remainder of -1.
+If the SAR instruction is used to shift -9 right by two bits, the result is -3 and the “remainder” is +3; however, the SAR instruction stores
+only the most significant bit of the remainder (in the CF flag).
+
+The OF flag is affected only on 1-bit shifts. For left shifts, the OF flag is set to 0 if the most-significant bit of the result is the same as
+the CF flag (that is, the top two bits of the original operand were the same); otherwise, it is set to 1. For the SAR instruction, the OF flag
+is cleared for all 1-bit shifts. For the SHR instruction, the OF flag is set to the most-significant bit of the original operand.
+
+In 64-bit mode, the instruction’s default operation size is 32 bits and the mask width for CL is 5 bits. Using a REX prefix in the form of
+REX.R permits access to additional registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64-bits and sets the mask
+width for CL to 6 bits. See the summary chart at the beginning of this section for encoding data and limits.
--- /dev/null
+# SUB — Subtract
+
+## Description
+
+Subtracts the second operand (source operand) from the first operand (destination operand) and stores the result in the destination operand.
+The destination operand can be a register or a memory location; the source operand can be an immediate, register, or memory location. However,
+two memory operands cannot be used in one instruction. When an immediate value is used as an operand, it is sign-extended to the length of the
+destination operand format.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|------------------|-------|-------------|-------------|--------------------------------------------------------------------|
+| 2C ib | SUB AL, imm8 | I | Valid | Valid | Subtract imm8 from AL. |
+| 2D iw | SUB AX, imm16 | I | Valid | Valid | Subtract imm16 from AX. |
+| 2D id | SUB EAX, imm32 | I | Valid | Valid | Subtract imm32 from EAX. |
+| REX.W + 2D id | SUB RAX, imm32 | I | Valid | N.E. | Subtract imm32 sign-extended to 64-bits from RAX. |
+| 80 /5 ib | SUB r/m8, imm8 | MI | Valid | Valid | Subtract imm8 from r/m8. |
+| REX + 80 /5 ib | SUB r/m8*, imm8 | MI | Valid | N.E. | Subtract imm8 from r/m8. |
+| 81 /5 iw | SUB r/m16, imm16 | MI | Valid | Valid | Subtract imm16 from r/m16. |
+| 81 /5 id | SUB r/m32, imm32 | MI | Valid | Valid | Subtract imm32 from r/m32. |
+| REX.W + 81 /5 id | SUB r/m64, imm32 | MI | Valid | N.E. | Subtract imm32 sign-extended to 64-bits from r/m64. |
+| 83 /5 ib | SUB r/m16, imm8 | MI | Valid | Valid | Subtract sign-extended imm8 from r/m16. |
+| 83 /5 ib | SUB r/m32, imm8 | MI | Valid | Valid | Subtract sign-extended imm8 from r/m32. |
+| REX.W + 83 /5 ib | SUB r/m64, imm8 | MI | Valid | N.E. | Subtract sign-extended imm8 from r/m64. |
+| 28 /r | SUB r/m8, r8 | MR | Valid | Valid | Subtract r8 from r/m8. |
+| REX + 28 /r | SUB r/m8*, r8* | MR | Valid | N.E. | Subtract r8 from r/m8. |
+| 29 /r | SUB r/m16, r16 | MR | Valid | Valid | Subtract r16 from r/m16. |
+| 29 /r | SUB r/m32, r32 | MR | Valid | Valid | Subtract r32 from r/m32. |
+| REX.W + 29 /r | SUB r/m64, r64 | MR | Valid | N.E. | Subtract r64 from r/m64. |
+| 2A /r | SUB r8, r/m8 | RM | Valid | Valid | Subtract r/m8 from r8. |
+| REX + 2A /r | SUB r8*, r/m8* | RM | Valid | N.E. | Subtract r/m8 from r8. |
+| 2B /r | SUB r16, r/m16 | RM | Valid | Valid | Subtract r/m16 from r16. |
+| 2B /r | SUB r32, r/m32 | RM | Valid | Valid | Subtract r/m32 from r32. |
+| REX.W + 2B /r | SUB r64, r/m64 | RM | Valid | N.E. | Subtract r/m64 from r64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+The SUB instruction performs integer subtraction. It evaluates the result for both signed and unsigned integer operands and sets the OF and CF
+flags to indicate an overflow in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed result.
+
+In 64-bit mode, the instruction's default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional
+registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this
+section for encoding data and limits.
--- /dev/null
+# SYSCALL — Fast System Call
+
+## Description
+
+SYSCALL invokes an OS system-call handler at privilege level 0. It does so by loading RIP from the IA32_LSTAR MSR (after saving the address of
+the instruction following SYSCALL into RCX). The WRMSR instruction ensures that the IA32_LSTAR MSR always contain a canonical address.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|--------|----------|-------|-------------|-------------|--------------------------------------------------------------------------------------|
+| 0F 05 | SYSCALL | NP | Valid | Invalid | Fast call to privilege level 0 system procedures. |
+
+## Information
+
+SYSCALL also saves RFLAGS into R11 and then masks RFLAGS using the IA32_FMASK MSR (MSR address C0000084H); specifically, the processor clears
+in RFLAGS every bit corresponding to a bit that is set in the IA32_FMASK MSR.
+
+SYSCALL loads the CS and SS selectors with values derived from bits 47:32 of the IA32_STAR MSR. However, the CS and SS descriptor caches are
+not loaded from the descriptors (in GDT or LDT) referenced by those selectors. Instead, the descriptor caches are loaded with fixed values. See
+the Operation section for details. It is the responsibility of OS software to ensure that the descriptors (in GDT or LDT) referenced by those
+selector values correspond to the fixed values loaded into the descriptor caches; the SYSCALL instruction does not ensure this correspondence.
+
+The SYSCALL instruction does not save the stack pointer (RSP). If the OS system-call handler will change the stack pointer, it is the
+responsibility of software to save the previous value of the stack pointer. This might be done prior to executing SYSCALL, with software
+restoring the stack pointer with the instruction following SYSCALL (which will be executed after SYSRET). Alternatively, the OS system-call
+handler may save the stack pointer and restore it before executing SYSRET.
--- /dev/null
+# SYSENTER — Fast System Call
+
+## Description
+
+Executes a fast call to a level 0 system procedure or routine. SYSENTER is a companion instruction to SYSEXIT. The instruction is optimized to
+provide the maximum performance for system calls from user code running at privilege level 3 to operating system or executive procedures
+running at privilege level 0.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|--------|----------|-------|-------------|-------------|--------------------------------------------------------------------------------------|
+| 0F 34 | SYSENTER | NP | Valid | Valid | Fast call to privilege level 0 system procedures. |
+
+## Information
+
+When executed in IA-32e mode, the SYSENTER instruction transitions the logical processor to 64-bit mode; otherwise, the logical processor
+remains in protected mode.
+
+Prior to executing the SYSENTER instruction, software must specify the privilege level 0 code segment and code entry point, and the privilege
+level 0 stack segment and stack pointer by writing values to the following MSRs: - IA32_SYSENTER_CS (MSR address 174H) — The lower 16 bits of
+this MSR are the segment selector for the privilege level 0 code segment. This value is also used to determine the segment selector of the
+privilege level 0 stack segment (see the Operation section). This value cannot indicate a null selector.
+
+- IA32_SYSENTER_EIP (MSR address 176H) — The value of this MSR is loaded into RIP (thus, this value references the first instruction of the
+selected operating procedure or routine). In protected mode, only bits 31:0 are loaded.
+
+- IA32_SYSENTER_ESP (MSR address 175H) — The value of this MSR is loaded into RSP (thus, this value contains the stack pointer for the
+privilege level 0 stack). This value cannot represent a non-canonical address. In protected mode, only bits 31:0 are loaded.
+
+These MSRs can be read from and written to using RDMSR/WRMSR. The WRMSR instruction ensures that the IA32_SYSENTER_EIP and IA32_SYSENTER_ESP
+MSRs always contain canonical addresses.
+
+While SYSENTER loads the CS and SS selectors with values derived from the IA32_SYSENTER_CS MSR, the CS and SS descriptor caches are not loaded
+from the descriptors (in GDT or LDT) referenced by those selectors. Instead, the descriptor caches are loaded with fixed values. See the
+Operation section for details. It is the responsibility of OS software to ensure that the descriptors (in GDT or LDT) referenced by those
+selector values correspond to the fixed values loaded into the descriptor caches; the SYSENTER instruction does not ensure this correspondence.
+The SYSENTER instruction can be invoked from all operating modes except real-address mode.
+
+The SYSENTER and SYSEXIT instructions are companion instructions, but they do not constitute a call/return pair. When executing a SYSENTER
+instruction, the processor does not save state information for the user code (e.g., the instruction pointer), and neither the SYSENTER nor the
+SYSEXIT instruction supports passing parameters on the stack.
+
+To use the SYSENTER and SYSEXIT instructions as companion instructions for transitions between privilege level 3 code and privilege level 0
+operating system procedures, the following conventions must be followed:
+
+- The segment descriptors for the privilege level 0 code and stack segments and for the privilege level 3 code and stack segments must be
+contiguous in a descriptor table. This convention allows the processor to compute the segment selectors from the value entered in the
+SYSENTER_CS_MSR MSR.
+
+- The fast system call "stub" routines executed by user code (typically in shared libraries or DLLs) must save the required return IP and
+processor state information if a return to the calling procedure is required. Likewise, the operating system or executive procedures called
+with SYSENTER instructions must have access to and use this saved return and state information when returning to the user code.
+
+The SYSENTER and SYSEXIT instructions were introduced into the IA-32 architecture in the Pentium II processor. The availability of these
+instructions on a processor is indicated with the SYSENTER/SYSEXIT present (SEP) feature flag returned to the EDX register by the CPUID
+instruction. An operating system that qualifies the SEP flag must also qualify the processor family and model to ensure that the
+SYSENTER/SYSEXIT instructions are actually present.
+
+When the CPUID instruction is executed on the Pentium Pro processor (model 1), the processor returns a the SEP flag as set, but does not
+support the SYSENTER/SYSEXIT instructions.
--- /dev/null
+# SYSEXIT — Return from Fast System Call
+
+## Description
+
+Executes a fast return to privilege level 3 user code. SYSEXIT is a companion instruction to the SYSENTER instruction. The instruction is
+optimized to provide the maximum performance for returns from system procedures executing at protections levels 0 to user procedures executing
+at protection level 3. It must be executed from code executing at privilege level 0.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|----------|-------|-------------|-------------|-------------------------------------------------------------------------------|
+| 0F 35 | SYSEXIT | NP | Valid | Valid | Fast return to privilege level 3 user code. |
+| REX.W + 0F 35 | SYSEXIT | NP | Valid | Valid | Fast return to 64-bit mode privilege level 3 user code. |
+
+## Information
+
+With a 64-bit operand size, SYSEXIT remains in 64-bit mode; otherwise, it either enters compatibility mode (if the logical processor is in
+IA-32e mode) or remains in protected mode (if it is not).
+
+Prior to executing SYSEXIT, software must specify the privilege level 3 code segment and code entry point, and the privilege level 3 stack
+segment and stack pointer by writing values into the following MSR and general-purpose registers:
+
+- IA32_SYSENTER_CS (MSR address 174H) — Contains a 32-bit value that is used to determine the segment selectors for the privilege level 3 code
+and stack segments.
+
+- RDX — The canonical address in this register is loaded into RIP (thus, this value references the first instruction to be executed in the user
+code). If the return is not to 64-bit mode, only bits 31:0 are loaded.
+
+- ECX — The canonical address in this register is loaded into RSP (thus, this value contains the stack pointer for the privilege level 3
+stack). If the return is not to 64-bit mode, only bits 31:0 are loaded. The IA32_SYSENTER_CS MSR can be read from and written to using RDMSR
+and WRMSR.
+
+While SYSEXIT loads the CS and SS selectors with values derived from the IA32_SYSENTER_CS MSR, the CS and SS descriptor caches are not loaded
+from the descriptors (in GDT or LDT) referenced by those selectors. Instead, the descriptor caches are loaded with fixed values. See the
+Operation section for details. It is the responsibility of OS software to ensure that the descriptors (in GDT or LDT) referenced by those
+selector values correspond to the fixed values loaded into the descriptor caches; the SYSEXIT instruction does not ensure this correspondence.
+The SYSEXIT instruction can be invoked from all operating modes except real-address mode and virtual-8086 mode.
+
+The SYSENTER and SYSEXIT instructions were introduced into the IA-32 architecture in the Pentium II processor. The availability of these
+instructions on a processor is indicated with the SYSENTER/SYSEXIT present (SEP) feature flag returned to the EDX register by the CPUID
+instruction. An operating system that qualifies the SEP flag must also qualify the processor family and model to ensure that the
+SYSENTER/SYSEXIT instructions are actually present.
+
+When the CPUID instruction is executed on the Pentium Pro processor (model 1), the processor returns a the SEP flag as set, but does not
+support the SYSENTER/SYSEXIT instructions.
--- /dev/null
+# SYSRET — Return from Fast System Call
+
+## Description
+
+SYSRET is a companion instruction to the SYSCALL instruction. It returns from an OS system-call handler to user code at privilege level 3. It
+does so by loading RIP from RCX and loading RFLAGS from R11.1 With a 64-bit operand size, SYSRET remains in 64-bit mode; otherwise, it enters
+compatibility mode and only the low 32 bits of the regis- ters are loaded.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|---------------|----------|-------|-------------|-------------|-------------------------------------------------------------------------------|
+| 0F 07 | SYSRET | NP | Valid | Invalid | Return to compatibility mode from fast system call. |
+| REX.W + 0F 07 | SYSRET | NP | Valid | Invalid | Return to 64-bit mode from fast system call. |
+
+## Information
+
+SYSRET loads the CS and SS selectors with values derived from bits 63:48 of the IA32_STAR MSR. However, the CS and SS descriptor caches are not
+loaded from the descriptors (in GDT or LDT) referenced by those selectors. Instead, the descriptor caches are loaded with fixed values. See the
+Operation section for details. It is the respon- sibility of OS software to ensure that the descriptors (in GDT or LDT) referenced by those
+selector values corre- spond to the fixed values loaded into the descriptor caches; the SYSRET instruction does not ensure this correspondence.
+
+The SYSRET instruction does not modify the stack pointer (ESP or RSP). For that reason, it is necessary for software to switch to the user
+stack. The OS may load the user stack pointer (if it was saved after SYSCALL) before executing SYSRET; alternatively, user code may load the
+stack pointer (if it was saved before SYSCALL) after receiving control from SYSRET.
+
+If the OS loads the stack pointer before executing SYSRET, it must ensure that the handler of any interrupt or exception delivered between
+restoring the stack pointer and successful execution of SYSRET is not invoked with the user stack. It can do so using approaches such as the
+following:
+
+- External interrupts. The OS can prevent an external interrupt from being delivered by clearing EFLAGS.IF before loading the user stack
+pointer.
+
+- Nonmaskable interrupts (NMIs). The OS can ensure that the NMI handler is invoked with the correct stack by using the interrupt stack table
+(IST) mechanism for gate 2 (NMI) in the IDT .
+
+- General-protection exceptions (#GP). The SYSRET instruction generates #GP(0) if the value of RCX is not canonical. The OS can address this
+possibility using one or more of the following approaches:
+
+1) Confirming that the value of RCX is canonical before executing SYSRET.
+2) Using paging to ensure that the SYSCALL instruction will never save a non-canonical value into RCX.
+3) Using the IST mechanism for gate 13 (#GP) in the IDT.
--- /dev/null
+#
+
+## Description
+
+
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|--------|-------------|-------|-------------|-------------|-----------------------------------------------------------------------------------|
+
+
+## Information
+
+
--- /dev/null
+# XOR — Logical Exclusive Or
+
+## Description
+
+Performs a bitwise exclusive OR (XOR) operation on the destination (first) and source (second) operands and stores the result in the
+destination operand location. The source operand can be an immediate, a register, or a memory location; the destination operand can be a
+register or a memory location. However, two memory operands cannot be used in one instruction. Each bit of the result is 1 if the corresponding
+bits of the operands are different; each bit is 0 if the corresponding bits are the same.
+
+## Instruction
+
+| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description |
+|------------------|------------------|-------|-------------|-------------|--------------------------------------------------------------------|
+| 34 ib | XOR AL, imm8 | I | Valid | Valid | AL XOR imm8. |
+| 35 iw | XOR AX, imm16 | I | Valid | Valid | AX XOR imm16. |
+| 35 id | XOR EAX, imm32 | I | Valid | Valid | EAX XOR imm32. |
+| REX.W + 35 id | XOR RAX, imm32 | I | Valid | N.E. | RAX XOR imm32 (sign-extended). |
+| 80 /6 ib | XOR r/m8, imm8 | MI | Valid | Valid | r/m8 XOR imm8. |
+| REX + 80 /6 ib | XOR r/m8*, imm8 | MI | Valid | N.E. | r/m8 XOR imm8. |
+| 81 /6 iw | XOR r/m16, imm16 | MI | Valid | Valid | r/m16 XOR imm16. |
+| 81 /6 id | XOR r/m32, imm32 | MI | Valid | Valid | r/m32 XOR imm32. |
+| REX.W + 81 /6 id | XOR r/m64, imm32 | MI | Valid | N.E. | r/m64 XOR imm32 (sign-extended). |
+| 83 /6 ib | XOR r/m16, imm8 | MI | Valid | Valid | r/m16 XOR imm8 (sign-extended). |
+| 83 /6 ib | XOR r/m32, imm8 | MI | Valid | Valid | r/m32 XOR imm8 (sign-extended). |
+| REX.W + 83 /6 ib | XOR r/m64, imm8 | MI | Valid | N.E. | r/m64 XOR imm8 (sign-extended). |
+| 30 /r | XOR r/m8, r8 | MR | Valid | Valid | r/m8 XOR r8. |
+| REX + 30 /r | XOR r/m8*, r8* | MR | Valid | N.E. | r/m8 XOR r8. |
+| 31 /r | XOR r/m16, r16 | MR | Valid | Valid | r/m16 XOR r16. |
+| 31 /r | XOR r/m32, r32 | MR | Valid | Valid | r/m32 XOR r32. |
+| REX.W + 31 /r | XOR r/m64, r64 | MR | Valid | N.E. | r/m64 XOR r64. |
+| 32 /r | XOR r8, r/m8 | RM | Valid | Valid | r8 XOR r/m8. |
+| REX + 32 /r | XOR r8*, r/m8* | RM | Valid | N.E. | r8 XOR r/m8. |
+| 33 /r | XOR r16, r/m16 | RM | Valid | Valid | r16 XOR r/m16. |
+| 33 /r | XOR r32, r/m32 | RM | Valid | Valid | r32 XOR r/m32. |
+| REX.W + 33 /r | XOR r64, r/m64 | RM | Valid | N.E. | r64 XOR r/m64. |
+
+- In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.
+
+## Information
+
+This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
+
+In 64-bit mode, using a REX prefix in the form of REX.R permits access to additional registers (R8-R15). Using a REX prefix in the form of
+REX.W promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.
--- /dev/null
+#define use_fatal_failure
+#define use_png_library
+#define use_raptor_renderer
+//~#define use_common_renderer
+//~#define use_opengl_renderer
+//~#define use_vulkan_renderer
+
+#include <xolatile/xtandard.h>
+#include <xolatile/xormat.h>
+#include <xolatile/xross.h>
+#include <xolatile/xui.h>
+
+int main (void) {
+ cross_structure * cross = cross_initialize (30, 3);
+ ui_structure * ui = ui_initialize (cross);
+
+ cross_configure (cross, 640, 480, "Xaptor - File Manager");
+
+ while (cross->active == true) {
+ const uint offset = 48;
+
+ cross_synchronize (cross, 0x00000000);
+
+ ui_render_window (cross, ui, 0, 0, cross->window_width, cross->window_height);
+
+ ui_render_status (cross, ui, offset, offset, cross->window_width - 2 * offset, cross->window_height - 2 * offset);
+
+ cross_render_string (cross, "Xaptors are coming!", 0, 2 * offset, 2 * offset, 1.5f, 0x4488ccff);
+
+ cross_render_string (cross, format ("%i", cross->framerate), 0, 2 * offset, 3 * offset, 1.0f, 0x4488ccff);
+ cross_render_string (cross, format ("%i", cross->global_tick), 0, 2 * offset, 4 * offset, 1.0f, 0x4488ccff);
+ cross_render_string (cross, format ("%i", cross->gameplay_tick), 0, 2 * offset, 5 * offset, 1.0f, 0x4488ccff);
+ cross_render_string (cross, format ("%i", cross->animation_tick), 0, 2 * offset, 6 * offset, 1.0f, 0x4488ccff);
+ cross_render_string (cross, format ("%i", cross->cursor_x), 0, 2 * offset, 7 * offset, 1.0f, 0x4488ccff);
+ cross_render_string (cross, format ("%i", cross->cursor_y), 0, 2 * offset, 8 * offset, 1.0f, 0x4488ccff);
+
+ if (cross->signal [signal_q] == true) break;
+ }
+
+ cross = cross_deinitialize (cross);
+ ui = ui_deinitialize (ui);
+
+ return (log_success);
+}
--- /dev/null
+/// _
+/// __ ____ _ _ __ | |_ ___ _ __
+/// \ \/ / _` | '_ \| __/ _ \| '__|
+/// > < (_| | |_) | || (_) | |
+/// /_/\_\__,_| .__/ \__\___/|_|
+/// |_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xaptor - Carnivorous medium-to-large sized Xlib wrapper that has a hooked beak and large sharp talons.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+typedef struct {
+ Display * display;
+ Window window;
+ XVisualInfo visual;
+ GC context;
+ Pixmap pixmap;
+ XImage * image;
+ Atom atom_close_button;
+ Atom atom_transparency;
+
+ bool signal [signal_count];
+ bool cursor [cursor_count];
+ int cursor_x;
+ int cursor_y;
+
+ uint gameplay_framerate;
+ uint animation_framerate;
+ uint window_width;
+ uint window_height;
+ bool active;
+ uint framerate;
+ ulong frame_time;
+ ulong frame_begin;
+ ulong frame_end;
+ uint * framebuffer;
+ uint global_tick;
+ uint gameplay_tick;
+ uint animation_tick;
+ uint tab_width;
+ uint sprite_count;
+ uint font_count;
+ uint * * sprite_data;
+ uint * sprite_width;
+ uint * sprite_height;
+ uint * * font_index;
+ uint * * font_width;
+ uint * * font_height;
+ char * font_begin;
+ char * font_end;
+} raptor_structure;
+
+static raptor_structure * raptor_initialize (uint gameplay_framerate, uint animation_framerate) {
+ raptor_structure * raptor = allocate (sizeof (* raptor));
+
+ raptor->gameplay_framerate = gameplay_framerate;
+ raptor->animation_framerate = animation_framerate;
+ raptor->tab_width = 8;
+
+ return (raptor);
+}
+
+static raptor_structure * raptor_deinitialize (raptor_structure * raptor) {
+ for (uint index = 0; index < raptor->sprite_count; ++index) {
+ raptor->sprite_data [index] = deallocate (raptor->sprite_data [index]);
+ }
+
+ for (uint index = 0; index < raptor->font_count; ++index) {
+ raptor->font_index [index] = deallocate (raptor->font_index [index]);
+ raptor->font_width [index] = deallocate (raptor->font_width [index]);
+ raptor->font_height [index] = deallocate (raptor->font_height [index]);
+ }
+
+ raptor->font_index = deallocate (raptor->font_index);
+ raptor->font_width = deallocate (raptor->font_width);
+ raptor->font_height = deallocate (raptor->font_height);
+ raptor->font_begin = deallocate (raptor->font_begin);
+ raptor->font_end = deallocate (raptor->font_end);
+
+ raptor->sprite_data = deallocate (raptor->sprite_data);
+ raptor->sprite_width = deallocate (raptor->sprite_width);
+ raptor->sprite_height = deallocate (raptor->sprite_height);
+
+ if (raptor->framebuffer != null) {
+ raptor->framebuffer = deallocate (raptor->framebuffer);
+ }
+
+ XFreePixmap (raptor->display, raptor->pixmap);
+ XFreeGC (raptor->display, raptor->context);
+ XUnmapWindow (raptor->display, raptor->window);
+ XDestroyWindow (raptor->display, raptor->window);
+
+ XCloseDisplay (raptor->display);
+
+ return (deallocate (raptor));
+}
+
+static uint raptor_sprite_raw_import (raptor_structure * raptor, uint * data, uint width, uint height) {
+ ++raptor->sprite_count;
+
+ raptor->sprite_data = reallocate (raptor->sprite_data, raptor->sprite_count * sizeof (* raptor->sprite_data));
+ raptor->sprite_width = reallocate (raptor->sprite_width, raptor->sprite_count * sizeof (* raptor->sprite_width));
+ raptor->sprite_height = reallocate (raptor->sprite_height, raptor->sprite_count * sizeof (* raptor->sprite_height));
+
+ raptor->sprite_data [raptor->sprite_count - 1] = data;
+ raptor->sprite_width [raptor->sprite_count - 1] = width;
+ raptor->sprite_height [raptor->sprite_count - 1] = height;
+
+ return (raptor->sprite_count - 1);
+}
+
+static uint raptor_font_raw_import (raptor_structure * raptor, uint * data, uint image_width, char begin, char end, uint separator_colour) {
+ uint pointer = 0;
+ uint width = 0;
+ uint height = 0;
+ uint * buffer = null;
+
+ const uint current = raptor->font_count;
+
+ ++raptor->font_count;
+
+ raptor->font_index = reallocate (raptor->font_index, raptor->font_count * sizeof (* raptor->font_index));
+ raptor->font_width = reallocate (raptor->font_width, raptor->font_count * sizeof (* raptor->font_width));
+ raptor->font_height = reallocate (raptor->font_height, raptor->font_count * sizeof (* raptor->font_height));
+ raptor->font_begin = reallocate (raptor->font_begin, raptor->font_count * sizeof (* raptor->font_begin));
+ raptor->font_end = reallocate (raptor->font_end, raptor->font_count * sizeof (* raptor->font_end));
+
+ raptor->font_begin [current] = begin;
+ raptor->font_end [current] = end;
+
+ raptor->font_index [current] = allocate ((ulong) (end - begin + 1) * sizeof (* * raptor->font_index));
+ raptor->font_width [current] = allocate ((ulong) (end - begin + 1) * sizeof (* * raptor->font_width));
+ raptor->font_height [current] = allocate ((ulong) (end - begin + 1) * sizeof (* * raptor->font_height));
+
+ for (char index = begin; index <= end; ++index) {
+ for ( ; data [pointer] == separator_colour; ++pointer);
+ for (width = 0; data [pointer + width] != separator_colour; ++width);
+ for (height = 0; data [pointer + height * image_width] != separator_colour; ++height);
+
+ buffer = allocate (width * height * sizeof (* buffer));
+
+ for (uint y = 0; y < height; ++y) {
+ for (uint x = 0; x < width; ++x) {
+ buffer [y * width + x] = data [pointer + (y * image_width) + x];
+ }
+ }
+
+ raptor->font_index [current] [index - begin] = raptor_sprite_raw_import (raptor, buffer, width, height);
+ raptor->font_width [current] [index - begin] = width;
+ raptor->font_height [current] [index - begin] = height;
+
+ pointer += width;
+
+ for (; data [pointer] == separator_colour; ++pointer);
+
+ if (pointer % image_width == 2) {
+ pointer += height * image_width;
+ }
+ }
+
+ return (current);
+}
+
+static uint raptor_sprite_import (raptor_structure * raptor, const char * path) {
+ uint width = 0;
+ uint height = 0;
+ uint * data = null;
+
+ data = format_image_import (path, & width, & height);
+
+ return (raptor_sprite_raw_import (raptor, data, width, height));
+}
+
+static uint raptor_font_import (raptor_structure * raptor, const char * path, char begin, char end, uint colour) {
+ uint width = 0;
+ uint height = 0;
+ uint result = 0;
+ uint * data = null;
+
+ data = format_image_import (path, & width, & height);
+
+ result = raptor_font_raw_import (raptor, data, width, begin, end, colour);
+
+ data = deallocate (data);
+
+ return (result);
+}
+
+static uint raptor_sprite_width (const raptor_structure * raptor, uint sprite) {
+ return (raptor->sprite_width [sprite]);
+}
+
+static uint raptor_sprite_height (const raptor_structure * raptor, uint sprite) {
+ return (raptor->sprite_height [sprite]);
+}
+
+static uint raptor_character_width (raptor_structure * raptor, char character, uint font, float scale) {
+ if ((character < raptor->font_begin [font]) || (character > raptor->font_end [font])) {
+ return (0);
+ } else {
+ const uint index = raptor->font_index [font] [character - raptor->font_begin [font]];
+
+ return ((uint) (scale * (float) raptor->sprite_width [index]));
+ }
+}
+
+static uint raptor_character_height (raptor_structure * raptor, char character, uint font, float scale) {
+ if ((character < raptor->font_begin [font]) || (character > raptor->font_end [font])) {
+ return (0);
+ } else {
+ const uint index = raptor->font_index [font] [character - raptor->font_begin [font]];
+
+ return ((uint) (scale * (float) raptor->sprite_height [index]));
+ }
+}
+
+static uint raptor_string_width (raptor_structure * raptor, const char * string, uint font, float scale) {
+ uint width = 0;
+ uint match = 0;
+
+ if (string == null) {
+ return (0);
+ }
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ if (string [index] == '\t') {
+ width += raptor->tab_width * raptor_character_width (raptor, ' ', font, scale);
+ } else if (string [index] == '\n') {
+ match = maximum (width, match);
+ width = 0;
+ } else {
+ width += raptor_character_width (raptor, string [index], font, scale);
+ }
+ }
+
+ return (maximum (width, match));
+}
+
+static uint raptor_string_height (raptor_structure * raptor, const char * string, uint font, float scale) {
+ uint height = raptor_character_height (raptor, ' ', font, scale);
+
+ if ((string == null) || (string [0] == '\0')) {
+ return (0);
+ }
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ if (string [index] == '\n') {
+ height += raptor_character_height (raptor, ' ', font, scale);
+ }
+ }
+
+ return (height);
+}
+
+static uint raptor_center_x (const raptor_structure * raptor, uint size) {
+ return ((raptor->window_width - size) / 2);
+}
+
+static uint raptor_center_y (const raptor_structure * raptor, uint size) {
+ return ((raptor->window_height - size) / 2);
+}
+
+static bool raptor_cursor_inside (const raptor_structure * raptor, int x, int y, uint width, uint height) {
+ return ((raptor->cursor_x > x)
+ && (raptor->cursor_y > y)
+ && (raptor->cursor_x < x + (int) width)
+ && (raptor->cursor_y < y + (int) height));
+}
+
+static bool raptor_cursor_left_click (const raptor_structure * raptor, int x, int y, uint width, uint height) {
+ if (raptor->cursor [cursor_left] == true) {
+ return (raptor_cursor_inside (raptor, x, y, width, height) == true);
+ }
+
+ return (false);
+}
+
+static bool raptor_cursor_right_click (const raptor_structure * raptor, int x, int y, uint width, uint height) {
+ if (raptor->cursor [cursor_right] == true) {
+ return (raptor_cursor_inside (raptor, x, y, width, height));
+ }
+
+ return (false);
+}
+
+static void raptor_configure (raptor_structure * raptor, uint window_width, uint window_height, const char * window_title) {
+ const ulong font_bitmap [2 * 95] = {
+ 0x0000000000000000, 0x0000000000000000, 0x0000101010101010, 0x1000101000000000, 0x0024242400000000, 0x0000000000000000,
+ 0x00002424247e2424, 0x7e24242400000000, 0x0010107c9290907c, 0x1212927c10100000, 0x0000649468081010, 0x202c524c00000000,
+ 0x000018242418304a, 0x4444443a00000000, 0x0010101000000000, 0x0000000000000000, 0x0000081020202020, 0x2020100800000000,
+ 0x0000201008080808, 0x0808102000000000, 0x000000000024187e, 0x1824000000000000, 0x000000000010107c, 0x1010000000000000,
+ 0x0000000000000000, 0x0000101020000000, 0x000000000000007e, 0x0000000000000000, 0x0000000000000000, 0x0000101000000000,
+ 0x0000040408081010, 0x2020404000000000, 0x00003c4242464a52, 0x6242423c00000000, 0x0000081828080808, 0x0808083e00000000,
+ 0x00003c4242020408, 0x1020407e00000000, 0x00003c4242021c02, 0x0242423c00000000, 0x000002060a122242, 0x7e02020200000000,
+ 0x00007e4040407c02, 0x0202423c00000000, 0x00001c2040407c42, 0x4242423c00000000, 0x00007e0202040408, 0x0810101000000000,
+ 0x00003c4242423c42, 0x4242423c00000000, 0x00003c424242423e, 0x0202043800000000, 0x0000000000101000, 0x0000101000000000,
+ 0x0000000000101000, 0x0000101020000000, 0x0000000408102040, 0x2010080400000000, 0x00000000007e0000, 0x7e00000000000000,
+ 0x0000004020100804, 0x0810204000000000, 0x00003c4242420408, 0x0800080800000000, 0x00007c829ea2a2a2, 0xa69a807e00000000,
+ 0x00003c424242427e, 0x4242424200000000, 0x00007c4242427c42, 0x4242427c00000000, 0x00003c4242404040, 0x4042423c00000000,
+ 0x0000784442424242, 0x4242447800000000, 0x00007e4040407840, 0x4040407e00000000, 0x00007e4040407840, 0x4040404000000000,
+ 0x00003c424240404e, 0x4242423c00000000, 0x0000424242427e42, 0x4242424200000000, 0x0000381010101010, 0x1010103800000000,
+ 0x00000e0404040404, 0x0444443800000000, 0x0000424448506060, 0x5048444200000000, 0x0000404040404040, 0x4040407e00000000,
+ 0x000082c6aa929282, 0x8282828200000000, 0x000042424262524a, 0x4642424200000000, 0x00003c4242424242, 0x4242423c00000000,
+ 0x00007c424242427c, 0x4040404000000000, 0x00003c4242424242, 0x42424a3c02000000, 0x00007c424242427c, 0x5048444200000000,
+ 0x00003c4240403c02, 0x0242423c00000000, 0x0000fe1010101010, 0x1010101000000000, 0x0000424242424242, 0x4242423c00000000,
+ 0x0000424242424224, 0x2424181800000000, 0x0000828282828292, 0x92aac68200000000, 0x0000424224241818, 0x2424424200000000,
+ 0x0000828244442810, 0x1010101000000000, 0x00007e0202040810, 0x2040407e00000000, 0x0000382020202020, 0x2020203800000000,
+ 0x0000404020201010, 0x0808040400000000, 0x0000380808080808, 0x0808083800000000, 0x0000102844000000, 0x0000000000000000,
+ 0x0000000000000000, 0x0000007e00000000, 0x1008000000000000, 0x0000000000000000, 0x00000000003c023e, 0x4242423e00000000,
+ 0x00004040407c4242, 0x4242427c00000000, 0x00000000003c4240, 0x4040423c00000000, 0x00000202023e4242, 0x4242423e00000000,
+ 0x00000000003c4242, 0x7e40403c00000000, 0x00000e10107c1010, 0x1010101000000000, 0x00000000003e4242, 0x4242423e02023c00,
+ 0x00004040407c4242, 0x4242424200000000, 0x0000101000301010, 0x1010103800000000, 0x00000404000c0404, 0x0404040444443800,
+ 0x0000404040424448, 0x7048444200000000, 0x0000301010101010, 0x1010103800000000, 0x0000000000fc9292, 0x9292929200000000,
+ 0x00000000007c4242, 0x4242424200000000, 0x00000000003c4242, 0x4242423c00000000, 0x00000000007c4242, 0x4242427c40404000,
+ 0x00000000003e4242, 0x4242423e02020200, 0x00000000005e6040, 0x4040404000000000, 0x00000000003e4040, 0x3c02027c00000000,
+ 0x00001010107c1010, 0x1010100e00000000, 0x0000000000424242, 0x4242423e00000000, 0x0000000000424242, 0x2424181800000000,
+ 0x0000000000828292, 0x9292927c00000000, 0x0000000000424224, 0x1824424200000000, 0x0000000000424242, 0x4242423e02023c00,
+ 0x00000000007e0408, 0x1020407e00000000, 0x00000c1010102010, 0x1010100c00000000, 0x0000101010101010, 0x1010101000000000,
+ 0x0000300808080408, 0x0808083000000000, 0x000000000062928c, 0x0000000000000000
+ };
+
+ XSetWindowAttributes window_attributes;
+
+ uint * dumb_buffer = allocate (256 * sizeof (* dumb_buffer));
+
+ for (uint index = 0; index < 256; ++index) {
+ dumb_buffer [index] = 0xffffffff;
+ }
+
+ ++raptor->font_count;
+
+ raptor->font_index = reallocate (raptor->font_index, raptor->font_count * sizeof (* raptor->font_index));
+ raptor->font_width = reallocate (raptor->font_width, raptor->font_count * sizeof (* raptor->font_width));
+ raptor->font_height = reallocate (raptor->font_height, raptor->font_count * sizeof (* raptor->font_height));
+ raptor->font_begin = reallocate (raptor->font_begin, raptor->font_count * sizeof (* raptor->font_begin));
+ raptor->font_end = reallocate (raptor->font_end, raptor->font_count * sizeof (* raptor->font_end));
+
+ raptor->font_begin [raptor->font_count - 1] = ' ';
+ raptor->font_end [raptor->font_count - 1] = '~';
+
+ raptor->font_index [raptor->font_count - 1] = allocate (95 * sizeof (* * raptor->font_index));
+ raptor->font_width [raptor->font_count - 1] = allocate (95 * sizeof (* * raptor->font_width));
+ raptor->font_height [raptor->font_count - 1] = allocate (95 * sizeof (* * raptor->font_height));
+
+ for (uint index = 0; index < 95; ++index) {
+ uint * buffer = allocate (8 * 16 * sizeof (* buffer));
+
+ for (uint value = 0; value < 2; ++value) {
+ for (uint bit = 64; bit > 0; --bit) {
+ uint destination = ((value << 3) - ((bit - 1) >> 3) + 7) * 8 - ((bit - 1) & 7) + 7;
+ uint source = (font_bitmap [2 * index + value] >> (bit - 1)) & 1;
+
+ buffer [destination] = (source) ? 0xffffffff : 0x00000000;
+ }
+ }
+
+ raptor->font_index [raptor->font_count - 1] [index] = raptor_sprite_raw_import (raptor, buffer, 8, 16);
+ raptor->font_width [raptor->font_count - 1] [index] = 8;
+ raptor->font_height [raptor->font_count - 1] [index] = 16;
+ }
+
+ raptor_sprite_raw_import (raptor, dumb_buffer, 16, 16);
+
+ raptor->window_width = window_width;
+ raptor->window_height = window_height;
+
+ raptor->display = XOpenDisplay (null);
+
+ int screen = DefaultScreen (raptor->display);
+
+ XMatchVisualInfo (raptor->display, screen, 32, TrueColor, & raptor->visual);
+
+ window_attributes.colormap = XCreateColormap (raptor->display, DefaultRootWindow (raptor->display), raptor->visual.visual, AllocNone);
+
+ window_attributes.border_pixel = 0x00000000;
+ window_attributes.background_pixel = 0x00000000;
+
+ raptor->window = XCreateWindow (raptor->display, DefaultRootWindow (raptor->display), 0, 0, window_width, window_height, 0,
+ raptor->visual.depth, InputOutput, raptor->visual.visual, CWColormap | CWBorderPixel | CWBackPixel,
+ & window_attributes);
+
+ XStoreName (raptor->display, raptor->window, window_title);
+
+ XSelectInput (raptor->display, raptor->window, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask);
+
+ raptor->pixmap = XCreatePixmap (raptor->display, raptor->window, raptor->window_width, raptor->window_height, raptor->visual.depth);
+
+ raptor->context = XCreateGC (raptor->display, raptor->window, 0, null);
+
+ XSetForeground (raptor->display, raptor->context, BlackPixel (raptor->display, screen));
+
+ raptor->atom_close_button = XInternAtom (raptor->display, "WM_DELETE_WINDOW", false);
+
+ XSetWMProtocols (raptor->display, raptor->window, & raptor->atom_close_button, 1);
+
+ //~XGrabPointer(raptor->display, DefaultRootWindow (raptor->display), False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None,
+ //~CurrentTime);
+
+ XMapWindow (raptor->display, raptor->window);
+
+ XFlush (raptor->display);
+
+ raptor->framebuffer = allocate (window_width * window_height * sizeof (* raptor->framebuffer));
+
+ raptor->active = true;
+
+ raptor->frame_begin = nano_time ();
+}
+
+static void raptor_render_base (raptor_structure * raptor, uint sprite, int x, int y, uint u, uint v, uint width, uint height, float scale_x,
+ float scale_y, int flip_x, int flip_y, uint upper_left, uint upper_right, uint lower_left, uint lower_right) {
+ (void) scale_x;
+ (void) scale_y;
+ (void) flip_x;
+ (void) flip_y;
+ /// FIX TO INTERPOLATE ALL 4 COLOURS
+ //~(void) upper_left;
+ (void) upper_right;
+ (void) lower_left;
+ (void) lower_right;
+
+ uint interpolate_pixels (uint pixel, uint modifier) {
+ const uint r = (((pixel & 0xff000000) >> 24) * ((modifier & 0x000000ff) >> 0)) / 0xff;
+ const uint g = (((pixel & 0x00ff0000) >> 16) * ((modifier & 0x0000ff00) >> 8)) / 0xff;
+ const uint b = (((pixel & 0x0000ff00) >> 8) * ((modifier & 0x00ff0000) >> 16)) / 0xff;
+ const uint a = (((pixel & 0x000000ff) >> 0) * ((modifier & 0xff000000) >> 24)) / 0xff;
+
+ return ((r << 24) | (g << 16) | (b << 8) | a);
+ }
+
+ if ((x + (int) width < 0) || (y + (int) height < 0) || (x > (int) raptor->window_width) || (y > (int) raptor->window_height)) return;
+
+ for (uint vertical = 0; vertical < height; ++vertical) {
+ if (vertical + y >= raptor->window_height) break;
+ if (vertical + v >= raptor->sprite_height [sprite]) break;
+
+ for (uint horizontal = 0; horizontal < width; ++horizontal) {
+ if (horizontal + x >= raptor->window_width) break;
+ if (horizontal + u >= raptor->sprite_width [sprite]) break;
+
+ const uint pixel = raptor->sprite_data [sprite] [(vertical + v) * raptor->sprite_width [sprite] + horizontal + u];
+ const uint at = (y + vertical) * raptor->window_width + (x + horizontal);
+
+ raptor->framebuffer [at] = (((pixel & 0xff000000) >> 24) > 0x77)
+ ? interpolate_pixels (pixel, upper_left)
+ : raptor->framebuffer [at];
+ }
+ }
+}
+
+static void raptor_render_rectangle (raptor_structure * raptor, int x, int y, uint width, uint height, uint colour) {
+ raptor_render_base (raptor, raptor->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16, (float) height / 16, 0, 0, colour, colour,
+ colour, colour);
+}
+
+static void raptor_render_sprite (raptor_structure * raptor, uint sprite, int x, int y) {
+ const uint width = raptor->sprite_width [sprite];
+ const uint height = raptor->sprite_height [sprite];
+
+ raptor_render_base (raptor, sprite, x, y, 0, 0, width, height, 1.0f, 1.0f, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static void raptor_render_sprite_scale (raptor_structure * raptor, uint sprite, int x, int y, float scale_x, float scale_y) {
+ const uint width = raptor->sprite_width [sprite];
+ const uint height = raptor->sprite_height [sprite];
+
+ raptor_render_base (raptor, sprite, x, y, 0, 0, width, height, scale_x, scale_y, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu,
+ 0xffffffffu);
+}
+
+static void raptor_render_sprite_crop (raptor_structure * raptor, uint sprite, int x, int y, uint u, uint v, uint width, uint height) {
+ raptor_render_base (raptor, sprite, x, y, u, v, width, height, 1.0f, 1.0f, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static void raptor_render_sprite_colour (raptor_structure * raptor, uint sprite, uint colour, int x, int y) {
+ const uint width = raptor->sprite_width [sprite];
+ const uint height = raptor->sprite_height [sprite];
+
+ raptor_render_base (raptor, sprite, x, y, 0, 0, width, height, 1.0f, 1.0f, 0, 0, colour, colour, colour, colour);
+}
+
+static void raptor_render_sprite_crop_colour (raptor_structure * raptor, uint sprite, uint colour, int x, int y, uint u, uint v, uint width, uint height) {
+ raptor_render_base (raptor, sprite, x, y, u, v, width, height, 1.0f, 1.0f, 0, 0, colour, colour, colour, colour);
+}
+
+static void raptor_render_sprite_flip (raptor_structure * raptor, uint sprite, int x, int y, int flip_x, int flip_y) {
+ const uint width = raptor->sprite_width [sprite];
+ const uint height = raptor->sprite_height [sprite];
+
+ raptor_render_base (raptor, sprite, x, y, 0, 0, width, height, 1.0f, 1.0f, flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu,
+ 0xffffffffu);
+}
+
+static void raptor_render_sprite_animate (raptor_structure * raptor, uint sprite, int x, int y, uint frames, uint state, uint states) {
+ const uint width = raptor->sprite_width [sprite] / states;
+ const uint height = raptor->sprite_height [sprite] / frames;
+
+ const uint u = width * (state % states);
+ const uint v = height * (raptor->animation_tick % frames);
+
+ raptor_render_sprite_crop (raptor, sprite, x, y, u, v, width, height);
+}
+
+static void raptor_render_character (raptor_structure * raptor, char character, uint font, int x, int y, float scale, uint colour) {
+ if ((character < raptor->font_begin [font]) || (character > raptor->font_end [font])) return;
+
+ const uint index = raptor->font_index [font] [character - raptor->font_begin [font]];
+
+ const uint width = raptor->sprite_width [index];
+ const uint height = raptor->sprite_height [index];
+
+ raptor_render_base (raptor, index, x, y, 0, 0, width, height, scale, scale, 0, 0, colour, colour, colour, colour);
+}
+
+static void raptor_render_string (raptor_structure * raptor, const char * string, uint font, int x, int y, float scale, uint colour) {
+ int offset = x;
+
+ if (string == null) return;
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ if (string [index] == '\t') {
+ x += raptor->tab_width * raptor_character_width (raptor, ' ', font, scale);
+ continue;
+ } else if (string [index] == '\n') {
+ x = offset;
+ y += raptor_character_height (raptor, ' ', font, scale);
+ continue;
+ } else {
+ raptor_render_character (raptor, string [index], font, x, y, scale, colour);
+
+ x += raptor_character_width (raptor, string [index], font, scale);
+ }
+ }
+}
+
+static void raptor_render_framerate (raptor_structure * raptor, uint font, int x, int y, float scale, uint colour) {
+ raptor_render_string (raptor, number_to_string (raptor->framerate), font, x, y, scale, colour);
+}
+
+static void raptor_synchronize (raptor_structure * raptor, uint clear_colour) {
+ const uint signal_code [signal_count] = {
+ 0,
+ 38, 56, 54, 40, 26, 41, 42, 43, 31, 44, 45, 46, 58, 57, 32, 33,
+ 24, 27, 39, 28, 30, 55, 25, 53, 29, 52, 19, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 9, 23, 36, 36, 61, 51, 47, 49, 65, 22, 60, 59,
+ 48, 66, 20, 21, 34, 35, 37, 105, 50, 62, 64, 108, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 95, 96, 111, 116, 113, 114, 77, 127, 118, 110,
+ 112, 119, 115, 117, 86, 82, 63, 106, 104, 91, 90, 87, 88, 89, 83, 84,
+ 85, 79, 80, 81
+ };
+
+ uint new_window_width = raptor->window_width;
+ uint new_window_height = raptor->window_height;
+
+ XEvent event = { 0 };
+ //~Window root_window = { 0 };
+
+ //~int root_x = 0;
+ //~int root_y = 0;
+ //~uint mask = 0;
+
+ for (uint index = 0; index < cursor_count; ++index) {
+ raptor->cursor [index] = false;
+ }
+
+ for (uint index = 0; index < signal_count; ++index) {
+ raptor->signal [index] = false;
+ }
+
+ //~XQueryPointer (raptor->display, raptor->window, & root_window, & root_window, & root_x, & root_y, & root_x, & root_y, & mask);
+
+ XNextEvent (raptor->display, & event);
+
+ switch (event.type) {
+ case (Expose): {
+ XFlush (raptor->display);
+ } break;
+ case (ClientMessage): {
+ if ((Atom) event.xclient.data.l [0] == raptor->atom_close_button) {
+ raptor->active = false;
+ return;
+ }
+ } break;
+ case (ConfigureNotify): {
+ new_window_width = event.xconfigure.width;
+ new_window_height = event.xconfigure.height;
+ } break;
+ case (ButtonPress): {
+ if (event.xbutton.button == Button1) raptor->cursor [cursor_left] = true;
+ if (event.xbutton.button == Button2) raptor->cursor [cursor_middle] = true;
+ if (event.xbutton.button == Button3) raptor->cursor [cursor_right] = true;
+ raptor->cursor_x = event.xbutton.x;
+ raptor->cursor_y = event.xbutton.y;
+ } break;
+ case (KeyPress): {
+ for (uint index = 0; index < signal_count; ++index) {
+ if (event.xkey.keycode == signal_code [index]) {
+ raptor->signal [index] = true;
+ }
+ }
+ } break;
+ default: {
+ //~XFlush (raptor->display);
+ return;
+ } break;
+ }
+
+ for (uint pixel = 0; pixel < raptor->window_width * raptor->window_height; ++pixel) {
+ uint r = (raptor->framebuffer [pixel] & 0x00ff0000) >> 16;
+ uint b = (raptor->framebuffer [pixel] & 0x000000ff) << 16;
+
+ raptor->framebuffer [pixel] = (raptor->framebuffer [pixel] & 0xff00ff00) | b | r;
+ }
+
+ raptor->image = XCreateImage (raptor->display, raptor->visual.visual, raptor->visual.depth, ZPixmap, 0, (char *) raptor->framebuffer,
+ raptor->window_width, raptor->window_height, 32, 0);
+
+ XPutImage (raptor->display, raptor->pixmap, raptor->context, raptor->image, 0, 0, 0, 0, raptor->window_width, raptor->window_height);
+
+ XCopyArea (raptor->display, raptor->pixmap, raptor->window, raptor->context, 0, 0, raptor->window_width, raptor->window_height, 0, 0);
+
+ XDestroyImage (raptor->image);
+
+ if ((new_window_width != raptor->window_width) || (new_window_height != raptor->window_height)) {
+ XFreePixmap (raptor->display, raptor->pixmap);
+
+ raptor->pixmap = XCreatePixmap (raptor->display, raptor->window, new_window_width, new_window_height, raptor->visual.depth);
+
+ raptor->window_width = new_window_width;
+ raptor->window_height = new_window_height;
+ }
+
+ raptor->framebuffer = allocate (raptor->window_width * raptor->window_height * sizeof (* raptor->framebuffer));
+
+ clear_colour = colour_channel_reverse (clear_colour);
+
+ for (uint pixel = 0; pixel < raptor->window_width * raptor->window_height; ++pixel) {
+ raptor->framebuffer [pixel] = clear_colour;
+ }
+
+ raptor->frame_end = nano_time ();
+
+ raptor->frame_time = raptor->frame_end - raptor->frame_begin;
+
+ if (raptor->frame_time < 1000000000ul / raptor->gameplay_framerate) {
+ nano_wait (1000000000ul / raptor->gameplay_framerate - raptor->frame_time);
+ }
+
+ if (raptor->global_tick % raptor->gameplay_framerate == 0) {
+ raptor->framerate = (uint) (1000000000ul / raptor->frame_time);
+ }
+
+ ++raptor->global_tick;
+
+ raptor->global_tick = raptor->global_tick % (raptor->gameplay_framerate * raptor->animation_framerate);
+
+ raptor->gameplay_tick = raptor->global_tick / raptor->animation_framerate;
+ raptor->animation_tick = raptor->global_tick / raptor->gameplay_framerate;
+
+ raptor->frame_begin = nano_time ();
+}
+
+////////////// MOVE ME PLEASE
+
+static void raptor_render_rectangle_vertical_gradient (raptor_structure * raptor, int x, int y, uint width, uint height, uint colour_up,
+ uint colour_down) {
+ raptor_render_base (raptor, raptor->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16.0f, (float) height / 16.0f, 0, 0,
+ colour_up, colour_up, colour_down, colour_down);
+}
--- /dev/null
+/// _
+/// __ ____ _ _ __| |__ ___ _ __
+/// \ \/ / _` | '__| '_ \ / _ \| '_ |
+/// > < (_| | | | |_) | (_) | | | |
+/// /_/\_\__,_|_| |_.__/ \___/|_| |_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xarbon - Source code renderer to PNG image, very slow but self-contained, hardcoded font.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#include <xolatile/xtandard.h>
+#include <xolatile/xyntax.h>
+#include <xolatile/xanguage.h>
+#include <xolatile/xormat/png.h>
+
+static const uint background = 0xff181818;
+static const uint foreground = 0xffcccccc;
+static const uint font_width = 8;
+static const uint font_height = 16;
+static const uint tab_width = 8;
+static const uint render_border = 10;
+
+static uint * render_image = null;
+static uint render_width = 0;
+static uint render_height = 0;
+static uint line_number = 0;
+static uint line_digits = 0;
+
+static void conditionally_exit (language_structure * language, syntax_structure * syntax, bool terminate) {
+ syntax = syntax_deinitialize (syntax);
+ language = language_deinitialize (language);
+
+ if (terminate == true) {
+ exit (log_success);
+ }
+}
+
+static void print_common (void) {
+ print ("/B/4xarbon/-: /4Source code PNG renderer/-\n\n");
+ print ("\tAuthor: /4Ognjen 'xolatile' Milan Robovic/-\n");
+ print ("\tLicense: /4GNU//GPLv3/-\n\n");
+}
+
+static void print_help (void) {
+ print_common ();
+
+ print ("Example usage:\n\n");
+ print ("\t/6$ cat file.ext | xarbon [flags]/- /0---/- You need to pass language flag in this case.\n");
+ print ("\t/6$ xarbon [flags] < file.ext/- /0---/- You need to pass language flag in this case.\n");
+ print ("\t/6$ xarbon file.ext/- /0---/- Language is automatically detected in this case.\n\n");
+ print ("Supported languages:\n\n");
+
+ for (uint index = 0; index < language_count; ++index) {
+ char align [32] = "";
+
+ print ("\t/B/4%s/- /4%s/- /0---/- %s syntax highlighting\n",
+ language_short_option (index),
+ string_align_left (string_copy (align, language_long_option (index)), 9, ' '),
+ language_identifier (index));
+ }
+}
+
+static void print_version (void) {
+ print_common ();
+
+ print ("\tVersion: /40 (Zero)/-\n");
+}
+
+static uint fetch_width (const char * data) {
+ uint image_width = 0;
+ uint count = 0;
+
+ do {
+ if (* data == '\t') {
+ count += tab_width;
+ } else if (* data == '\n') {
+ image_width = (++count > image_width) ? count : image_width;
+ count = 0;
+ } else {
+ ++count;
+ }
+ } while (* (++data) != '\0');
+
+ return (image_width - 1);
+}
+
+static uint fetch_height (const char * data) {
+ uint image_height = 0;
+ uint count = 0;
+
+ do {
+ if (* data == '\n') {
+ ++image_height;
+ }
+ } while (* (++data) != '\0');
+
+ count = image_height + 1;
+
+ do {
+ ++line_digits;
+
+ count /= 10;
+ } while (count > 0);
+
+ return (image_height + 1);
+}
+
+static void render_character (char character, uint * x, uint * y, uint colour) {
+ const ulong glyphmap [192] = {
+ 0x0000000000000000, 0x0000000000000000, 0x0000101010101010, 0x1000101000000000, 0x0024242400000000, 0x0000000000000000,
+ 0x00002424247e2424, 0x7e24242400000000, 0x0010107c9290907c, 0x1212927c10100000, 0x0000649468081010, 0x202c524c00000000,
+ 0x000018242418304a, 0x4444443a00000000, 0x0010101000000000, 0x0000000000000000, 0x0000081020202020, 0x2020100800000000,
+ 0x0000201008080808, 0x0808102000000000, 0x000000000024187e, 0x1824000000000000, 0x000000000010107c, 0x1010000000000000,
+ 0x0000000000000000, 0x0000101020000000, 0x000000000000007e, 0x0000000000000000, 0x0000000000000000, 0x0000101000000000,
+ 0x0000040408081010, 0x2020404000000000, 0x00003c4242464a52, 0x6242423c00000000, 0x0000081828080808, 0x0808083e00000000,
+ 0x00003c4242020408, 0x1020407e00000000, 0x00003c4242021c02, 0x0242423c00000000, 0x000002060a122242, 0x7e02020200000000,
+ 0x00007e4040407c02, 0x0202423c00000000, 0x00001c2040407c42, 0x4242423c00000000, 0x00007e0202040408, 0x0810101000000000,
+ 0x00003c4242423c42, 0x4242423c00000000, 0x00003c424242423e, 0x0202043800000000, 0x0000000000101000, 0x0000101000000000,
+ 0x0000000000101000, 0x0000101020000000, 0x0000000408102040, 0x2010080400000000, 0x00000000007e0000, 0x7e00000000000000,
+ 0x0000004020100804, 0x0810204000000000, 0x00003c4242420408, 0x0800080800000000, 0x00007c829ea2a2a2, 0xa69a807e00000000,
+ 0x00003c424242427e, 0x4242424200000000, 0x00007c4242427c42, 0x4242427c00000000, 0x00003c4242404040, 0x4042423c00000000,
+ 0x0000784442424242, 0x4242447800000000, 0x00007e4040407840, 0x4040407e00000000, 0x00007e4040407840, 0x4040404000000000,
+ 0x00003c424240404e, 0x4242423c00000000, 0x0000424242427e42, 0x4242424200000000, 0x0000381010101010, 0x1010103800000000,
+ 0x00000e0404040404, 0x0444443800000000, 0x0000424448506060, 0x5048444200000000, 0x0000404040404040, 0x4040407e00000000,
+ 0x000082c6aa929282, 0x8282828200000000, 0x000042424262524a, 0x4642424200000000, 0x00003c4242424242, 0x4242423c00000000,
+ 0x00007c424242427c, 0x4040404000000000, 0x00003c4242424242, 0x42424a3c02000000, 0x00007c424242427c, 0x5048444200000000,
+ 0x00003c4240403c02, 0x0242423c00000000, 0x0000fe1010101010, 0x1010101000000000, 0x0000424242424242, 0x4242423c00000000,
+ 0x0000424242424224, 0x2424181800000000, 0x0000828282828292, 0x92aac68200000000, 0x0000424224241818, 0x2424424200000000,
+ 0x0000828244442810, 0x1010101000000000, 0x00007e0202040810, 0x2040407e00000000, 0x0000382020202020, 0x2020203800000000,
+ 0x0000404020201010, 0x0808040400000000, 0x0000380808080808, 0x0808083800000000, 0x0000102844000000, 0x0000000000000000,
+ 0x0000000000000000, 0x0000007e00000000, 0x1008000000000000, 0x0000000000000000, 0x00000000003c023e, 0x4242423e00000000,
+ 0x00004040407c4242, 0x4242427c00000000, 0x00000000003c4240, 0x4040423c00000000, 0x00000202023e4242, 0x4242423e00000000,
+ 0x00000000003c4242, 0x7e40403c00000000, 0x00000e10107c1010, 0x1010101000000000, 0x00000000003e4242, 0x4242423e02023c00,
+ 0x00004040407c4242, 0x4242424200000000, 0x0000101000301010, 0x1010103800000000, 0x00000404000c0404, 0x0404040444443800,
+ 0x0000404040424448, 0x7048444200000000, 0x0000301010101010, 0x1010103800000000, 0x0000000000fc9292, 0x9292929200000000,
+ 0x00000000007c4242, 0x4242424200000000, 0x00000000003c4242, 0x4242423c00000000, 0x00000000007c4242, 0x4242427c40404000,
+ 0x00000000003e4242, 0x4242423e02020200, 0x00000000005e6040, 0x4040404000000000, 0x00000000003e4040, 0x3c02027c00000000,
+ 0x00001010107c1010, 0x1010100e00000000, 0x0000000000424242, 0x4242423e00000000, 0x0000000000424242, 0x2424181800000000,
+ 0x0000000000828292, 0x9292927c00000000, 0x0000000000424224, 0x1824424200000000, 0x0000000000424242, 0x4242423e02023c00,
+ 0x00000000007e0408, 0x1020407e00000000, 0x00000c1010102010, 0x1010100c00000000, 0x0000101010101010, 0x1010101000000000,
+ 0x0000300808080408, 0x0808083000000000, 0x000000000062928c, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000
+ };
+
+ for (ulong index = 0; index < 2; ++index) {
+ for (ulong bit = 64; bit > 0; --bit) {
+ ulong destination = (* y + (index << 3) - ((bit - 1) >> 3) + 7) * render_width + (* x - ((bit - 1) & 7) + 7);
+ ulong source = (glyphmap [2 * (ulong) (character - ' ') + index] >> (bit - 1)) & 1;
+
+ render_image [destination] = (source) ? colour : background;
+ }
+ }
+
+ * x += font_width;
+}
+
+static void render_string (char * string, uint length, uint * x, uint * y, uint colour) {
+ for (uint offset = 0; offset < length; ++offset) {
+ if (string [offset] == '\t') {
+ * x += font_width * tab_width;
+ } else if (string [offset] == '\n') {
+ * y += font_height;
+ * x = render_border;
+
+ render_string (format_to_string ((int) ++line_number, false, 10, (int) line_digits, ' '), line_digits, x, y, foreground);
+
+ * x += font_width;
+ } else {
+ render_character (string [offset], x, y, colour);
+ }
+ }
+}
+
+int main (int argc, char * * argv) {
+ uint select = language_count;
+ uint offset = 0;
+ uint length = 0;
+ uint x = render_border;
+ uint y = render_border;
+ char * buffer = null;
+ char * dump = null;
+
+ syntax_structure * syntax = syntax_initialize (666);
+ language_structure * language = language_initialize (true);
+
+ for (int argument = 1; argument < argc; ++argument) {
+ if (argument_compare (argv [argument], "-h", "--help") == true) {
+ print_help ();
+ conditionally_exit (language, syntax, true);
+ } else if (argument_compare (argv [argument], "-v", "--version") == true) {
+ print_version ();
+ conditionally_exit (language, syntax, true);
+ } else if (argument_compare (argv [argument], "-o", "--output") == true) {
+ if (argument + 1 >= argc) {
+ print ("/f Expected output file name: /1%s/-\n", argv [argument]);
+ conditionally_exit (language, syntax, true);
+ }
+ ++argument;
+ dump = string_duplicate (argv [argument]);
+ continue;
+ }
+
+ for (uint index = 0; index < language_count; ++index) {
+ if (argument_compare (argv [argument], language_short_option (index), language_long_option (index)) == true) {
+ (* (language_highlighter (index))) (language, syntax);
+ select = index;
+ break;
+ }
+ }
+
+ if (file_exists (argv [argument]) == true) {
+ if (select == language_count) {
+ select = (uint) file_type (argv [argument]);
+ }
+ if (buffer == null) {
+ buffer = file_import (argv [argument]);
+ } continue;
+ } else {
+ print ("/f Unrecognized command line argument: /1%s/-\n", argv [argument]);
+ conditionally_exit (language, syntax, true);
+ }
+ }
+
+ if (dump == null) {
+ dump = string_duplicate ("xarbon.png");
+ }
+
+ if (select == language_count) {
+ select = language_common;
+ }
+
+ if (buffer == null) {
+ buffer = record ();
+ }
+
+ language_conditionally_select (language, syntax, select);
+
+ render_width = fetch_width (buffer) * font_width + 2 * render_border;
+ render_height = fetch_height (buffer) * font_height + 2 * render_border;
+
+ render_width += (line_digits + 1) * font_width;
+
+ render_image = allocate (render_width * render_height * sizeof (* render_image));
+
+ for (offset = 0; offset < render_width * render_height; ++offset) {
+ render_image [offset] = background;
+ }
+
+ render_string (format_to_string ((int) ++line_number, false, 10, (int) line_digits, ' '), line_digits, & x, & y, foreground);
+
+ x += font_width;
+
+ for (offset = 0; buffer [offset] != '\0'; offset += length) {
+ select = syntax_select (syntax, & buffer [offset], & length);
+
+ render_string (& buffer [offset], length, & x, & y, (select >= syntax->count) ? background : (uint) syntax->colour [select]);
+ }
+
+ png_image_export (dump, render_image, render_width, render_height);
+
+ conditionally_exit (language, syntax, false);
+
+ render_image = deallocate (render_image);
+ buffer = deallocate (buffer);
+ dump = deallocate (dump);
+
+ return (log_success);
+}
--- /dev/null
+/// _ _ _
+/// __ ____ _ _ __| |_(_) ___| | ___
+/// \ \/ / _` | '__| __| |/ __| |/ _ \
+/// > < (_| | | | |_| | (__| | __/
+/// /_/\_\__,_|_| \__|_|\___|_|\___|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xarticle - Forgiving, kind and nice general static 3D particle system.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+typedef struct {
+ uint count;
+ uint limit;
+ uint * sprite;
+ float * life;
+ uint * colour_in;
+ uint * colour_out;
+ vector_3 * * position;
+ vector_3 * * target;
+ vector_3 * * speed;
+} particle_structure;
+
+static particle_structure * particle_initialize (uint limit) {
+ particle_structure * particle = allocate (sizeof (* particle));
+
+ particle->limit = limit;
+
+ particle->sprite = allocate (limit * sizeof (* particle->sprite));
+ particle->life = allocate (limit * sizeof (* particle->life));
+ particle->colour_in = allocate (limit * sizeof (* particle->colour_in));
+ particle->colour_out = allocate (limit * sizeof (* particle->colour_out));
+ particle->position = allocate (limit * sizeof (* particle->position));
+ particle->target = allocate (limit * sizeof (* particle->target));
+ particle->speed = allocate (limit * sizeof (* particle->speed));
+
+ for (uint index = 0; index < limit; ++index) {
+ particle->life [index] = 0.0f;
+
+ particle->position [index] = allocate (sizeof (* * particle->position));
+ particle->target [index] = allocate (sizeof (* * particle->target));
+ particle->speed [index] = allocate (sizeof (* * particle->speed));
+
+ vector_3_nullify (particle->position [index]);
+ vector_3_nullify (particle->target [index]);
+ vector_3_nullify (particle->speed [index]);
+ }
+
+ return (particle);
+}
+
+static particle_structure * particle_deinitialize (particle_structure * particle) {
+ for (uint index = 0; index < particle->count; ++index) {
+ particle->position [index] = deallocate (particle->position [index]);
+ particle->target [index] = deallocate (particle->target [index]);
+ particle->speed [index] = deallocate (particle->speed [index]);
+ }
+
+ particle->sprite = deallocate (particle->sprite);
+ particle->life = deallocate (particle->life);
+ particle->colour_in = deallocate (particle->colour_in);
+ particle->colour_out = deallocate (particle->colour_out);
+ particle->position = deallocate (particle->position);
+ particle->target = deallocate (particle->target);
+ particle->speed = deallocate (particle->speed);
+
+ return (deallocate (particle));
+}
+
+static void particle_append (particle_structure * particle, uint sprite, float life, uint colour_in, uint colour_out, const vector_3 * position,
+ const vector_3 * target, const vector_3 * speed) {
+ if (particle->count + 1 >= particle->limit) return;
+
+ ++particle->count;
+
+ uint current = particle->count - 1;
+
+ particle->sprite [current] = sprite;
+ particle->life [current] = life;
+ particle->colour_in [current] = colour_in;
+ particle->colour_out [current] = colour_out;
+
+ vector_3_copy (particle->position [current], position);
+ vector_3_copy (particle->target [current], target);
+ vector_3_copy (particle->speed [current], speed);
+}
+
+static void particle_switch (particle_structure * particle, uint this, uint with) {
+ uint_exchange (& particle->sprite [this], & particle->sprite [with]);
+ float_exchange (& particle->life [this], & particle->life [with]);
+ uint_exchange (& particle->colour_in [this], & particle->colour_in [with]);
+ uint_exchange (& particle->colour_out [this], & particle->colour_out [with]);
+ vector_3_exchange ( particle->position [this], particle->position [with]);
+ vector_3_exchange ( particle->target [this], particle->target [with]);
+ vector_3_exchange ( particle->speed [this], particle->speed [with]);
+}
+
+static void particle_remove (particle_structure * particle, uint index) {
+ if (index >= particle->count) return;
+
+ particle_switch (particle, index, particle->count - 1);
+
+ --particle->count;
+}
+
+static void particle_effect_splash (particle_structure * particle, uint sprite, float life, uint colour_in, uint colour_out,
+ vector_3 * position, uint ray_count, float ray_force, float ray_error) {
+ for (uint ray = 0; ray < ray_count; ++ray) {
+ vector_3 target = {
+ //~position->x + frandomize (- ray_force, + ray_force),
+ //~position->y + frandomize (- ray_force, + ray_force),
+ //~position->z + frandomize (- ray_force, + ray_force) + frandomize (- ray_error, + ray_error)
+ //~frandomize (- ray_force, + ray_force),
+ //~frandomize (- ray_force, + ray_force),
+ //~frandomize (- ray_force, + ray_force)
+ 0.0f, 0.0f, 0.0f
+ };
+
+ vector_3 speed = {
+ frandomize (- ray_force, + ray_force),
+ frandomize (- ray_force, + ray_force),
+ frandomize (- ray_force, + ray_force)
+ };
+
+ life += frandomize (- 1.0f, + 1.0f);
+
+ particle_append (particle, sprite, life, colour_in, colour_out, position, & target, & speed);
+ }
+}
+
+static void particle_effect_evaporate (particle_structure * particle, uint sprite, float life, uint colour_in, uint colour_out,
+ vector_3 * position, uint ray_count, float ray_force, float ray_error) {
+ for (uint ray = 0; ray < ray_count; ++ray) {
+ vector_3 target = {
+ frandomize (0.0f, + ray_force / 6.0f),
+ frandomize (0.0f, + ray_force / 1.0f),
+ frandomize (0.0f, + ray_force / 6.0f),
+ };
+
+ vector_3 speed = {
+ frandomize (- ray_force, + ray_force),
+ frandomize (- ray_force, + ray_force),
+ frandomize (- ray_force, + ray_force)
+ };
+
+ life += frandomize (- 1.0f, + 1.0f);
+
+ particle_append (particle, sprite, life, colour_in, colour_out, position, & target, & speed);
+ }
+}
+
+static void particle_synchronize (particle_structure * particle, uint framerate) {
+ for (uint index = 0; index < particle->count; ++index) {
+ particle->life [index] -= 1.0f / (float) framerate;
+
+ if (particle->life [index] < 0.0f) {
+ particle_remove (particle, index);
+ }
+
+ vector_3_add (particle->position [index], particle->speed [index]);
+ vector_3_add (particle->speed [index], particle->target [index]);
+ //~vector_3_add (particle->position [index], particle->target [index]);
+ }
+}
--- /dev/null
+/// _ _
+/// __ ____ _| |_ _ __(_)_ __
+/// \ \/ / _` | __| '__| \ \/ /
+/// > < (_| | |_| | | |> <
+/// /_/\_\__,_|\__|_| |_/_/\_\
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xatrix - Very dumb and slow matrix library, mathematical matrix, because I don't like other people ideas...
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+typedef float matrix_2 [2] [2];
+typedef float matrix_3 [3] [3];
+typedef float matrix_4 [4] [4];
+
+static matrix_2 * matrix_2_assign (matrix_2 * destination,
+ float m00, float m01,
+ float m10, float m11) {
+ destination [0] [0] = m00;
+ destination [0] [1] = m01;
+ destination [1] [0] = m10;
+ destination [1] [1] = m11;
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_assign (matrix_3 * destination,
+ float m00, float m01, float m02,
+ float m10, float m11, float m12,
+ float m20, float m21, float m22) {
+ destination [0] [0] = m00;
+ destination [0] [1] = m01;
+ destination [0] [2] = m02;
+ destination [1] [0] = m10;
+ destination [1] [1] = m11;
+ destination [1] [2] = m12;
+ destination [2] [0] = m20;
+ destination [2] [1] = m21;
+ destination [2] [2] = m22;
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_assign (matrix_4 * destination,
+ float m00, float m01, float m02, float m03,
+ float m10, float m11, float m12, float m13,
+ float m20, float m21, float m22, float m23,
+ float m30, float m31, float m32, float m33) {
+ destination [0] [0] = m00;
+ destination [0] [1] = m01;
+ destination [0] [2] = m02;
+ destination [0] [3] = m03;
+ destination [1] [0] = m10;
+ destination [1] [1] = m11;
+ destination [1] [2] = m12;
+ destination [1] [3] = m13;
+ destination [2] [0] = m20;
+ destination [2] [1] = m21;
+ destination [2] [2] = m22;
+ destination [2] [3] = m23;
+ destination [3] [0] = m30;
+ destination [3] [1] = m31;
+ destination [3] [2] = m32;
+ destination [3] [3] = m33;
+
+ return (destination);
+}
+
+static matrix_2 * matrix_2_nullify (matrix_2 * destination) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ destination [row] [column] = 0.0f;
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_nullify (matrix_3 * destination) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ destination [row] [column] = 0.0f;
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_nullify (matrix_4 * destination) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ destination [row] [column] = 0.0f;
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_2 * matrix_2_identity (matrix_2 * destination) {
+ destination = matrix_2_nullify (destination);
+
+ for (uint index = 0; index < 2; ++index) {
+ destination [index] [index] = 1.0f;
+ }
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_identity (matrix_3 * destination) {
+ destination = matrix_3_nullify (destination);
+
+ for (uint index = 0; index < 3; ++index) {
+ destination [index] [index] = 1.0f;
+ }
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_identity (matrix_4 * destination) {
+ destination = matrix_4_nullify (destination);
+
+ for (uint index = 0; index < 4; ++index) {
+ destination [index] [index] = 1.0f;
+ }
+
+ return (destination);
+}
+
+static float matrix_2_determinant (const matrix_2 * matrix) {
+ const float a = matrix [0] [0] * matrix [1] [1];
+ const float b = matrix [0] [1] * matrix [1] [0];
+
+ return (a - b);
+}
+
+static float matrix_3_determinant (const matrix_3 * matrix) {
+ const matrix_2 matrix_a = { { matrix [1] [1], matrix [1] [2] },
+ { matrix [2] [1], matrix [2] [2] } };
+ const matrix_2 matrix_b = { { matrix [1] [0], matrix [1] [2] },
+ { matrix [2] [0], matrix [2] [2] } };
+ const matrix_2 matrix_c = { { matrix [1] [0], matrix [1] [1] },
+ { matrix [2] [0], matrix [2] [1] } };
+
+ const float a = matrix [0] [0] * matrix_2_determinant (& matrix_a);
+ const float b = matrix [0] [1] * matrix_2_determinant (& matrix_b);
+ const float c = matrix [0] [2] * matrix_2_determinant (& matrix_c);
+
+ return (a - b + c);
+}
+
+static float matrix_4_determinant (const matrix_4 * matrix) {
+ const matrix_3 matrix_a = { { matrix [1] [1], matrix [1] [2], matrix [1] [3] },
+ { matrix [2] [1], matrix [2] [2], matrix [2] [3] },
+ { matrix [3] [1], matrix [3] [2], matrix [3] [3] } };
+ const matrix_3 matrix_b = { { matrix [1] [0], matrix [1] [2], matrix [1] [3] },
+ { matrix [2] [0], matrix [2] [2], matrix [2] [3] },
+ { matrix [3] [0], matrix [3] [2], matrix [3] [3] } };
+ const matrix_3 matrix_c = { { matrix [1] [0], matrix [1] [1], matrix [1] [3] },
+ { matrix [2] [0], matrix [2] [1], matrix [2] [3] },
+ { matrix [3] [0], matrix [3] [1], matrix [3] [3] } };
+ const matrix_3 matrix_d = { { matrix [1] [0], matrix [1] [1], matrix [1] [2] },
+ { matrix [2] [0], matrix [2] [1], matrix [2] [2] },
+ { matrix [3] [0], matrix [3] [1], matrix [3] [2] } };
+
+ const float a = matrix [0] [0] * matrix_3_determinant (& matrix_a);
+ const float b = matrix [0] [1] * matrix_3_determinant (& matrix_b);
+ const float c = matrix [0] [2] * matrix_3_determinant (& matrix_c);
+ const float d = matrix [0] [3] * matrix_3_determinant (& matrix_d);
+
+ return (a - b + c - d);
+}
+
+static matrix_2 * matrix_2_copy (matrix_2 * destination, const matrix_2 * source) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ destination [row] [column] = source [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_copy (matrix_3 * destination, const matrix_3 * source) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ destination [row] [column] = source [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_copy (matrix_4 * destination, const matrix_4 * source) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ destination [row] [column] = source [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_2 * matrix_2_scale (matrix_2 * destination, float scale) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ destination [row] [column] *= scale;
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_scale (matrix_3 * destination, float scale) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ destination [row] [column] *= scale;
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_scale (matrix_4 * destination, float scale) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ destination [row] [column] *= scale;
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_2 * matrix_2_scale_to (matrix_2 * destination, const matrix_2 * source, float scale) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ destination [row] [column] = source [row] [column] * scale;
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_scale_to (matrix_3 * destination, const matrix_3 * source, float scale) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ destination [row] [column] = source [row] [column] * scale;
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_scale_to (matrix_4 * destination, const matrix_4 * source, float scale) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ destination [row] [column] = source [row] [column] * scale;
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_2 * matrix_2_add (matrix_2 * destination, const matrix_2 * source) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ destination [row] [column] += source [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_add (matrix_3 * destination, const matrix_3 * source) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ destination [row] [column] += source [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_add (matrix_4 * destination, const matrix_4 * source) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ destination [row] [column] += source [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_2 * matrix_2_add_to (matrix_2 * destination, const matrix_2 * matrix_a, const matrix_2 * matrix_b) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ destination [row] [column] = matrix_a [row] [column] + matrix_b [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_add_to (matrix_3 * destination, const matrix_3 * matrix_a, const matrix_3 * matrix_b) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ destination [row] [column] = matrix_a [row] [column] + matrix_b [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_add_to (matrix_4 * destination, const matrix_4 * matrix_a, const matrix_4 * matrix_b) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ destination [row] [column] = matrix_a [row] [column] + matrix_b [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_2 * matrix_2_subtract (matrix_2 * destination, const matrix_2 * source) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ destination [row] [column] -= source [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_subtract (matrix_3 * destination, const matrix_3 * source) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ destination [row] [column] -= source [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_subtract (matrix_4 * destination, const matrix_4 * source) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ destination [row] [column] -= source [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_2 * matrix_2_subtract_to (matrix_2 * destination, const matrix_2 * matrix_a, const matrix_2 * matrix_b) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ destination [row] [column] = matrix_a [row] [column] - matrix_b [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_3 * matrix_3_subtract_to (matrix_3 * destination, const matrix_3 * matrix_a, const matrix_3 * matrix_b) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ destination [row] [column] = matrix_a [row] [column] - matrix_b [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_4 * matrix_4_subtract_to (matrix_4 * destination, const matrix_4 * matrix_a, const matrix_4 * matrix_b) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ destination [row] [column] = matrix_a [row] [column] - matrix_b [row] [column];
+ }
+ }
+
+ return (destination);
+}
+
+static matrix_2 * matrix_2_multiply (matrix_2 * result, const matrix_2 * matrix_a, const matrix_2 * matrix_b) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ result [row] [column] = 0.0f;
+
+ for (uint index = 0; index < 2; ++index) {
+ result [row] [column] += matrix_a [row] [index] * matrix_b [index] [column];
+ }
+ }
+ }
+
+ return (result);
+}
+
+static matrix_3 * matrix_3_multiply (matrix_3 * result, const matrix_3 * matrix_a, const matrix_3 * matrix_b) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ result [row] [column] = 0.0f;
+
+ for (uint index = 0; index < 3; ++index) {
+ result [row] [column] += matrix_a [row] [index] * matrix_b [index] [column];
+ }
+ }
+ }
+
+ return (result);
+}
+
+static matrix_4 * matrix_4_multiply (matrix_4 * result, const matrix_4 * matrix_a, const matrix_4 * matrix_b) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ result [row] [column] = 0.0f;
+
+ for (uint index = 0; index < 4; ++index) {
+ result [row] [column] += matrix_a [row] [index] * matrix_b [index] [column];
+ }
+ }
+ }
+
+ return (result);
+}
+
+static float matrix_2_trace (const matrix_2 * matrix) {
+ return (matrix [0] [0] + matrix [1] [1]);
+}
+
+static float matrix_3_trace (const matrix_3 * matrix) {
+ return (matrix [0] [0] + matrix [1] [1] + matrix [2] [2]);
+}
+
+static float matrix_4_trace (const matrix_4 * matrix) {
+ return (matrix [0] [0] + matrix [1] [1] + matrix [2] [2] + matrix [3] [3]);
+}
+
+static bool matrix_2_compare (const matrix_2 * matrix_a, const matrix_2 * matrix_b) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = 0; column < 2; ++column) {
+ if (matrix_a [row] [column] != matrix_b [row] [column]) {
+ return (false);
+ }
+ }
+ }
+
+ return (true);
+}
+
+static bool matrix_3_compare (const matrix_3 * matrix_a, const matrix_3 * matrix_b) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ if (matrix_a [row] [column] != matrix_b [row] [column]) {
+ return (false);
+ }
+ }
+ }
+
+ return (true);
+}
+
+static bool matrix_4_compare (const matrix_4 * matrix_a, const matrix_4 * matrix_b) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ if (matrix_a [row] [column] != matrix_b [row] [column]) {
+ return (false);
+ }
+ }
+ }
+
+ return (true);
+}
+
+static void matrix_2_transpose (matrix_2 * matrix_a, matrix_2 * matrix_b) {
+ for (uint row = 0; row < 2; ++row) {
+ for (uint column = row + 1; column < 2; ++column) {
+ float temporary = matrix_a [row] [column];
+
+ matrix_a [row] [column] = matrix_b [column] [row];
+ matrix_b [column] [row] = temporary;
+ }
+ }
+}
+
+static void matrix_3_transpose (matrix_3 * matrix_a, matrix_3 * matrix_b) {
+ for (uint row = 0; row < 3; ++row) {
+ for (uint column = 0; column < 3; ++column) {
+ float temporary = matrix_a [row] [column];
+
+ matrix_a [row] [column] = matrix_b [column] [row];
+ matrix_b [column] [row] = temporary;
+ }
+ }
+}
+
+static void matrix_4_transpose (matrix_4 * matrix_a, matrix_4 * matrix_b) {
+ for (uint row = 0; row < 4; ++row) {
+ for (uint column = 0; column < 4; ++column) {
+ float temporary = matrix_a [row] [column];
+
+ matrix_a [row] [column] = matrix_b [column] [row];
+ matrix_b [column] [row] = temporary;
+ }
+ }
+}
--- /dev/null
+/// _ _
+/// __ _____ _ __(_)_ __ | |_
+/// \ \/ / __| '__| | '_ \| __|
+/// > < (__| | | | |_) | |_
+/// /_/\_\___|_| |_| .__/ \__|
+/// |_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xcript - Whitespace insignificant INI/CFG-like script parser.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+typedef enum {
+ script_unknown, script_comment, script_string, script_number, script_marker, script_header, script_assign, script_end,
+ script_from, script_to, script_next
+} script_word_type;
+
+typedef struct {
+ char * path;
+ char * source;
+ uint prefix;
+ uint length;
+ uint suffix;
+ uint offset;
+ uint line;
+ uint last_length;
+ char * last_string;
+ bool force;
+ bool range;
+} script_structure;
+
+typedef struct {
+ uint counter;
+ char * * identifier;
+ uint * index;
+} script_information;
+
+static void script_warning (const script_structure * script, bool condition, const char * message) {
+ if (condition == true) {
+ print ("[/3Warning/-] %s: %i: %s\n", script->path, script->line, message);
+ }
+}
+
+static void script_failure (const script_structure * script, bool condition, const char * message) {
+ if (condition == true) {
+ print ("[/1Failure/-] %s: %i: %s\n", script->path, script->line, message);
+
+ print ("/1%s/-", & script->source [script->offset]);
+
+ exit (log_failure);
+ }
+}
+
+static script_structure * script_open (const char * path) {
+ script_structure * script = allocate (sizeof (* script));
+
+ script->path = string_duplicate (path);
+ script->source = file_import (path);
+
+ script->prefix = 0;
+ script->length = 0;
+ script->suffix = 0;
+ script->offset = 0;
+ script->line = 1;
+ script->last_length = 0;
+ script->last_string = & script->source [0];
+
+ return (script);
+}
+
+static script_structure * script_close (script_structure * script) {
+ script->path = deallocate (script->path);
+ script->source = deallocate (script->source);
+
+ return (deallocate (script));
+}
+
+static bool script_compare (const script_structure * script, const char * string) {
+ return (string_compare_limit (string, script->last_string, script->last_length));
+}
+
+static bool script_check (const script_information * information, uint index, const char * identifier) {
+ return (string_compare (identifier, information->identifier [index]));
+}
+
+static char * script_export_string (const script_structure * script) {
+ return (string_duplicate_limit (script->last_string, script->last_length));
+}
+
+static uint script_export_number (const script_structure * script) {
+ return (string_limit_to_number (script->last_string, script->last_length));
+}
+
+static uint script_export_marker (const script_information * information, const script_structure * script) {
+ for (uint counter = 0; counter < information->counter; ++counter) {
+ if (script_compare (script, information->identifier [counter]) == true) {
+ return (information->index [counter]);
+ }
+ }
+
+ script_failure (script, true, "No such identifier defined so far in any of the headers!");
+
+ return (~ 0u);
+}
+
+static script_word_type script_parser (script_structure * script) {
+ script_word_type word = script_unknown;
+
+ script->prefix = 0;
+ script->length = 0;
+ script->suffix = 0;
+
+ for (; character_is_blank (script->source [script->offset + script->prefix]) == true; ++script->prefix) {
+ if (script->source [script->offset + script->prefix] == '\n') {
+ ++script->line;
+ }
+ }
+
+ if (script->source [script->offset + script->prefix] == '\0') {
+ word = script_end;
+ } else if (script->source [script->offset + script->prefix] == '(') {
+ script_failure (script, script->range == true, "You are already defining a range, only one pair of () is allowed.");
+ script->range = true;
+ ++script->length;
+ word = script_from;
+ } else if (script->source [script->offset + script->prefix] == ',') {
+ script_failure (script, script->range == false, "You can't use ',' outside of a range.");
+ ++script->length;
+ word = script_next;
+ } else if (script->source [script->offset + script->prefix] == ')') {
+ script_failure (script, script->range == false, "You already defined a range, only one pair of () is allowed.");
+ script->range = false;
+ ++script->length;
+ word = script_to;
+ } else if (script->source [script->offset + script->prefix] == ';') {
+ for (; script->source [script->offset + script->prefix + script->length] != '\n'; ++script->length) {
+ script_warning (script, script->source [script->offset + script->prefix + script->length] == '\0',
+ "Expected at least a trailing new line or some blank character after a comment!");
+ }
+ word = script_comment;
+ } else if (script->source [script->offset + script->prefix] == '#') {
+ for (; script->source [script->offset + script->prefix + script->length] != '\n'; ++script->length) {
+ script_warning (script, script->source [script->offset + script->prefix + script->length] == '\0',
+ "Expected at least a trailing new line or some blank character after a comment!");
+ }
+ word = script_comment;
+ } else if (script->source [script->offset + script->prefix] == '=') {
+ ++script->length;
+ word = script_assign;
+ } else if (script->source [script->offset + script->prefix] == '"') {
+ script_failure (script, script->range == true, "You can't use string inside of a range.");
+ for (script->length = 1; script->source [script->offset + script->prefix + script->length] != '"'; ++script->length) {
+ script_failure (script, script->source [script->offset + script->prefix + script->length] == '\0',
+ "Unterminated string literal, missing '\"' character.");
+ }
+ ++script->prefix;
+ --script->length;
+ ++script->suffix;
+ word = script_string;
+ } else if (script->source [script->offset + script->prefix] == '\'') {
+ script_failure (script, script->range == true, "You can't use string inside of a range.");
+ for (script->length = 1; script->source [script->offset + script->prefix + script->length] != '\''; ++script->length) {
+ script_failure (script, script->source [script->offset + script->prefix + script->length] == '\0',
+ "Unterminated string literal, missing ''' character.");
+ }
+ ++script->prefix;
+ --script->length;
+ ++script->suffix;
+ word = script_string;
+ } else if (script->source [script->offset + script->prefix] == '[') {
+ script_failure (script, script->range == true, "You can't use header inside of a range.");
+ for (; script->source [script->offset + script->prefix + script->length] != ']'; ++script->length) {
+ script_failure (script, script->source [script->offset + script->prefix + script->length] == '\0',
+ "Unterminated header element, missing ']' character.");
+ }
+ ++script->prefix;
+ --script->length;
+ ++script->suffix;
+ word = script_header;
+ } else if (character_is_digit (script->source [script->offset + script->prefix]) == true) {
+ for (; character_is_digit (script->source [script->offset + script->prefix + script->length]) == true; ++script->length) {
+ script_warning (script, script->source [script->offset + script->prefix + script->length] == '\0',
+ "Expected at least a trailing new line or some blank character after a number!");
+ }
+ word = script_number;
+ } else if (character_is_identifier (script->source [script->offset + script->prefix]) == true) {
+ for (; character_is_identifier (script->source [script->offset + script->prefix + script->length]) == true; ++script->length) {
+ script_warning (script, script->source [script->offset + script->prefix + script->length] == '\0',
+ "Expected at least a trailing new line or some blank character after a marker!");
+ }
+ word = script_marker;
+ } else {
+ script_failure (script, true, format ("Illegal character '%c' in script.", script->source [script->offset + script->prefix]));
+ }
+
+ script->last_string = & script->source [script->offset + script->prefix];
+ script->last_length = script->length;
+
+ script->offset += script->prefix + script->length + script->suffix;
+
+ return (word);
+}
+
+static char * script_expect_header (script_information * information, const script_structure * script, uint index, bool accept) {
+ if (accept == true) {
+ ++information->counter;
+
+ information->identifier = reallocate (information->identifier, information->counter * sizeof (* information->identifier));
+ information->index = reallocate (information->index, information->counter * sizeof (* information->index));
+
+ information->identifier [information->counter - 1] = string_duplicate_limit (script->last_string, script->last_length);
+ information->index [information->counter - 1] = index;
+ }
+
+ return (script_export_string (script));
+}
+
+static char * script_expect_string (script_structure * script) {
+ script_word_type word = script_unknown;
+
+ script_failure (script, (word = script_parser (script)) != script_assign, "Expected '=', assignment operator.");
+ script_failure (script, (word = script_parser (script)) != script_string, "Expected string literal.");
+
+ return (script_export_string (script));
+}
+
+static uint script_expect_number (script_structure * script) {
+ script_word_type word = script_unknown;
+
+ script_failure (script, (word = script_parser (script)) != script_assign, "Expected '=', assignment operator.");
+ script_failure (script, (word = script_parser (script)) != script_number, "Expected number literal.");
+
+ return (script_export_number (script));
+}
+
+static uint script_expect_marker (const script_information * information, script_structure * script) {
+ script_word_type word = script_unknown;
+
+ script_failure (script, (word = script_parser (script)) != script_assign, "Expected '=', assignment operator.");
+ script_failure (script, (word = script_parser (script)) != script_marker, "Expected marker literal.");
+
+ return (script_export_marker (information, script));
+}
+
+static uint script_expect_number_or_marker (const script_information * information, script_structure * script) {
+ script_word_type word = script_unknown;
+
+ script_failure (script, (word = script_parser (script)) != script_assign, "Expected '=', assignment operator.");
+
+ word = script_parser (script);
+
+ if (word == script_number) {
+ return (script_export_number (script));
+ } else if (word == script_marker) {
+ return (script_export_marker (information, script));
+ } else {
+ script_failure (script, true, "Expected number or marker literal.");
+ }
+
+ return (~ 0u);
+}
+
+static uint * script_expect_ordered_array (const script_information * information, script_structure * script, uint * count) {
+ script_word_type word = script_unknown;
+
+ uint found = 0;
+ uint * array = null;
+
+ script_failure (script, (word = script_parser (script)) != script_assign, "Expected '=', assignment operator.");
+ script_failure (script, (word = script_parser (script)) != script_from, "Expected '(', begin range operator.");
+
+ for (word = script_parser (script); word != script_to; word = script_parser (script)) {
+ ++found;
+
+ array = reallocate (array, found * sizeof (* array));
+
+ if (word == script_number) {
+ array [found - 1] = script_export_number (script);
+ } else if (word == script_marker) {
+ array [found - 1] = script_export_marker (information, script);
+ } else {
+ script_failure (script, true, "Expected number or marker!");
+ }
+
+ if ((word = script_parser (script)) == script_to) break;
+
+ script_failure (script, word != script_next, "Expected ranged next ','.");
+ script_failure (script, word == script_end, "Expected ranged to ')'.");
+ }
+
+ (* count) = found;
+
+ return (array);
+}
+
+static uint * script_expect_unordered_array (const script_information * information, script_structure * script, uint count) {
+ script_word_type word = script_unknown;
+
+ uint * array = allocate (count * sizeof (* array));
+
+ script_failure (script, (word = script_parser (script)) != script_assign, "Expected '=', assignment operator.");
+ script_failure (script, (word = script_parser (script)) != script_from, "Expected '(', begin range operator.");
+
+ for (word = script_parser (script); word != script_to; word = script_parser (script)) {
+ uint index = script_export_marker (information, script);
+
+ script_failure (script, word != script_marker, "Expected ranged marker.");
+
+ script_failure (script, (word = script_parser (script)) != script_assign, "Expected '=', assignment operator.");
+
+ word = script_parser (script);
+
+ if (word == script_number) {
+ array [index] = script_export_number (script);
+ } else if (word == script_marker) {
+ array [index] = script_export_marker (information, script);
+ } else {
+ script_failure (script, true, "Expected number or marker!");
+ }
+
+ if ((word = script_parser (script)) == script_to) break;
+
+ script_failure (script, word != script_next, "Expected ranged next ','.");
+ script_failure (script, word == script_end, "Expected ranged to ')'.");
+ }
+
+ return (array);
+}
+
+static script_information * script_initialize (const char * general_script_file_path) {
+ script_information * script = allocate (sizeof (* script));
+
+ script_word_type word = script_unknown;
+
+ script_structure * general = script_open (general_script_file_path);
+
+ for (word = script_parser (general); word != script_end; word = script_parser (general)) {
+ if (word == script_header) {
+ ++script->counter;
+ script->identifier = reallocate (script->identifier, script->counter * sizeof (* script->identifier));
+ script->index = reallocate (script->index, script->counter * sizeof (* script->index));
+ script->identifier [script->counter - 1] = string_duplicate_limit (general->last_string, general->last_length);
+ script->index [script->counter - 1] = script->counter - 1;
+ } else if ((word == script_end) || (word == script_comment)) {
+ continue;
+ } else {
+ script_failure (general, true, "Expected header in general script.");
+ }
+ }
+
+ general = script_close (general);
+
+ return (script);
+}
+
+static script_information * script_deinitialize (script_information * script) {
+ for (uint index = 0; index < script->counter; ++index) {
+ script->identifier [index] = deallocate (script->identifier [index]);
+ }
+
+ script->identifier = deallocate (script->identifier);
+ script->index = deallocate (script->index);
+
+ return (deallocate (script));
+}
+
+static uint script_indexer (script_information * information, const char * identifier) {
+ for (uint counter = 0; counter < information->counter; ++counter) {
+ if (string_compare (identifier, information->identifier [counter]) == true) {
+ return (information->index [counter]);
+ }
+ }
+
+ fatal_failure (true, "script_indexer: No such identifier defined so far in any of the headers!");
+
+ return (~ 0u);
+}
--- /dev/null
+/// _
+/// __ _____ ___| |_ ___ _ __
+/// \ \/ / _ \/ __| __/ _ \| '__|
+/// > < __/ (__| || (_) | |
+/// /_/\_\___|\___|\__\___/|_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xector - Very slow and dumb vector library, mathematical vector, not that C++ cancer by the way...
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+typedef struct {
+ float x, y;
+} vector_2;
+
+typedef struct {
+ float x, y, z;
+} vector_3;
+
+typedef struct {
+ float x, y, z, w;
+} vector_4;
+
+static vector_2 * vector_2_assign (vector_2 * destination, float x, float y) {
+ destination->x = x;
+ destination->y = y;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_assign (vector_3 * destination, float x, float y, float z) {
+ destination->x = x;
+ destination->y = y;
+ destination->z = z;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_assign (vector_4 * destination, float x, float y, float z, float w) {
+ destination->x = x;
+ destination->y = y;
+ destination->z = z;
+ destination->w = w;
+
+ return (destination);
+}
+
+static vector_2 * vector_2_nullify (vector_2 * destination) {
+ destination->x = destination->y = 0.0f;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_nullify (vector_3 * destination) {
+ destination->x = destination->y = destination->z = 0.0f;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_nullify (vector_4 * destination) {
+ destination->x = destination->y = destination->z = destination->w = 0.0f;
+
+ return (destination);
+}
+
+static float vector_2_length (const vector_2 * vector) {
+ const float x = vector->x;
+ const float y = vector->y;
+
+ return (square_root (x * x + y * y));
+}
+
+static float vector_3_length (const vector_3 * vector) {
+ const float x = vector->x;
+ const float y = vector->y;
+ const float z = vector->z;
+
+ return (square_root (x * x + y * y + z * z));
+}
+
+static float vector_4_length (const vector_4 * vector) {
+ const float x = vector->x;
+ const float y = vector->y;
+ const float z = vector->z;
+ const float w = vector->w;
+
+ return (square_root (x * x + y * y + z * z + w * w));
+}
+
+static vector_2 * vector_2_normalize (vector_2 * destination) {
+ const float length = vector_2_length (destination);
+
+ destination->x /= length;
+ destination->y /= length;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_normalize (vector_3 * destination) {
+ const float length = vector_3_length (destination);
+
+ destination->x /= length;
+ destination->y /= length;
+ destination->z /= length;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_normalize (vector_4 * destination) {
+ const float length = vector_4_length (destination);
+
+ destination->x /= length;
+ destination->y /= length;
+ destination->z /= length;
+ destination->w /= length;
+
+ return (destination);
+}
+
+static vector_2 * vector_2_normalize_to (vector_2 * destination, const vector_2 * source) {
+ const float length = vector_2_length (source);
+
+ destination->x = source->x / length;
+ destination->y = source->y / length;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_normalize_to (vector_3 * destination, const vector_3 * source) {
+ const float length = vector_3_length (source);
+
+ destination->x = source->x / length;
+ destination->y = source->y / length;
+ destination->z = source->z / length;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_normalize_to (vector_4 * destination, const vector_4 * source) {
+ const float length = vector_4_length (source);
+
+ destination->x = source->x / length;
+ destination->y = source->y / length;
+ destination->z = source->z / length;
+ destination->w = source->w / length;
+
+ return (destination);
+}
+
+static vector_2 * vector_2_copy (vector_2 * destination, const vector_2 * source) {
+ destination->x = source->x;
+ destination->y = source->y;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_copy (vector_3 * destination, const vector_3 * source) {
+ destination->x = source->x;
+ destination->y = source->y;
+ destination->z = source->z;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_copy (vector_4 * destination, const vector_4 * source) {
+ destination->x = source->x;
+ destination->y = source->y;
+ destination->z = source->z;
+ destination->w = source->w;
+
+ return (destination);
+}
+
+static void vector_2_exchange (vector_2 * vector_a, vector_2 * vector_b) {
+ float_exchange (& vector_a->x, & vector_b->x);
+ float_exchange (& vector_a->y, & vector_b->y);
+}
+
+static void vector_3_exchange (vector_3 * vector_a, vector_3 * vector_b) {
+ float_exchange (& vector_a->x, & vector_b->x);
+ float_exchange (& vector_a->y, & vector_b->y);
+ float_exchange (& vector_a->z, & vector_b->z);
+}
+
+static void vector_4_exchange (vector_4 * vector_a, vector_4 * vector_b) {
+ float_exchange (& vector_a->x, & vector_b->x);
+ float_exchange (& vector_a->y, & vector_b->y);
+ float_exchange (& vector_a->z, & vector_b->z);
+ float_exchange (& vector_a->w, & vector_b->w);
+}
+
+static vector_2 * vector_2_scale (vector_2 * destination, float scale) {
+ destination->x *= scale;
+ destination->y *= scale;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_scale (vector_3 * destination, float scale) {
+ destination->x *= scale;
+ destination->y *= scale;
+ destination->z *= scale;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_scale (vector_4 * destination, float scale) {
+ destination->x *= scale;
+ destination->y *= scale;
+ destination->z *= scale;
+ destination->w *= scale;
+
+ return (destination);
+}
+
+static vector_2 * vector_2_scale_to (vector_2 * destination, const vector_2 * source, float scale) {
+ destination->x = source->x * scale;
+ destination->y = source->y * scale;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_scale_to (vector_3 * destination, const vector_3 * source, float scale) {
+ destination->x = source->x * scale;
+ destination->y = source->y * scale;
+ destination->z = source->z * scale;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_scale_to (vector_4 * destination, const vector_4 * source, float scale) {
+ destination->x = source->x * scale;
+ destination->y = source->y * scale;
+ destination->z = source->z * scale;
+ destination->w = source->w * scale;
+
+ return (destination);
+}
+
+static vector_2 * vector_2_add (vector_2 * destination, const vector_2 * source) {
+ destination->x += source->x;
+ destination->y += source->y;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_add (vector_3 * destination, const vector_3 * source) {
+ destination->x += source->x;
+ destination->y += source->y;
+ destination->z += source->z;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_add (vector_4 * destination, const vector_4 * source) {
+ destination->x += source->x;
+ destination->y += source->y;
+ destination->z += source->z;
+ destination->w += source->w;
+
+ return (destination);
+}
+
+static vector_2 * vector_2_add_to (vector_2 * destination, const vector_2 * vector_a, const vector_2 * vector_b) {
+ destination->x = vector_a->x + vector_b->x;
+ destination->y = vector_a->y + vector_b->y;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_add_to (vector_3 * destination, const vector_3 * vector_a, const vector_3 * vector_b) {
+ destination->x = vector_a->x + vector_b->x;
+ destination->y = vector_a->y + vector_b->y;
+ destination->z = vector_a->z + vector_b->z;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_add_to (vector_4 * destination, const vector_4 * vector_a, const vector_4 * vector_b) {
+ destination->x = vector_a->x + vector_b->x;
+ destination->y = vector_a->y + vector_b->y;
+ destination->z = vector_a->z + vector_b->z;
+ destination->w = vector_a->w + vector_b->w;
+
+ return (destination);
+}
+
+static vector_2 * vector_2_subtract (vector_2 * destination, const vector_2 * source) {
+ destination->x -= source->x;
+ destination->y -= source->y;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_subtract (vector_3 * destination, const vector_3 * source) {
+ destination->x -= source->x;
+ destination->y -= source->y;
+ destination->z -= source->z;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_subtract (vector_4 * destination, const vector_4 * source) {
+ destination->x -= source->x;
+ destination->y -= source->y;
+ destination->z -= source->z;
+ destination->w -= source->w;
+
+ return (destination);
+}
+
+static vector_2 * vector_2_subtract_to (vector_2 * destination, const vector_2 * vector_a, const vector_2 * vector_b) {
+ destination->x = vector_a->x - vector_b->x;
+ destination->y = vector_a->y - vector_b->y;
+
+ return (destination);
+}
+
+static vector_3 * vector_3_subtract_to (vector_3 * destination, const vector_3 * vector_a, const vector_3 * vector_b) {
+ destination->x = vector_a->x - vector_b->x;
+ destination->y = vector_a->y - vector_b->y;
+ destination->z = vector_a->z - vector_b->z;
+
+ return (destination);
+}
+
+static vector_4 * vector_4_subtract_to (vector_4 * destination, const vector_4 * vector_a, const vector_4 * vector_b) {
+ destination->x = vector_a->x - vector_b->x;
+ destination->y = vector_a->y - vector_b->y;
+ destination->z = vector_a->z - vector_b->z;
+ destination->w = vector_a->w - vector_b->w;
+
+ return (destination);
+}
+
+static bool vector_2_compare (const vector_2 * vector_a, const vector_2 * vector_b) {
+ if ((vector_a->x == vector_b->x) && (vector_a->y == vector_b->y)) {
+ return (true);
+ } else {
+ return (false);
+ }
+}
+
+static bool vector_3_compare (const vector_3 * vector_a, const vector_3 * vector_b) {
+ if ((vector_a->x == vector_b->x) && (vector_a->y == vector_b->y) && (vector_a->z == vector_b->z)) {
+ return (true);
+ } else {
+ return (false);
+ }
+}
+
+static bool vector_4_compare (const vector_4 * vector_a, const vector_4 * vector_b) {
+ if ((vector_a->x == vector_b->x) && (vector_a->y == vector_b->y) && (vector_a->z == vector_b->z) && (vector_a->w == vector_b->w)) {
+ return (true);
+ } else {
+ return (false);
+ }
+}
+
+static float vector_2_dot_product (const vector_2 * vector_a, const vector_2 * vector_b) {
+ return (vector_a->x * vector_b->x + vector_a->y * vector_b->y);
+}
+
+static float vector_3_dot_product (const vector_3 * vector_a, const vector_3 * vector_b) {
+ return (vector_a->x * vector_b->x + vector_a->y * vector_b->y + vector_a->z * vector_b->z);
+}
+
+static float vector_4_dot_product (const vector_4 * vector_a, const vector_4 * vector_b) {
+ return (vector_a->x * vector_b->x + vector_a->y * vector_b->y + vector_a->z * vector_b->z + vector_a->w * vector_b->w);
+}
+
+static float vector_2_cross_product (const vector_2 * vector_a, const vector_2 * vector_b) {
+ return (vector_a->x * vector_b->y - vector_a->y * vector_b->x);
+}
+
+static vector_3 * vector_3_cross_product (vector_3 * destination, const vector_3 * source) {
+ destination->x = destination->y * source->z - destination->z * source->y;
+ destination->y = destination->z * source->x - destination->x * source->z;
+ destination->z = destination->x * source->y - destination->y * source->x;
+
+ return (destination);
+}
--- /dev/null
+#define use_fatal_failure
+
+#include <xolatile/xtandard.h>
+#include <xolatile/xcript.h>
+#include <xolatile/xerminal.h>
+
+#define challenges_per_day (10)
+#define attribute_minimum (1)
+#define attribute_maximum (10)
+
+typedef enum {
+ special_strength, special_perception, special_edurance, special_charisma,
+ special_intelligence, special_agility, special_luck,
+ special_count
+} special_enumeration;
+
+typedef struct {
+ uint count;
+ uint limit;
+ uint * completed;
+ uint * * requirement;
+ uint * type;
+ char * * class;
+ char * * description;
+} challenge_structure;
+
+static const char * special_name [special_count] = {
+ "strength", "perception", "edurance", "charisma", "intelligence", "agility", "luck"
+};
+
+static bool challenge_is_repeatable (const challenge_structure * challenges, uint index) {
+ return ((challenges->type [index] == special_strength + 1) ||
+ (challenges->type [index] == special_edurance + 1) ||
+ (challenges->type [index] == special_agility + 1));
+}
+
+static bool challenge_is_available (const challenge_structure * challenges, uint index) {
+ return ((challenges->completed [index] == 0) || (challenge_is_repeatable (challenges, index) == true));
+}
+
+static bool challenge_is_completable (const uint * special, const challenge_structure * challenges, uint index) {
+ if (challenge_is_available (challenges, index) == false) {
+ return (false);
+ }
+
+ for (uint check = 0; check < special_count; ++check) {
+ if (challenges->requirement [index] [check] > special [check]) {
+ return (false);
+ }
+ }
+
+ return (true);
+}
+
+static void render_challenge_list (terminal_structure * terminal, const uint * special, const challenge_structure * challenges, uint x, uint y) {
+ uint count = 0;
+ uint * array = allocate (challenges->count * sizeof (* array));
+
+ for (uint index = 0; index < challenges->count; ++index) {
+ if (challenge_is_completable (special, challenges, index) == true) {
+ ++count;
+ array [count - 1] = index;
+ }
+ }
+
+ terminal_render_format (terminal, "Count of unlocked challenges: /2/B%i", x, y + 0, count);
+ terminal_render_format (terminal, "Count of locked challenges: /1/B%i", x, y + 1, challenges->count - count);
+
+ for (uint index = 0; index < count; ++index) {
+ terminal_render_character (terminal, '[', colour_grey, effect_bold, x, y + index + 2);
+
+ for (uint value = 0; value < special_count; ++value) {
+ terminal_render_number (terminal, challenges->requirement [array [index]] [value], value + 1, effect_bold, x + 3 * value + 2, y + index + 2);
+ }
+
+ terminal_render_character (terminal, ']', colour_grey, effect_bold, x + special_count * 3 + 1, y + index + 2);
+
+ terminal_render_format (terminal, "/7/B%s/0/B --- /-%s", x + special_count * 3 + 3, y + index + 2,
+ challenges->class [array [index]],
+ challenges->description [array [index]]);
+ }
+
+ array = deallocate (array);
+}
+
+static void render_special_attributes (terminal_structure * terminal, const uint * special, uint offset, uint selection) {
+ for (uint index = 0; index < special_count; ++index) {
+ const uint effect = (selection == index) ? effect_bold : effect_normal;
+ const uint length = attribute_maximum + 3;
+
+ char name [32] = "";
+
+ string_copy_limit (name, special_name [index], sizeof (name));
+
+ terminal_render_fill_bar (terminal, special [index], 10, '+', index + 1, effect, 0, index + offset);
+
+ terminal_render_string (terminal, capitalize (name), index + 1, effect, length, index + offset);
+ }
+}
+
+static void prompt_special_attributes (uint * special) {
+ terminal_structure * terminal = terminal_initialize ();
+
+ uint selection = 0;
+ bool show_help = false;
+
+ const char * main_messages [] = {
+ "Press H or Tab to toggle help.",
+ "Press Q or Escape to use default settings.",
+ "Press S or Enter to save changes.",
+ "",
+ "Choose your SPECIAL attributes:"
+ };
+
+ const char * help_messages [] = {
+ "Show help - H or Tab",
+ "Use default settings - Q or Escape",
+ "Save and quit - S or Enter",
+ "Move up - J, Up arrow key or KP8",
+ "Move down - K, Down arrow key or KP2",
+ "Increase attribute - P, Right arrow key or KP6",
+ "Decrease attribute - N, Left arrow key or KP4"
+ };
+
+ for (uint index = 0; index < special_count; ++index) {
+ special [index] = 5;
+ }
+
+ while (terminal->active == true) {
+ terminal_render_background (terminal, ' ', colour_white, effect_normal);
+
+ for (uint index = 0; index < array_length (main_messages); ++index) {
+ terminal_render_string (terminal, main_messages [index], colour_white, effect_normal, 0, index);
+ }
+
+ render_special_attributes (terminal, special, array_length (main_messages) + 1, selection);
+
+ if (show_help == true) {
+ for (uint index = 0; index < array_length (help_messages); ++index) {
+ const uint offset = array_length (main_messages) + special_count + 2;
+
+ terminal_render_string (terminal, help_messages [index], colour_white, effect_normal, 0, index + offset);
+ }
+ }
+
+ terminal_synchronize (terminal);
+
+ if ((terminal->signal [signal_tabulator] == true) || (terminal->signal [signal_h] == true)) {
+ show_help = ! show_help;
+ } else if ((terminal->signal [signal_escape] == true) || (terminal->signal [signal_q] == true)) {
+ for (uint index = 0; index < special_count; ++index) {
+ special [index] = 5;
+ } break;
+ } else if ((terminal->signal [signal_return] == true) || (terminal->signal [signal_s] == true)) {
+ break;
+ } else if ((terminal->signal [signal_arrow_up] == true) || (terminal->signal [signal_j] == true)) {
+ selection = (selection - 1 + special_count) % special_count;
+ } else if ((terminal->signal [signal_arrow_down] == true) || (terminal->signal [signal_k] == true)) {
+ selection = (selection + 1) % special_count;
+ } else if ((terminal->signal [signal_arrow_left] == true) || (terminal->signal [signal_h] == true)) {
+ --special [selection];
+ special [selection] = (special [selection] < 1) ? 1 : special [selection];
+ } else if ((terminal->signal [signal_arrow_right] == true) || (terminal->signal [signal_l] == true)) {
+ ++special [selection];
+ special [selection] = (special [selection] > 10) ? 10 : special [selection];
+ }
+ }
+
+ terminal = terminal_deinitialize (terminal);
+}
+
+static void import_user_configuration (uint * special, uint challenge_count, uint * * daily_challenges, bool * * completition) {
+ bool special_defined [special_count] = { false };
+
+ bool daily_challenges_defined = false;
+ bool completition_defined = false;
+
+ script_information * information = allocate (sizeof (* information));
+ script_structure * structure = script_open (configuration_format ("xhallenge.cfg"));
+
+ for (script_word_type word = script_parser (structure); word != script_end; word = script_parser (structure)) {
+ if (word == script_marker) {
+ if (script_compare (structure, "challenges") == true) {
+ uint check = 0;
+ script_failure (structure, daily_challenges_defined == true, "Challenge array was already defined.");
+ (* daily_challenges) = script_expect_ordered_array (information, structure, & check);
+ daily_challenges_defined = true;
+ script_failure (structure, check != challenges_per_day, "Ordered array 'daily_challenges' is incomplete.");
+ for (uint index = 0; index < challenges_per_day; ++index) {
+ script_failure (structure, (* daily_challenges) [index] >= challenge_count, "Invalid index.");
+ }
+ } else if (script_compare (structure, "completition") == true) {
+ uint check = 0;
+ script_failure (structure, completition_defined == true, "Completition array was already defined.");
+ (* completition) = script_expect_ordered_array (information, structure, & check);
+ completition_defined = true;
+ script_failure (structure, check != challenges_per_day, "Ordered array 'completition' is incomplete.");
+ } else for (uint index = 0; index < special_count; ++index) {
+ if (script_compare (structure, special_name [index]) == true) {
+ script_failure (structure, special_defined [index] == true, "Attribute was already defined.");
+ special [index] = script_expect_number (structure);
+ script_failure (structure, special [index] > attribute_maximum, "Attribute exceeded maximum value.");
+ script_failure (structure, special [index] < attribute_minimum, "Attribute exceeded minimum value.");
+ special_defined [index] = true;
+ }
+ }
+ } else if ((word == script_end) || (word == script_comment)) {
+ continue;
+ } else {
+ script_failure (structure, true, "Expected 'marker = number' in configuration script.");
+ }
+ }
+
+ structure = script_close (structure);
+ information = deallocate (information);
+}
+
+static void export_user_configuration (const uint * special, const uint * daily_challenges, const bool * completition) {
+ char buffer [4096] = "";
+
+ for (uint index = 0; index < special_count; ++index) {
+ string_concatenate (buffer, format ("%s = %i\n", special_name [index], special [index]));
+ }
+
+ string_concatenate (buffer, "challenges = (");
+ for (uint index = 0; index < challenges_per_day; ++index) {
+ string_concatenate (buffer, number_to_string (daily_challenges [index]));
+
+ if (index < challenges_per_day - 1) {
+ string_concatenate (buffer, ", ");
+ }
+ }
+ string_concatenate (buffer, ")\n");
+
+ string_concatenate (buffer, "completition = (");
+ for (uint index = 0; index < challenges_per_day; ++index) {
+ string_concatenate (buffer, number_to_string (completition [index]));
+
+ if (index < challenges_per_day - 1) {
+ string_concatenate (buffer, ", ");
+ }
+ }
+ string_concatenate (buffer, ")\n");
+
+ configuration_export ("xhallenge.cfg", buffer);
+}
+
+static challenge_structure * challenges_initialize (uint limit) {
+ challenge_structure * challenges = allocate (sizeof (* challenges));
+
+ challenges->limit = limit;
+
+ return (challenges);
+}
+
+static challenge_structure * challenges_deinitialize (challenge_structure * challenges) {
+ for (uint index = 0; index < challenges->count; ++index) {
+ challenges->requirement [index] = deallocate (challenges->requirement [index]);
+ challenges->description [index] = deallocate (challenges->description [index]);
+ challenges->class [index] = deallocate (challenges->class [index]);
+ }
+
+ challenges->completed = deallocate (challenges->completed);
+ challenges->requirement = deallocate (challenges->requirement);
+ challenges->type = deallocate (challenges->type);
+ challenges->class = deallocate (challenges->class);
+ challenges->description = deallocate (challenges->description);
+
+ return (deallocate (challenges));
+}
+
+static void import_challenges (challenge_structure * challenges) {
+ bool completed_defined = false;
+ bool requirement_defined = false;
+ bool type_defined = false;
+ bool class_defined = false;
+ bool description_defined = false;
+
+ script_information * information = allocate (sizeof (* information));
+ script_structure * structure = script_open (configuration_format ("xhallenge_list.cfg"));
+
+ for (script_word_type word = script_parser (structure); word != script_end; word = script_parser (structure)) {
+ if (word == script_header) {
+ if (challenges->count > 0) {
+ script_warning (structure,
+ (completed_defined == false) ||
+ (requirement_defined == false) ||
+ (type_defined == false) ||
+ (class_defined == false) ||
+ (description_defined == false),
+ "Some fields were left uninitialized and default to zero.");
+ }
+ ++challenges->count;
+ challenges->completed = reallocate (challenges->completed, challenges->count * sizeof (* challenges->completed));
+ challenges->requirement = reallocate (challenges->requirement, challenges->count * sizeof (* challenges->requirement));
+ challenges->type = reallocate (challenges->type, challenges->count * sizeof (* challenges->type));
+ challenges->class = reallocate (challenges->class, challenges->count * sizeof (* challenges->class));
+ challenges->description = reallocate (challenges->description, challenges->count * sizeof (* challenges->description));
+ completed_defined = false;
+ requirement_defined = false;
+ type_defined = false;
+ class_defined = false;
+ description_defined = false;
+ } else if (word == script_marker) {
+ uint current = challenges->count - 1;
+ if (script_compare (structure, "completed") == true) {
+ script_failure (structure, completed_defined == true, "Marker 'completed' already defined.");
+ challenges->completed [current] = script_expect_number (structure);
+ completed_defined = true;
+ } else if (script_compare (structure, "requirement") == true) {
+ uint check = 0;
+ script_failure (structure, requirement_defined == true, "Marker 'requirement' already defined.");
+ challenges->requirement [current] = script_expect_ordered_array (information, structure, & check);
+ requirement_defined = true;
+ script_failure (structure, check != special_count, "Ordered array doesn't have enough elements.");
+ } else if (script_compare (structure, "type") == true) {
+ script_failure (structure, type_defined == true, "Marker 'type' already defined.");
+ challenges->type [current] = script_expect_number (structure);
+ type_defined = true;
+ } else if (script_compare (structure, "class") == true) {
+ script_failure (structure, class_defined == true, "Marker 'class' already defined.");
+ challenges->class [current] = script_expect_string (structure);
+ class_defined = true;
+ } else if (script_compare (structure, "description") == true) {
+ script_failure (structure, description_defined == true, "Marker 'description' already defined.");
+ challenges->description [current] = script_expect_string (structure);
+ description_defined = true;
+ } else {
+ script_failure (structure, true, "Expected name, faction, statistic or ability.");
+ }
+ } else if ((word == script_end) || (word == script_comment)) {
+ continue;
+ } else {
+ script_failure (structure, true, "Expected 'marker = number/string/ordered_array' in configuration script.");
+ }
+ }
+
+ structure = script_close (structure);
+ information = deallocate (information);
+}
+
+static void export_challenges (challenge_structure * challenges) {
+ int file = file_open (configuration_format ("xhallenge_list.cfg"), file_flag_edit | file_flag_truncate);
+
+ for (uint index = 0; index < challenges->count; ++index) {
+ file_echo (file, "[] ");
+
+ file_echo (file, format ("completed = %i ", challenges->completed [index]));
+
+ file_echo (file, "requirement = (");
+ for (uint subindex = 0; subindex < special_count; ++subindex) {
+ file_echo (file, number_to_string (challenges->requirement [index] [subindex]));
+
+ if (subindex < special_count - 1) {
+ file_echo (file, ", ");
+ }
+ }
+ file_echo (file, ") ");
+
+ file_echo (file, format ("type = %i ", challenges->type [index]));
+ file_echo (file, format ("class = \"%s\" ", challenges->class [index]));
+ file_echo (file, format ("description = \"%s\"\n", challenges->description [index]));
+ }
+
+ file = file_close (file);
+}
+
+static uint generate_challenge (const uint * special, const challenge_structure * challenges) {
+ uint index = urandomize (0, challenges->count - 1);
+ bool valid = false;
+
+ while (valid == false) {
+ valid = true;
+ index = urandomize (0, challenges->count - 1);
+
+ if ((challenges->completed [index] > 0) && (challenges->type [index] != 1) && (challenges->type [index] != 3)) continue;
+
+ for (uint check = 0; check < special_count; ++check) {
+ if (challenges->requirement [index] [check] > special [check]) {
+ valid = false;
+ break;
+ }
+ }
+ }
+
+ return (index);
+}
+
+static void generate_challenges (const uint * special, const challenge_structure * challenges, uint * * daily_challenges, bool * * completition) {
+ (* daily_challenges) = allocate (challenges_per_day * sizeof (* * daily_challenges));
+ (* completition) = allocate (challenges_per_day * sizeof (* * completition));
+
+ for (uint index = 0; index < challenges_per_day; ++index) {
+ (* daily_challenges) [index] = generate_challenge (special, challenges);
+ }
+}
+
+static void render_challenges (const uint * special, challenge_structure * challenges, uint * daily_challenges, bool * completition) {
+ terminal_structure * terminal = terminal_initialize ();
+
+ uint selection = 0;
+ bool show_help = false;
+ bool show_list = false;
+
+ const char * main_messages [] = {
+ "Press H or Tab to toggle help.",
+ "Press Q or Escape to quit the program without saving changes.",
+ "Press S or Enter to save changes and quit the program.",
+ "",
+ "Your daily challenges:"
+ };
+
+ const char * help_messages [] = {
+ "Show help - H or Tab",
+ "Quit - Q or Escape",
+ "Save and quit - S or Enter",
+ "Move up - J, Up arrow key or KP8",
+ "Move down - K, Down arrow key or KP2",
+ "(Un)Mark challenge - M or Space",
+ "Change challenge - C or Backspace",
+ "Reset challenges - R",
+ "List challenges - L"
+ };
+
+ while (terminal->active == true) {
+ terminal_render_background (terminal, ' ', colour_white, effect_normal);
+
+ for (uint index = 0; index < array_length (main_messages); ++index) {
+ terminal_render_string (terminal, main_messages [index], colour_white, effect_normal, 0, index);
+ }
+
+ for (uint index = 0; index < challenges_per_day; ++index) {
+ uint type = challenges->type [daily_challenges [index]];
+ char * class = challenges->class [daily_challenges [index]];
+ char * description = challenges->description [daily_challenges [index]];
+
+ const uint effect = (selection == index) ? effect_bold : effect_normal;
+
+ const uint offset = array_length (main_messages) + 2;
+
+ const uint alignment = string_length (class) + 4;
+
+ terminal_render_toggle (terminal, completition [index], 0, index + offset);
+
+ terminal_render_string (terminal, class, type, effect, 4, index + offset);
+ terminal_render_string (terminal, " --- ", colour_grey, effect_bold, alignment + 0, index + offset);
+ terminal_render_string (terminal, description, colour_white, effect, alignment + 5, index + offset);
+ }
+
+ if (show_list == true) {
+ render_challenge_list (terminal, special, challenges, 80, 0);
+ }
+
+ if (show_help == true) {
+ const uint offset = array_length (main_messages) + challenges_per_day + 3;
+
+ for (uint index = 0; index < array_length (help_messages); ++index) {
+ terminal_render_string (terminal, help_messages [index], colour_white, effect_normal, 0, index + offset);
+ }
+
+ render_special_attributes (terminal, special, offset + array_length (help_messages) + 1, special_count);
+ }
+
+ terminal_synchronize (terminal);
+
+ if ((terminal->signal [signal_tabulator] == true) || (terminal->signal [signal_h] == true)) {
+ show_help = ! show_help;
+ } else if (/*(terminal->signal [signal_tabulator] == true) || */(terminal->signal [signal_l] == true)) {
+ show_list = ! show_list;
+ } else if ((terminal->signal [signal_return] == true) || (terminal->signal [signal_s] == true)) {
+ export_user_configuration (special, daily_challenges, completition);
+ break;
+ } else if ((terminal->signal [signal_escape] == true) || (terminal->signal [signal_q] == true)) {
+ break;
+ } else if ((terminal->signal [signal_arrow_up] == true) || (terminal->signal [signal_j] == true)) {
+ selection = (selection - 1 + challenges_per_day) % challenges_per_day;
+ } else if ((terminal->signal [signal_arrow_down] == true) || (terminal->signal [signal_k] == true)) {
+ selection = (selection + 1) % challenges_per_day;
+ } else if ((terminal->signal [signal_space] == true) || (terminal->signal [signal_m] == true)) {
+ completition [selection] = ! completition [selection];
+ challenges->completed [daily_challenges [selection]] += (completition [selection] == true) ? 1 : -1;
+ } else if ((terminal->signal [signal_backspace] == true) || (terminal->signal [signal_c] == true)) {
+ daily_challenges [selection] = generate_challenge (special, challenges);
+ completition [selection] = false;
+ } else if (/*(terminal->signal [signal_backspace] == true) || */(terminal->signal [signal_r] == true)) {
+ for (uint index = 0; index < challenges_per_day; ++index) {
+ daily_challenges [index] = generate_challenge (special, challenges);
+ completition [index] = false;
+ }
+ }
+ }
+
+ terminal = terminal_deinitialize (terminal);
+}
+
+int main (int argc, char * * argv) {
+ uint special [special_count] = { 0 };
+
+ uint * daily_challenges = null;
+ bool * completition = null;
+
+ challenge_structure * challenges = challenges_initialize (1024);
+
+ randomize_seed_by_time ();
+
+ if (argc == 2) {
+ if (string_compare (argv [1], "-r") == true) {
+ configuration_remove ("xhallenge.cfg");
+ }
+ }
+
+ import_challenges (challenges);
+
+ if (configuration_exists ("xhallenge.cfg") == true) {
+ import_user_configuration (special, challenges->count, & daily_challenges, & completition);
+ } else {
+ prompt_special_attributes (special);
+ generate_challenges (special, challenges, & daily_challenges, & completition);
+ }
+
+ render_challenges (special, challenges, daily_challenges, completition);
+
+ export_challenges (challenges);
+
+ challenges = challenges_deinitialize (challenges);
+
+ daily_challenges = deallocate (daily_challenges);
+ completition = deallocate (completition);
+
+ return (log_success);
+}
--- /dev/null
+[] completed = 0 requirement = (1, 1, 1, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Eshnunna"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Babylon"
+[] completed = 0 requirement = (1, 1, 1, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Shuruppak"
+[] completed = 0 requirement = (1, 1, 1, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Nippur"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Kish"
+[] completed = 0 requirement = (1, 1, 1, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Isin"
+[] completed = 0 requirement = (1, 1, 1, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Umma"
+[] completed = 0 requirement = (1, 1, 2, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Girsu"
+[] completed = 0 requirement = (1, 1, 2, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Lagash"
+[] completed = 0 requirement = (1, 1, 2, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Uruk"
+[] completed = 0 requirement = (1, 1, 2, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Ur"
+[] completed = 0 requirement = (1, 1, 2, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Larsa"
+[] completed = 0 requirement = (1, 1, 2, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Akshak"
+[] completed = 0 requirement = (1, 1, 2, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Akkad"
+[] completed = 0 requirement = (1, 1, 2, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Marda"
+[] completed = 0 requirement = (1, 1, 2, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Adab"
+[] completed = 0 requirement = (1, 1, 3, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Urfa"
+[] completed = 0 requirement = (1, 1, 3, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Carchemish"
+[] completed = 0 requirement = (1, 1, 3, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Hadatu"
+[] completed = 0 requirement = (1, 1, 3, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Nineveh"
+[] completed = 0 requirement = (1, 1, 3, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Nimrud"
+[] completed = 0 requirement = (1, 1, 3, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Assur"
+[] completed = 0 requirement = (1, 1, 3, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Hatra"
+[] completed = 0 requirement = (1, 1, 3, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Mari"
+[] completed = 0 requirement = (1, 1, 3, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Ekallatum"
+[] completed = 0 requirement = (1, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Terqa"
+[] completed = 0 requirement = (1, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Seleucia"
+[] completed = 0 requirement = (1, 1, 4, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Ugarit"
+[] completed = 0 requirement = (1, 1, 4, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Susa"
+[] completed = 0 requirement = (1, 1, 4, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Estakhr"
+[] completed = 0 requirement = (1, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Parsa"
+[] completed = 0 requirement = (1, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Ganzak"
+[] completed = 0 requirement = (1, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Bastam"
+[] completed = 0 requirement = (1, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Pasargad"
+[] completed = 0 requirement = (1, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Neyriz"
+[] completed = 0 requirement = (1, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Gorgan"
+[] completed = 0 requirement = (1, 1, 4, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Ilion"
+[] completed = 0 requirement = (2, 1, 2, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Hattusa"
+[] completed = 0 requirement = (2, 1, 2, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Sardis"
+[] completed = 0 requirement = (2, 1, 2, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Miletus"
+[] completed = 0 requirement = (2, 1, 2, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Nicaea"
+[] completed = 0 requirement = (2, 1, 2, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Sapinuwa"
+[] completed = 0 requirement = (2, 1, 2, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Yazilikaya"
+[] completed = 0 requirement = (2, 1, 2, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Kanesh"
+[] completed = 0 requirement = (2, 1, 2, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Antalia"
+[] completed = 0 requirement = (2, 1, 2, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Mersin"
+[] completed = 0 requirement = (2, 1, 2, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Adana"
+[] completed = 0 requirement = (2, 1, 2, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Melid"
+[] completed = 0 requirement = (2, 1, 3, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Apamea"
+[] completed = 0 requirement = (2, 1, 3, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Jerusalem"
+[] completed = 0 requirement = (2, 1, 3, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Sarepta"
+[] completed = 0 requirement = (2, 1, 3, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Damascus"
+[] completed = 0 requirement = (2, 1, 3, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Adoraim"
+[] completed = 0 requirement = (2, 1, 3, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Tadmor"
+[] completed = 0 requirement = (2, 1, 3, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Ebla"
+[] completed = 0 requirement = (2, 1, 3, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Alalakh"
+[] completed = 0 requirement = (2, 1, 3, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Petra"
+[] completed = 0 requirement = (2, 1, 3, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Bethsaida"
+[] completed = 0 requirement = (2, 1, 3, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Tripoli"
+[] completed = 0 requirement = (2, 1, 4, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Aleppo"
+[] completed = 0 requirement = (2, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Qatna"
+[] completed = 0 requirement = (2, 1, 4, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Bethlehem"
+[] completed = 0 requirement = (2, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Hazor"
+[] completed = 0 requirement = (2, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Ashkelon"
+[] completed = 0 requirement = (2, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Samaria"
+[] completed = 0 requirement = (2, 1, 4, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Byblos"
+[] completed = 0 requirement = (2, 1, 4, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Jawa"
+[] completed = 0 requirement = (2, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Zahiran"
+[] completed = 0 requirement = (2, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Gezer"
+[] completed = 0 requirement = (3, 1, 4, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Jericho"
+[] completed = 0 requirement = (3, 1, 4, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Hama"
+[] completed = 0 requirement = (3, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Nashan"
+[] completed = 0 requirement = (3, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Qatif"
+[] completed = 0 requirement = (3, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Bakkah"
+[] completed = 0 requirement = (3, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Izki"
+[] completed = 0 requirement = (3, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Enkomi"
+[] completed = 0 requirement = (3, 1, 4, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Jebel Barkal"
+[] completed = 0 requirement = (3, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Adulis"
+[] completed = 0 requirement = (3, 1, 4, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Thonis"
+[] completed = 0 requirement = (3, 1, 4, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Idalion"
+[] completed = 0 requirement = (3, 1, 4, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Kerma"
+[] completed = 0 requirement = (3, 1, 5, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Sembel"
+[] completed = 0 requirement = (3, 1, 5, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Abydos"
+[] completed = 0 requirement = (3, 1, 5, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Kition"
+[] completed = 0 requirement = (3, 1, 5, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Meroe"
+[] completed = 0 requirement = (3, 1, 5, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Matara"
+[] completed = 0 requirement = (3, 1, 5, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Taremu"
+[] completed = 0 requirement = (3, 1, 5, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Kourion"
+[] completed = 0 requirement = (3, 1, 5, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Napata"
+[] completed = 0 requirement = (3, 1, 5, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Aksum"
+[] completed = 0 requirement = (3, 1, 5, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Iunu"
+[] completed = 0 requirement = (3, 1, 5, 1, 1, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Memphis"
+[] completed = 0 requirement = (3, 1, 5, 1, 2, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Yamu"
+[] completed = 0 requirement = (3, 1, 5, 1, 3, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Raqote"
+[] completed = 0 requirement = (3, 1, 5, 1, 4, 1, 1) type = 5 class = "Ancient cities" description = "1 page about ancient city of Khito"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of Belgrade"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Warsaw"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of Ankara"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of Washington"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of London"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of Kiev"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of Cairo"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Havana"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of Paris"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of Tokyo"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Nairobi"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Kingston"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of Berlin"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of Beijing"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of Addis Ababa"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of Brasilia"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of Rome"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Seoul"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Rabat"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Lima"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Madrid"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of New Delhi"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of Accra"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Santiago"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of Moscow"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Bangkok"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Tunis"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Bogota"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of Athens"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Jakarta"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Dakar"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Wellington"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Stockholm"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Tehran"
+[] completed = 0 requirement = (3, 3, 3, 1, 4, 1, 1) type = 5 class = "Cities" description = "1 page about city of Khartoum"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of Dublin"
+[] completed = 0 requirement = (3, 3, 3, 1, 2, 1, 1) type = 5 class = "Cities" description = "1 page about city of Oslo"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Hanoi"
+[] completed = 0 requirement = (3, 3, 3, 1, 3, 1, 1) type = 5 class = "Cities" description = "1 page about city of Ottawa"
+[] completed = 0 requirement = (3, 3, 3, 1, 1, 1, 1) type = 5 class = "Cities" description = "1 page about city of Budapest"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Sargon of Akkad (historical figure)"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Hammurabi of Babylon"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Gilgamesh of Uruk"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Naram-Sin of Akkad"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Ashurbanipal of Assur"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Narmer of Egypt"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Khufu of Egypt"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Akhenaten of Egypt"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Agamemnon of Mycenae"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Leonidas I of Sparta"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Pericles of Athens"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Pyrrhus of Epirus"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Cyrus II of Persia"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Darius I of Persia"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Xerxes I of Persia"
+[] completed = 0 requirement = (3, 1, 2, 1, 1, 4, 1) type = 5 class = "People" description = "1 page about Artaxerxes of Persia"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Tang of Shang"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Wu of Zhou"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Duke of Zhou"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Goujian of Yue"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Chandragupta of Maurya"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Ahoka of Maurya"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Hiram I of Tyre"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Ahab of Israel"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Suppiluliuma I of Hattusa"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Muwatalli II of Hattusa"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Hannibal Barca of Carthage"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Numa Pompilus of Rome"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Nebuchadnezzar II of Babylon"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Shalmaneser III of Assur"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Tiglath-Pileser III of Assur"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Psamtik I of Egypt"
+[] completed = 0 requirement = (3, 1, 2, 1, 2, 4, 1) type = 5 class = "People" description = "1 page about Croesus of Lydia"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Esarhaddon of Assur"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Thutmose III of Egypt"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Zimri-Lim of Mari"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Shulgi of Ur"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Eannatum of Lagash"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Piye of Kush"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Bimbisara of Magadha"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Charlemagne of H.R. Empire"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Ivan III of Moscow"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Harsha of India"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Dawit I of Ethiopia"
+[] completed = 0 requirement = (3, 1, 2, 1, 3, 4, 1) type = 5 class = "People" description = "1 page about Alfred of Wessex"
+[] completed = 0 requirement = (3, 1, 2, 1, 4, 4, 1) type = 5 class = "People" description = "1 page about Matilda of Tuscany"
+[] completed = 0 requirement = (3, 1, 2, 1, 4, 4, 1) type = 5 class = "People" description = "1 page about Rajendra I of Chola"
+[] completed = 0 requirement = (3, 1, 2, 1, 4, 4, 1) type = 5 class = "People" description = "1 page about Ibn Battuta of Morocco"
+[] completed = 0 requirement = (3, 1, 2, 1, 4, 4, 1) type = 5 class = "People" description = "1 page about William of Normandy"
+[] completed = 0 requirement = (3, 1, 2, 1, 4, 4, 1) type = 5 class = "People" description = "1 page about Eleanor of Aquitaine"
+[] completed = 0 requirement = (3, 1, 2, 1, 4, 4, 1) type = 5 class = "People" description = "1 page about Suleiman I of Turkey"
+[] completed = 0 requirement = (3, 1, 2, 1, 4, 4, 1) type = 5 class = "People" description = "1 page about Askia of Songhai"
+[] completed = 0 requirement = (3, 1, 2, 1, 5, 4, 1) type = 5 class = "People" description = "1 page about Henry II of England"
+[] completed = 0 requirement = (3, 1, 2, 1, 5, 4, 1) type = 5 class = "People" description = "1 page about Isabella I of Castile"
+[] completed = 0 requirement = (3, 1, 2, 1, 5, 4, 1) type = 5 class = "People" description = "1 page about Hongwu of Ming"
+[] completed = 0 requirement = (3, 1, 2, 1, 5, 4, 1) type = 5 class = "People" description = "1 page about Ibn Khaldun of Tunisia"
+[] completed = 0 requirement = (3, 1, 2, 1, 5, 4, 1) type = 5 class = "People" description = "1 page about Richard of England"
+[] completed = 0 requirement = (3, 1, 2, 1, 5, 4, 1) type = 5 class = "People" description = "1 page about Ferdinand I of Aragon"
+[] completed = 0 requirement = (3, 1, 2, 1, 5, 4, 1) type = 5 class = "People" description = "1 page about Yongle of Ming"
+[] completed = 0 requirement = (3, 1, 2, 1, 5, 4, 1) type = 5 class = "People" description = "1 page about Sigismund of Luxembourg"
+[] completed = 0 requirement = (3, 1, 2, 1, 5, 4, 1) type = 5 class = "People" description = "1 page about Edward I of England"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Justinian I of Byzantine"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Sejong of Korea"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Nzinga A Nkuwu of Kongo"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Philip II of France"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Basil II of Byzantine"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Jayavarman VII of Khmer"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Robert of Scotland"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Louis IX of France"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Kublai Khan of Mongolia"
+[] completed = 0 requirement = (3, 1, 2, 1, 6, 4, 1) type = 5 class = "People" description = "1 page about Alp Arslan of Seljuk"
+[] completed = 0 requirement = (3, 1, 2, 1, 7, 4, 1) type = 5 class = "People" description = "1 page about Theodoric of Ostrogoths"
+[] completed = 0 requirement = (3, 1, 2, 1, 7, 4, 1) type = 5 class = "People" description = "1 page about Frederick I of H.R. Empire"
+[] completed = 0 requirement = (3, 1, 2, 1, 7, 4, 1) type = 5 class = "People" description = "1 page about Genghis Khan of Mongolia"
+[] completed = 0 requirement = (3, 1, 2, 1, 7, 4, 1) type = 5 class = "People" description = "1 page about Mansa Musa of Mali"
+[] completed = 0 requirement = (3, 1, 2, 1, 7, 4, 1) type = 5 class = "People" description = "1 page about Dushan of Serbia"
+[] completed = 0 requirement = (3, 1, 2, 1, 7, 4, 1) type = 5 class = "People" description = "1 page about Otto I of H.R. Empire"
+[] completed = 0 requirement = (3, 1, 2, 1, 7, 4, 1) type = 5 class = "People" description = "1 page about Timur of Timurid"
+[] completed = 0 requirement = (3, 1, 2, 1, 7, 4, 1) type = 5 class = "People" description = "1 page about Ezana of Aksum"
+[] completed = 0 requirement = (3, 1, 2, 1, 7, 4, 1) type = 5 class = "People" description = "1 page about Harald Hardrada of Norway"
+[] completed = 0 requirement = (2, 2, 2, 1, 5, 1, 1) type = 5 class = "Periods" description = "1 page about Hadean eon"
+[] completed = 0 requirement = (2, 2, 2, 1, 5, 1, 1) type = 5 class = "Periods" description = "1 page about Archean eon"
+[] completed = 0 requirement = (2, 2, 2, 1, 5, 1, 1) type = 5 class = "Periods" description = "1 page about Proterozoic eon"
+[] completed = 0 requirement = (2, 2, 2, 1, 5, 1, 1) type = 5 class = "Periods" description = "1 page about Phanerozoic eon"
+[] completed = 0 requirement = (2, 2, 2, 1, 4, 1, 1) type = 5 class = "Periods" description = "1 page about Palaeoproterozoic era"
+[] completed = 0 requirement = (2, 2, 2, 1, 4, 1, 1) type = 5 class = "Periods" description = "1 page about Mesoproterozoic era"
+[] completed = 0 requirement = (2, 2, 2, 1, 4, 1, 1) type = 5 class = "Periods" description = "1 page about Neoproterozoic era"
+[] completed = 0 requirement = (2, 2, 2, 1, 4, 1, 1) type = 5 class = "Periods" description = "1 page about Paleozoic era"
+[] completed = 0 requirement = (2, 2, 2, 1, 4, 1, 1) type = 5 class = "Periods" description = "1 page about Mesozoic era"
+[] completed = 0 requirement = (2, 2, 2, 1, 4, 1, 1) type = 5 class = "Periods" description = "1 page about Cenozoic era"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Cambrian period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Ordovician period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Silurian period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Devonian period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Carboniferous period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Permian period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Triassic period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Jurassic period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Cretaceous period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Paleogene period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Neogene period"
+[] completed = 0 requirement = (2, 2, 2, 1, 3, 1, 1) type = 5 class = "Periods" description = "1 page about Quaternary period"
+[] completed = 0 requirement = (2, 2, 2, 1, 2, 1, 1) type = 5 class = "Periods" description = "1 page about Paleocene epoch"
+[] completed = 0 requirement = (2, 2, 2, 1, 2, 1, 1) type = 5 class = "Periods" description = "1 page about Eocene epoch"
+[] completed = 0 requirement = (2, 2, 2, 1, 2, 1, 1) type = 5 class = "Periods" description = "1 page about Oligocene epoch"
+[] completed = 0 requirement = (2, 2, 2, 1, 2, 1, 1) type = 5 class = "Periods" description = "1 page about Miocene epoch"
+[] completed = 0 requirement = (2, 2, 2, 1, 2, 1, 1) type = 5 class = "Periods" description = "1 page about Mississippian epoch"
+[] completed = 0 requirement = (2, 2, 2, 1, 2, 1, 1) type = 5 class = "Periods" description = "1 page about Pennsylvanian epoch"
+[] completed = 0 requirement = (2, 2, 2, 1, 2, 1, 1) type = 5 class = "Periods" description = "1 page about Pliocene epoch"
+[] completed = 0 requirement = (2, 2, 2, 1, 2, 1, 1) type = 5 class = "Periods" description = "1 page about Pleistocene epoch"
+[] completed = 0 requirement = (2, 2, 2, 1, 2, 1, 1) type = 5 class = "Periods" description = "1 page about Holocene epoch"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 5 class = "Periods" description = "1 page about Stone age"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 5 class = "Periods" description = "1 page about Bronze age"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 5 class = "Periods" description = "1 page about Iron age"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 5 class = "Periods" description = "1 page about Medieval age"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 5 class = "Periods" description = "1 page about Modern age"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 2 class = "Siege weapons" description = "1 page about battering ram"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 2 class = "Siege weapons" description = "1 page about ballista"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 2 class = "Siege weapons" description = "1 page about mangonel"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 2 class = "Siege weapons" description = "1 page about siege tower"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 2 class = "Siege weapons" description = "1 page about siege ladders"
+[] completed = 0 requirement = (1, 2, 1, 1, 2, 1, 1) type = 2 class = "Siege weapons" description = "1 page about onager"
+[] completed = 0 requirement = (1, 2, 1, 1, 2, 1, 1) type = 2 class = "Siege weapons" description = "1 page about trebuchet"
+[] completed = 0 requirement = (1, 2, 1, 1, 2, 1, 1) type = 2 class = "Siege weapons" description = "1 page about springald"
+[] completed = 0 requirement = (1, 2, 1, 1, 2, 1, 1) type = 2 class = "Siege weapons" description = "1 page about siege hook"
+[] completed = 0 requirement = (1, 2, 1, 1, 2, 1, 1) type = 2 class = "Siege weapons" description = "1 page about lithobolos"
+[] completed = 0 requirement = (1, 3, 1, 1, 3, 1, 1) type = 2 class = "Siege weapons" description = "1 page about mantlet"
+[] completed = 0 requirement = (1, 3, 1, 1, 3, 1, 1) type = 2 class = "Siege weapons" description = "1 page about sambuca"
+[] completed = 0 requirement = (1, 3, 1, 1, 3, 1, 1) type = 2 class = "Siege weapons" description = "1 page about harpax"
+[] completed = 0 requirement = (1, 3, 1, 1, 3, 1, 1) type = 2 class = "Siege weapons" description = "1 page about polybolos"
+[] completed = 0 requirement = (1, 3, 1, 1, 3, 1, 1) type = 2 class = "Siege weapons" description = "1 page about oxybeles"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 2 class = "Cold weapons" description = "1 page about arming sword"
+[] completed = 0 requirement = (1, 1, 1, 1, 2, 1, 1) type = 2 class = "Cold weapons" description = "1 page about rapier sword"
+[] completed = 0 requirement = (1, 1, 1, 1, 3, 1, 1) type = 2 class = "Cold weapons" description = "1 page about claymore sword"
+[] completed = 0 requirement = (1, 2, 1, 1, 4, 1, 1) type = 2 class = "Cold weapons" description = "1 page about falchion sword"
+[] completed = 0 requirement = (1, 2, 1, 1, 5, 1, 1) type = 2 class = "Cold weapons" description = "1 page about scimitar sword"
+[] completed = 0 requirement = (1, 2, 1, 1, 6, 1, 1) type = 2 class = "Cold weapons" description = "1 page about sabre sword"
+[] completed = 0 requirement = (1, 3, 1, 1, 7, 1, 1) type = 2 class = "Cold weapons" description = "1 page about khopesh sword"
+[] completed = 0 requirement = (1, 3, 1, 1, 8, 1, 1) type = 2 class = "Cold weapons" description = "1 page about katana sword"
+[] completed = 0 requirement = (1, 3, 1, 1, 9, 1, 1) type = 2 class = "Cold weapons" description = "1 page about jian sword"
+[] completed = 0 requirement = (1, 4, 1, 1, 9, 1, 1) type = 2 class = "Cold weapons" description = "1 page about estoc sword"
+[] completed = 0 requirement = (1, 4, 1, 1, 9, 1, 1) type = 2 class = "Cold weapons" description = "1 page about urumi sword"
+[] completed = 0 requirement = (1, 4, 1, 1, 9, 1, 1) type = 2 class = "Cold weapons" description = "1 page about zweihander sword"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 2 class = "Cold weapons" description = "1 page about Danish axe"
+[] completed = 0 requirement = (1, 1, 1, 1, 2, 1, 1) type = 2 class = "Cold weapons" description = "1 page about bearded axe"
+[] completed = 0 requirement = (1, 1, 1, 1, 3, 1, 1) type = 2 class = "Cold weapons" description = "1 page about franciska axe"
+[] completed = 0 requirement = (1, 2, 1, 1, 4, 1, 1) type = 2 class = "Cold weapons" description = "1 page about labrys axe"
+[] completed = 0 requirement = (1, 2, 1, 1, 5, 1, 1) type = 2 class = "Cold weapons" description = "1 page about sabaris axe"
+[] completed = 0 requirement = (1, 2, 1, 1, 6, 1, 1) type = 2 class = "Cold weapons" description = "1 page about tomahawk axe"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 2 class = "Cold weapons" description = "1 page about halberd"
+[] completed = 0 requirement = (1, 1, 1, 1, 2, 1, 1) type = 2 class = "Cold weapons" description = "1 page about lance"
+[] completed = 0 requirement = (1, 1, 1, 1, 3, 1, 1) type = 2 class = "Cold weapons" description = "1 page about naginata"
+[] completed = 0 requirement = (1, 2, 1, 1, 4, 1, 1) type = 2 class = "Cold weapons" description = "1 page about sarissa"
+[] completed = 0 requirement = (1, 2, 1, 1, 5, 1, 1) type = 2 class = "Cold weapons" description = "1 page about poleaxe"
+[] completed = 0 requirement = (1, 2, 1, 1, 6, 1, 1) type = 2 class = "Cold weapons" description = "1 page about fauchard"
+[] completed = 0 requirement = (1, 3, 1, 1, 7, 1, 1) type = 2 class = "Cold weapons" description = "1 page about glaive"
+[] completed = 0 requirement = (1, 3, 1, 1, 8, 1, 1) type = 2 class = "Cold weapons" description = "1 page about voulge"
+[] completed = 0 requirement = (1, 3, 1, 1, 9, 1, 1) type = 2 class = "Cold weapons" description = "1 page about falx"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 2 class = "Cold weapons" description = "1 page about self bow"
+[] completed = 0 requirement = (1, 2, 1, 1, 2, 1, 1) type = 2 class = "Cold weapons" description = "1 page about composite bow"
+[] completed = 0 requirement = (1, 3, 1, 1, 3, 1, 1) type = 2 class = "Cold weapons" description = "1 page about compound bow"
+[] completed = 0 requirement = (1, 4, 1, 1, 4, 1, 1) type = 2 class = "Cold weapons" description = "1 page about recurve bow"
+[] completed = 0 requirement = (1, 5, 1, 1, 5, 1, 1) type = 2 class = "Cold weapons" description = "1 page about yumi bow"
+[] completed = 0 requirement = (1, 6, 1, 1, 6, 1, 1) type = 2 class = "Cold weapons" description = "1 page about reflex bow"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 3 class = "Plank" description = "10 seconds"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 3 class = "Plank" description = "20 seconds"
+[] completed = 0 requirement = (2, 1, 2, 1, 1, 2, 1) type = 3 class = "Plank" description = "30 seconds"
+[] completed = 0 requirement = (2, 1, 3, 1, 1, 2, 1) type = 3 class = "Plank" description = "40 seconds"
+[] completed = 0 requirement = (3, 1, 4, 1, 1, 3, 1) type = 3 class = "Plank" description = "50 seconds"
+[] completed = 0 requirement = (3, 1, 5, 1, 1, 3, 1) type = 3 class = "Plank" description = "60 seconds"
+[] completed = 0 requirement = (4, 1, 6, 1, 1, 4, 1) type = 3 class = "Plank" description = "70 seconds"
+[] completed = 0 requirement = (4, 1, 7, 1, 1, 4, 1) type = 3 class = "Plank" description = "80 seconds"
+[] completed = 0 requirement = (5, 1, 8, 1, 1, 5, 1) type = 3 class = "Plank" description = "90 seconds"
+[] completed = 0 requirement = (5, 1, 10, 1, 1, 5, 1) type = 3 class = "Plank" description = "100 seconds"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 3 class = "Side plank" description = "10 seconds"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 3 class = "Side plank" description = "20 seconds"
+[] completed = 0 requirement = (2, 1, 2, 1, 1, 2, 1) type = 3 class = "Side plank" description = "30 seconds"
+[] completed = 0 requirement = (2, 1, 3, 1, 1, 2, 1) type = 3 class = "Side plank" description = "40 seconds"
+[] completed = 0 requirement = (3, 1, 4, 1, 1, 3, 1) type = 3 class = "Side plank" description = "50 seconds"
+[] completed = 0 requirement = (3, 1, 5, 1, 1, 3, 1) type = 3 class = "Side plank" description = "60 seconds"
+[] completed = 0 requirement = (4, 1, 6, 1, 1, 4, 1) type = 3 class = "Side plank" description = "70 seconds"
+[] completed = 0 requirement = (4, 1, 7, 1, 1, 4, 1) type = 3 class = "Side plank" description = "80 seconds"
+[] completed = 0 requirement = (5, 1, 8, 1, 1, 5, 1) type = 3 class = "Side plank" description = "90 seconds"
+[] completed = 0 requirement = (5, 1, 10, 1, 1, 5, 1) type = 3 class = "Side plank" description = "100 seconds"
+[] completed = 0 requirement = (3, 1, 5, 1, 1, 1, 1) type = 3 class = "Fist plank" description = "10 seconds"
+[] completed = 0 requirement = (3, 1, 5, 1, 1, 1, 1) type = 3 class = "Fist plank" description = "20 seconds"
+[] completed = 0 requirement = (4, 1, 6, 1, 1, 2, 1) type = 3 class = "Fist plank" description = "30 seconds"
+[] completed = 0 requirement = (4, 1, 6, 1, 1, 2, 1) type = 3 class = "Fist plank" description = "40 seconds"
+[] completed = 0 requirement = (5, 1, 7, 1, 1, 3, 1) type = 3 class = "Fist plank" description = "50 seconds"
+[] completed = 0 requirement = (5, 1, 7, 1, 1, 3, 1) type = 3 class = "Fist plank" description = "60 seconds"
+[] completed = 0 requirement = (6, 1, 8, 1, 1, 4, 1) type = 3 class = "Fist plank" description = "70 seconds"
+[] completed = 0 requirement = (6, 1, 8, 1, 1, 4, 1) type = 3 class = "Fist plank" description = "80 seconds"
+[] completed = 0 requirement = (7, 1, 9, 1, 1, 5, 1) type = 3 class = "Fist plank" description = "90 seconds"
+[] completed = 0 requirement = (7, 1, 10, 1, 1, 5, 1) type = 3 class = "Fist plank" description = "100 seconds"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "5 repetitions"
+[] completed = 0 requirement = (2, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "10 repetitions"
+[] completed = 0 requirement = (3, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "15 repetitions"
+[] completed = 0 requirement = (4, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "20 repetitions"
+[] completed = 0 requirement = (5, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "25 repetitions"
+[] completed = 0 requirement = (6, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "30 repetitions"
+[] completed = 0 requirement = (7, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "35 repetitions"
+[] completed = 0 requirement = (8, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "40 repetitions"
+[] completed = 0 requirement = (9, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "45 repetitions"
+[] completed = 0 requirement = (10, 1, 1, 1, 1, 1, 1) type = 1 class = "Push-ups" description = "50 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "5 repetitions"
+[] completed = 0 requirement = (2, 1, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "10 repetitions"
+[] completed = 0 requirement = (3, 2, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "15 repetitions"
+[] completed = 0 requirement = (4, 2, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "20 repetitions"
+[] completed = 0 requirement = (5, 3, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "25 repetitions"
+[] completed = 0 requirement = (6, 3, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "30 repetitions"
+[] completed = 0 requirement = (7, 4, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "35 repetitions"
+[] completed = 0 requirement = (8, 4, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "40 repetitions"
+[] completed = 0 requirement = (9, 5, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "45 repetitions"
+[] completed = 0 requirement = (10, 5, 1, 1, 1, 1, 1) type = 1 class = "Fist push-ups" description = "50 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 1 class = "Squats" description = "5 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 2, 1) type = 1 class = "Squats" description = "10 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 3, 1) type = 1 class = "Squats" description = "15 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 4, 1) type = 1 class = "Squats" description = "20 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 5, 1) type = 1 class = "Squats" description = "25 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 6, 1) type = 1 class = "Squats" description = "30 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 7, 1) type = 1 class = "Squats" description = "35 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 8, 1) type = 1 class = "Squats" description = "40 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 9, 1) type = 1 class = "Squats" description = "45 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 10, 1) type = 1 class = "Squats" description = "50 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 1 class = "Crunch" description = "5 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 2, 1) type = 1 class = "Crunch" description = "10 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 3, 1) type = 1 class = "Crunch" description = "15 repetitions"
+[] completed = 0 requirement = (1, 2, 1, 1, 1, 4, 1) type = 1 class = "Crunch" description = "20 repetitions"
+[] completed = 0 requirement = (1, 2, 1, 1, 1, 5, 1) type = 1 class = "Crunch" description = "25 repetitions"
+[] completed = 0 requirement = (1, 2, 1, 1, 1, 6, 1) type = 1 class = "Crunch" description = "30 repetitions"
+[] completed = 0 requirement = (1, 3, 1, 1, 1, 7, 1) type = 1 class = "Crunch" description = "35 repetitions"
+[] completed = 0 requirement = (1, 3, 1, 1, 1, 8, 1) type = 1 class = "Crunch" description = "40 repetitions"
+[] completed = 0 requirement = (1, 3, 1, 1, 1, 9, 1) type = 1 class = "Crunch" description = "45 repetitions"
+[] completed = 0 requirement = (1, 4, 1, 1, 1, 10, 1) type = 1 class = "Crunch" description = "50 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 1 class = "Lunges" description = "5 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 2, 1) type = 1 class = "Lunges" description = "10 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 3, 1) type = 1 class = "Lunges" description = "15 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 4, 1) type = 1 class = "Lunges" description = "20 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 5, 1) type = 1 class = "Lunges" description = "25 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 6, 1) type = 1 class = "Lunges" description = "30 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 7, 1) type = 1 class = "Lunges" description = "35 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 8, 1) type = 1 class = "Lunges" description = "40 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 9, 1) type = 1 class = "Lunges" description = "45 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 10, 1) type = 1 class = "Lunges" description = "50 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 3 class = "Burpees" description = "5 repetitions"
+[] completed = 0 requirement = (2, 1, 2, 1, 1, 2, 1) type = 3 class = "Burpees" description = "10 repetitions"
+[] completed = 0 requirement = (3, 1, 3, 1, 1, 3, 1) type = 3 class = "Burpees" description = "15 repetitions"
+[] completed = 0 requirement = (4, 1, 4, 1, 1, 4, 1) type = 3 class = "Burpees" description = "20 repetitions"
+[] completed = 0 requirement = (5, 1, 5, 1, 1, 5, 1) type = 3 class = "Burpees" description = "25 repetitions"
+[] completed = 0 requirement = (6, 1, 6, 1, 1, 6, 1) type = 3 class = "Burpees" description = "30 repetitions"
+[] completed = 0 requirement = (7, 1, 7, 1, 1, 7, 1) type = 3 class = "Burpees" description = "35 repetitions"
+[] completed = 0 requirement = (8, 1, 8, 1, 1, 8, 1) type = 3 class = "Burpees" description = "40 repetitions"
+[] completed = 0 requirement = (9, 1, 9, 1, 1, 9, 1) type = 3 class = "Burpees" description = "45 repetitions"
+[] completed = 0 requirement = (10, 1, 10, 1, 1, 10, 1) type = 3 class = "Burpees" description = "50 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 1 class = "Sit-ups" description = "5 repetitions"
+[] completed = 0 requirement = (1, 1, 2, 1, 1, 2, 1) type = 1 class = "Sit-ups" description = "10 repetitions"
+[] completed = 0 requirement = (2, 1, 3, 1, 1, 3, 1) type = 1 class = "Sit-ups" description = "15 repetitions"
+[] completed = 0 requirement = (2, 1, 4, 1, 1, 4, 1) type = 1 class = "Sit-ups" description = "20 repetitions"
+[] completed = 0 requirement = (3, 1, 5, 1, 1, 5, 1) type = 1 class = "Sit-ups" description = "25 repetitions"
+[] completed = 0 requirement = (3, 1, 6, 1, 1, 6, 1) type = 1 class = "Sit-ups" description = "30 repetitions"
+[] completed = 0 requirement = (4, 1, 7, 1, 1, 7, 1) type = 1 class = "Sit-ups" description = "35 repetitions"
+[] completed = 0 requirement = (4, 1, 8, 1, 1, 8, 1) type = 1 class = "Sit-ups" description = "40 repetitions"
+[] completed = 0 requirement = (5, 1, 9, 1, 1, 9, 1) type = 1 class = "Sit-ups" description = "45 repetitions"
+[] completed = 0 requirement = (5, 1, 10, 1, 1, 10, 1) type = 1 class = "Sit-ups" description = "50 repetitions"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 7) type = 7 class = "Anti-smoking" description = "smoke less than 20 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 8) type = 7 class = "Anti-smoking" description = "smoke less than 19 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 9) type = 7 class = "Anti-smoking" description = "smoke less than 18 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 1) type = 7 class = "Anti-smoking" description = "smoke less than 17 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 2) type = 7 class = "Anti-smoking" description = "smoke less than 16 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 3) type = 7 class = "Anti-smoking" description = "smoke less than 15 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 4) type = 7 class = "Anti-smoking" description = "smoke less than 14 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 5) type = 7 class = "Anti-smoking" description = "smoke less than 13 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 6) type = 7 class = "Anti-smoking" description = "smoke less than 12 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 1, 1, 1, 7) type = 7 class = "Anti-smoking" description = "smoke less than 11 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 8) type = 7 class = "Anti-smoking" description = "smoke less than 10 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 9) type = 7 class = "Anti-smoking" description = "smoke less than 9 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 1) type = 7 class = "Anti-smoking" description = "smoke less than 8 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 2) type = 7 class = "Anti-smoking" description = "smoke less than 7 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 3) type = 7 class = "Anti-smoking" description = "smoke less than 6 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 4) type = 7 class = "Anti-smoking" description = "smoke less than 5 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 5) type = 7 class = "Anti-smoking" description = "smoke less than 4 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 6) type = 7 class = "Anti-smoking" description = "smoke less than 3 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 7) type = 7 class = "Anti-smoking" description = "smoke less than 2 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 2, 1, 1, 8) type = 7 class = "Anti-smoking" description = "smoke less than 1 cigarettes"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 9) type = 7 class = "Anti-smoking" description = "smoke no cigarettes for entire day"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 1) type = 7 class = "Anti-drinking" description = "drink no alcohol for 1 day"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 2) type = 7 class = "Anti-drinking" description = "drink no alcohol for 2 days"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 3) type = 7 class = "Anti-drinking" description = "drink no alcohol for 3 days"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 4) type = 7 class = "Anti-drinking" description = "drink no alcohol for 4 days"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 5) type = 7 class = "Anti-drinking" description = "drink no alcohol for 5 days"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 6) type = 7 class = "Anti-drinking" description = "drink no alcohol for 6 days"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 7) type = 7 class = "Anti-drinking" description = "drink no alcohol for 7 days"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 8) type = 7 class = "Anti-drinking" description = "drink no alcohol for 8 days"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 9) type = 7 class = "Anti-drinking" description = "drink no alcohol for 9 days"
+[] completed = 0 requirement = (1, 1, 1, 3, 1, 1, 10) type = 7 class = "Anti-drinking" description = "drink no alcohol for 1 week"
+[] completed = 0 requirement = (1, 1, 1, 4, 1, 1, 10) type = 7 class = "Anti-drinking" description = "drink no alcohol for 2 weeks"
+[] completed = 0 requirement = (1, 1, 1, 5, 1, 1, 10) type = 7 class = "Anti-drinking" description = "drink no alcohol for 3 weeks"
+[] completed = 0 requirement = (1, 1, 1, 6, 1, 1, 10) type = 7 class = "Anti-drinking" description = "drink no alcohol for entire month"
--- /dev/null
+/// _
+/// __ _(_) __ _ ___ _ __ ___ __ _
+/// \ \/ / |/ _` / __| '_ ` _ \ / _` |
+/// > <| | (_| \__ \ | | | | | (_| |
+/// /_/\_\_|\__,_|___/_| |_| |_|\__,_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xiasma - Less minimalistic statical x86_64, ELF64, GEENOO/Leenoocks bytecode assembler following IA32e.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#define double_begin (add)
+#define single_begin (increment)
+#define static_1_begin (none)
+#define static_2_begin (system_call)
+#define jump_if_begin (jump_overflow)
+#define move_if_begin (move_overflow)
+#define set_if_begin (set_overflow)
+#define float_begin (float_add)
+#define shift_begin (rotate_left)
+
+#define jump_not_even (jump_odd)
+#define jump_not_odd (jump_even)
+#define jump_not_below (jump_above_equal)
+#define jump_not_below_equal (jump_above)
+#define jump_not_above (jump_below_equal)
+#define jump_not_above_equal (jump_below)
+#define jump_not_lesser (jump_greater_equal)
+#define jump_not_lesser_equal (jump_greater)
+#define jump_not_greater (jump_lesser_equal)
+#define jump_not_greater_equal (jump_lesser)
+#define move_not_even (move_odd)
+#define move_not_odd (move_even)
+#define move_not_below (move_above_equal)
+#define move_not_below_equal (move_above)
+#define move_not_above (move_below_equal)
+#define move_not_above_equal (move_below)
+#define move_not_lesser (move_greater_equal)
+#define move_not_lesser_equal (move_greater)
+#define move_not_greater (move_lesser_equal)
+#define move_not_greater_equal (move_lesser)
+#define set_not_even (set_odd)
+#define set_not_odd (set_even)
+#define set_not_below (set_above_equal)
+#define set_not_below_equal (set_above)
+#define set_not_above (set_below_equal)
+#define set_not_above_equal (set_below)
+#define set_not_lesser (set_greater_equal)
+#define set_not_lesser_equal (set_greater)
+#define set_not_greater (set_lesser_equal)
+#define set_not_greater_equal (set_lesser)
+
+#define elf_main_header_size (0x40)
+#define elf_text_sector_size (0x38)
+#define elf_data_sector_size (0x38)
+
+#define elf_header_size (elf_main_header_size + elf_text_sector_size + elf_data_sector_size)
+
+enum {
+ size_8, size_16, size_32, size_64
+};
+
+enum {
+ for_relative, for_register, for_memory, for_immediate
+};
+
+enum {
+ new_memory, new_relative, new_immediate,
+ add, or, carry_add, carry_subtract,
+ and, subtract, xor, compare,
+ increment, decrement, not, negate,
+ multiply, sign_multiply, divide, sign_divide,
+ float_add, float_multiply, float_compare, float_compare_pop,
+ float_subtract, float_unsubtract, float_divide, float_undivide,
+ carry_rotate_left, carry_rotate_right, rotate_left, rotate_right,
+ shift_left, shift_right, sign_shift_left, sign_shift_right,
+ none, near_return, far_return, leave,
+ pop_flags, push_flags,
+ system_call, cpu_identification, float_none, float_change_sign,
+ float_absolute, float_test, float_examine, float_push_1,
+ float_push_log2_10, float_push_log2_e, float_push_pi, float_push_log10_2,
+ float_push_ln_2, float_push_0, float_2xm1, float_yl2x,
+ float_tangent, float_arctangent, float_extract, float_modulus_push_1,
+ float_decrement, float_increment, float_modulus, float_yl2xp1,
+ float_square_root, float_sine_cosine, float_random, float_scale,
+ float_sine, float_cosine,
+ enter, call, in, out,
+ jump, move, pop, push,
+ jump_overflow, jump_not_overflow, jump_below, jump_above_equal,
+ jump_equal, jump_not_equal, jump_below_equal, jump_above,
+ jump_sign, jump_not_sign, jump_even, jump_odd,
+ jump_lesser, jump_greater_equal, jump_lesser_equal, jump_greater,
+ move_overflow, move_not_overflow, move_below, move_above_equal,
+ move_equal, move_not_equal, move_below_equal, move_above,
+ move_sign, move_not_sign, move_even, move_odd,
+ move_lesser, move_greater_equal, move_lesser_equal, move_greater,
+ set_overflow, set_not_overflow, set_below, set_above_equal,
+ set_equal, set_not_equal, set_below_equal, set_above,
+ set_sign, set_not_sign, set_even, set_odd,
+ set_lesser, set_greater_equal, set_lesser_equal, set_greater,
+ byte_swap, test, exchange, load_address,
+ bit_scan_forward, bit_scan_reverse,
+ repeat, repeat_equal, repeat_not_equal, repeat_zero,
+ repeat_not_zero, loop, loop_equal, loop_not_equal
+};
+
+enum {
+ register_0, register_1, register_2, register_3, register_4, register_5, register_6, register_7,
+ register_8, register_9, register_10, register_11, register_12, register_13, register_14, register_15
+};
+
+static int empty_count = 0;
+static int empty_holes = 1;
+static int * empty_array = null;
+static int * empty_imbue = null;
+static int * empty_store = null;
+
+static int text_sector_size = 0;
+static int data_sector_size = 0;
+
+static unsigned char * text_sector_byte = null;
+static unsigned char * data_sector_byte = null;
+
+static unsigned char elf_main_header_byte [elf_main_header_size] = {
+ 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00,
+ 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char elf_text_sector_byte [elf_text_sector_size] = {
+ 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char elf_data_sector_byte [elf_data_sector_size] = {
+ 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static int front (int data) { return ((data >= register_4) && (data <= register_7)); }
+static int lower (int data) { return ((data >= register_0) && (data <= register_7)); }
+static int upper (int data) { return ((data >= register_8) && (data <= register_15)); }
+
+static int far (int label) { return (label && 1); }
+static int near (int label) { return (label && 0); }
+
+static void inset (int when, int data) {
+ text_sector_byte [text_sector_size] = (unsigned char) data;
+
+ text_sector_size += (unsigned int) when;
+}
+
+static void inset_immediate (int when, int size, int data) {
+ inset ((when), (data >> 0) & 0xff);
+ inset ((when) && (size >= size_16), (data >> 8) & 0xff);
+ inset ((when) && (size >= size_32), (data >> 16) & 0xff);
+ inset ((when) && (size >= size_32), (data >> 24) & 0xff);
+}
+
+static void inset_memory (int when, int size, int data, int base) {
+ empty_array [empty_holes] = text_sector_size;
+ empty_imbue [empty_holes] = data;
+
+ empty_holes += (int) when;
+
+ inset_immediate (when, size, base);
+}
+
+static int store_relative (int * array) {
+ int relative = array [1];
+
+ empty_array [empty_holes] = text_sector_size;
+ empty_imbue [empty_holes] = relative;
+
+ ++empty_holes;
+
+ return (1);
+}
+
+static int store_memory (int * array) {
+ int operation = array [0],
+ memory = array [1];
+
+ empty_store [memory] = text_sector_size;
+
+ ++empty_count;
+
+ return (1);
+}
+
+static int store_immediate (int * array) {
+ int index = 0,
+ operation = array [0],
+ size = array [1],
+ amount = array [2];
+
+ for (index = 0; index < amount; ++index) {
+ inset_immediate (true, size, array [3 + index]);
+ }
+
+ return (amount + 2);
+}
+
+static void short_prefix (int size) {
+ inset (size == size_16, 0x66);
+}
+
+static void long_prefix (int size, int to, int destination, int from, int source) {
+ int to_upper = (to == for_register) && (upper (destination)),
+ from_upper = (from == for_register) && (upper (source)),
+ extension = (size == size_64);
+
+ inset (extension || to_upper || from_upper, 0x40 + 0x01 * to_upper + 0x04 * from_upper + 0x08 * extension);
+}
+
+static void modify_registers (int to, int destination, int from, int source) {
+ int to_register_from_register = ((to == for_register) && (from == for_register));
+
+ inset (to_register_from_register, 0xc0 + 0x01 * (destination & 0x07) + 0x08 * (source & 0x07));
+}
+
+static void modify_memory (int operation, int to, int from) {
+ int to_register_from_memory = ((to == for_register) && (from == for_memory)),
+ to_memory_from_register = ((to == for_memory) && (from == for_register)),
+ to_memory_from_immediate = ((to == for_memory) && (from == for_immediate));
+
+ inset (to_register_from_memory || to_memory_from_register, 0x05 + 0x08 * operation * to_memory_from_immediate);
+}
+
+static int build_double (int * array) {
+ int operation = array [0],
+ size = array [1],
+ to = array [2],
+ destination = array [3],
+ from = array [4],
+ source = array [5];
+
+ int to_register_from_register = ((to == for_register) && (from == for_register)),
+ to_register_from_memory = ((to == for_register) && (from == for_memory)),
+ to_register_from_immediate = ((to == for_register) && (from == for_immediate)),
+ to_register_from_relative = ((to == for_register) && (from == for_relative)),
+ to_memory_from_register = ((to == for_memory) && (from == for_register)),
+ to_memory_from_immediate = ((to == for_memory) && (from == for_immediate));
+
+ short_prefix (size);
+
+ long_prefix (size, to, destination, from, source);
+
+ inset (to_register_from_immediate, 0x80 + 0x01 * (size != size_8));
+ inset (to_register_from_immediate, 0xc0 + 0x08 * (operation - double_begin) + 0x01 * (destination & 0x07));
+
+ modify_registers (to, destination, from, source);
+
+ modify_memory (destination, to, from);
+ modify_memory (source, to, from);
+
+ inset_memory (to_register_from_memory, size_32, source, 0x1000 - text_sector_size - 4);
+ inset_memory (to_memory_from_register, size_32, destination, 0x1000 - text_sector_size - 4);
+ inset_memory (to_memory_from_immediate, size_32, destination, 0x1000 - text_sector_size - 4);
+ inset_memory (to_register_from_relative, size_32, source, 0x4010b0 - text_sector_size - 4);
+
+ inset_immediate (to_register_from_immediate, size, source);
+ inset_immediate (to_memory_from_immediate, size, source);
+
+ return (5);
+}
+
+static int build_single (int * array) {
+ int operation = array [0],
+ size = array [1],
+ to = array [2],
+ destination = array [3];
+
+ int irregularity = ((operation == increment) || (operation == decrement));
+
+ short_prefix (size);
+
+ long_prefix (size, to, destination, 0, 0);
+
+ inset ((size == size_8) && (to == for_register) && front (destination), 0x40);
+
+ inset (true, 0xf7 + 0x08 * irregularity - 0x01 * (size == size_8));
+
+ inset (to == for_register, 0xc0 + 0x08 * (operation - single_begin) + 0x01 * (destination & 0x07));
+ inset (to == for_memory, 0x05 + 0x08 * (operation - single_begin));
+
+ inset_memory (to == for_memory, size_32, destination, 0x1000 - (text_sector_size + 4));
+
+ return (3);
+}
+
+static int build_static_1 (int * array) {
+ int operation = array [0];
+
+ const unsigned char data [] = {
+ 0x90, 0xc3, 0xcb, 0xc9, 0x9d, 0x9c
+ };
+
+ inset (true, data [operation - static_1_begin]);
+
+ return (0);
+}
+
+static int build_static_2 (int * array) {
+ int operation = array [0];
+
+ const unsigned short data [] = {
+ 0x050f, 0xa20f, 0xd0d9, 0xe0d9, 0xe1d9, 0xe4d9, 0xe5d9, 0xe8d9,
+ 0xe9d9, 0xead9, 0xebd9, 0xecd9, 0xedd9, 0xeed9, 0xf0d9, 0xf1d9,
+ 0xf2d9, 0xf3d9, 0xf4d9, 0xf5d9, 0xf6d9, 0xf7d9, 0xf8d9, 0xf9d9,
+ 0xfad9, 0xfbd9, 0xfcd9, 0xfdd9, 0xfed9, 0xffd9
+ };
+
+ inset_immediate (true, size_16, data [operation - static_2_begin]);
+
+ return (0);
+}
+
+static int build_jump_if (int * array) {
+ int operation = array [0],
+ size = array [1],
+ location = array [3];
+
+ inset (far (location) && (size == size_32), 0x0f);
+
+ inset (far (location), 0x80 + operation - jump_if_begin);
+ inset (near (location), 0x70 + operation - jump_if_begin);
+
+ inset_memory (true, size_32, location, -(text_sector_size + 4));
+
+ return (3);
+}
+
+static int build_move_if (int * array) {
+ int operation = array [0],
+ size = array [1],
+ to = array [2],
+ destination = array [3],
+ from = array [4],
+ source = array [5];
+
+ short_prefix (size);
+
+ long_prefix (size, to, destination, from, source);
+
+ inset (true, 0x0f);
+ inset (true, 0x40 + operation - move_if_begin);
+
+ modify_registers (to, destination, from, source);
+
+ modify_memory (destination, to, from);
+
+ return (5);
+}
+
+static int build_set_if (int * array) {
+ int operation = array [0],
+ to = array [2],
+ destination = array [3];
+
+ inset ((to == for_register) && (front (destination)), 0x40);
+ inset ((to == for_register) && (upper (destination)), 0x41);
+
+ inset (true, 0x0f);
+ inset (true, 0x90 + operation - set_if_begin);
+
+ inset (to == for_register, 0xc0 + 0x01 * (destination & 0x07));
+ inset (to == for_memory, 0x05);
+
+ inset_memory (to == for_memory, size_32, destination, 0x1000 - (text_sector_size + 4));
+
+ return (3);
+}
+
+static int build_jump (int * array) {
+ int operation = array [0],
+ size = array [1],
+ to = array [2],
+ destination = array [3];
+
+ inset ((to == for_register) && upper (destination), 0X41);
+
+ inset (to == for_relative, 0xe9 + 0x02 * (size == size_8));
+ inset (to == for_register, 0xff);
+ inset (to == for_register, 0xe0 + 0x01 * (destination & 0x07));
+ inset (to == for_memory, 0xff);
+ inset (to == for_memory, 0x25);
+
+ inset_memory (to == for_relative, size_32, destination, -(text_sector_size + 4));
+ inset_memory (to == for_memory, size_32, destination, 0x4010b0);
+
+ return (3);
+}
+
+static int build_move (int * array) {
+ int operation = array [0],
+ size = array [1],
+ to = array [2],
+ destination = array [3],
+ from = array [4],
+ source = array [5],
+ extension = array [6];
+
+ short_prefix (size);
+
+ long_prefix (size, to, destination, from, source);
+
+ inset ((to == for_register) && (from == for_register), 0x88 + 0x01 * (size != size_8));
+ inset ((to == for_register) && (from == for_memory), 0x8a + 0x01 * (size != size_8));
+ inset ((to == for_memory) && (from == for_register), 0x88 + 0x01 * (size != size_8));
+
+ modify_memory (destination, to, from);
+ modify_memory (source, to, from);
+
+ modify_registers (to, destination, from, source);
+
+ inset ((to == for_register) && ((from == for_immediate) || (from == for_relative)), 0xb0 + 0x08 * (size != size_8) + 0x01 * (destination & 0x07));
+
+ inset ((to == for_memory) && (from == for_immediate), 0xc6 + 0x01 * (size != size_8));
+ inset ((to == for_memory) && (from == for_immediate), 0x05);
+
+ inset_memory ((to == for_register) && (from == for_memory), size_32, source, 0x1000 - text_sector_size - 4);
+ inset_memory ((to == for_memory) && (from == for_register), size_32, destination, 0x1000 - text_sector_size - 4);
+ inset_memory ((to == for_memory) && (from == for_immediate), size_32, destination, 0x1000 - text_sector_size - 4);
+ inset_memory ((to == for_register) && (from == for_relative), size_32, source, 0x4010b0);
+
+ inset_immediate ((to == for_register) && (from == for_immediate) && (size != size_64), size, source);
+ inset_immediate ((to == for_memory) && (from == for_immediate) && (size != size_64), size, source);
+ inset_immediate ((to == for_register) && (from == for_immediate) && (size == size_64), size_32, source);
+ inset_immediate ((to == for_register) && (from == for_immediate) && (size == size_64), size_32, extension);
+ inset_immediate ((to == for_register) && (from == for_immediate) && (size == size_64), size_32, 0);
+
+ return (5 + (size == size_64));
+}
+
+static int build_call (int * array) {
+ int operation = array [0],
+ from = array [1],
+ source = array [2];
+
+ inset ((from == for_register) && (upper (source)), 0x41);
+
+ inset (from == for_relative, 0xe8);
+ inset (from == for_register, 0xff);
+
+ inset_memory (from == for_relative, size_32, source, -(text_sector_size + 4));
+
+ inset (from == for_register, (0xd0 + 0x01 * (source & 0x07)));
+
+ return (2);
+}
+
+static int build_enter (int * array) {
+ int operation = array [0],
+ dynamic_storage = array [1],
+ nesting_level = array [2];
+
+ inset (true, 0xc8);
+
+ inset_immediate (true, size_16, dynamic_storage);
+ inset_immediate (true, size_8, nesting_level & 0x1f);
+
+ return (2);
+}
+
+static int build_float (int * array) {
+ int operation = array [0],
+ size = array [1],
+ from = array [2],
+ source = array [3];
+
+ inset (from == for_memory, 0xd8 + 0x04 * (size == size_64));
+
+ modify_memory (operation, 0, from);
+
+ inset_memory (from == for_memory, size, source, 0);
+
+ return (3);
+}
+
+static int build_shift (int * array) {
+ int operation = array [0],
+ size = array [1],
+ to = array [2],
+ destination = array [3],
+ offset = array [5];
+
+ short_prefix (size);
+
+ long_prefix (size, to, destination, 0, 0);
+
+ inset (true, 0xc0 + 0x01 * (size != size_8));
+
+ inset (to == for_register, 0x05 + 0x08 * (operation & 7));
+ inset (to == for_memory, 0xc0 + 0x08 * (operation & 7));
+
+ inset_memory (to == for_memory, size_32, destination, 0x1000 - text_sector_size - 4);
+ inset_immediate (true, size_8, offset);
+
+ return (5);
+}
+
+static int build_in_out (int * array) {
+ int move = array [0],
+ size = array [1],
+ type = array [2],
+ port = array [3];
+
+ short_prefix (size);
+
+ inset (true, 0xe4 + 0x01 * (size != size_8) + 0x02 * (move != out) + 0x08 * (type == for_register));
+
+ inset_immediate (type == for_immediate, size_8, port);
+
+ return (3);
+}
+
+static int build_pop (int * array) {
+ int operation = array [0],
+ size = array [1],
+ to = array [2],
+ destination = array [3];
+
+ short_prefix (size);
+
+ inset ((to == for_register) && (upper (destination)), 0x41);
+
+ inset (to == for_register, 0x58 + 0x01 * (destination & 0x07));
+ inset (to == for_memory, 0x8f);
+ inset (to == for_memory, 0x05);
+
+ inset_memory (to == for_memory, size_32, destination, 0);
+
+ return (3);
+}
+
+static int build_push (int * array) {
+ int operation = array [0],
+ size = array [1],
+ from = array [2],
+ source = array [3];
+
+ short_prefix (size);
+
+ inset ((from == for_register) && (upper (source)), 0x41);
+
+ inset (from == for_register, 0x50 + 0x01 * (source & 0x07));
+ inset (from == for_memory, 0xff);
+ inset (from == for_memory, 0x35);
+ inset (from == for_immediate, 0x68 + 0x02 * (size == size_8));
+
+ inset_memory (from == for_memory, size_32, source, 0);
+ inset_immediate (from == for_immediate, size, source);
+
+ return (3);
+}
+
+static int build_swap (int * array) {
+ int operation = array [0],
+ size = array [1],
+ destination = array [3];
+
+ long_prefix (size, for_register, destination, 0, 0);
+
+ inset (true, 0x0f);
+ inset (true, 0xc8 + 0x01 * (destination & 0x07));
+
+ return (3);
+}
+
+static int build_bit_scan (int * array) {
+ int operation = array [0],
+ size = array [1],
+ destination = array [3],
+ from = array [4],
+ source = array [5];
+
+ short_prefix (size);
+
+ long_prefix (size, for_register, destination, from, source);
+
+ inset_immediate (true, size_16, 0xbc0f);
+
+ modify_registers (for_register, destination, from, source);
+
+ inset (from == for_memory, 0x05 + 0x08 * destination);
+
+ inset_memory (from == for_memory, size_32, source, 0x1000 - (text_sector_size + 4));
+
+ return (5);
+}
+
+static int build_loop (int * array) {
+ int operation = array [0],
+ location = array [3];
+
+ inset (operation == loop_not_equal, 0xe0);
+ inset (operation == loop_equal, 0xe1);
+ inset (operation == loop, 0xe2);
+
+ inset_memory (1, size_8, location, -(text_sector_size + 1));
+
+ return (3);
+}
+
+static void elf_main_header (void) {
+ int enter = empty_store [0] + 0x4000b0;
+
+ elf_main_header_byte [16] = 0x02;
+ elf_main_header_byte [ 7] = 0x03;
+ elf_main_header_byte [18] = 0x3e;
+
+ memory_copy (& elf_main_header_byte [24], & enter, sizeof (enter));
+}
+
+static void elf_text_sector (unsigned long text_size, unsigned long data_size) {
+ unsigned long text = elf_header_size + text_size - data_size;
+
+ memory_copy (& elf_text_sector_byte [32], & text, (int) sizeof (text));
+ memory_copy (& elf_text_sector_byte [40], & text, (int) sizeof (text));
+}
+
+static void elf_data_sector (unsigned long text_size, unsigned long data_size) {
+ unsigned long data = data_size;
+ unsigned long core = elf_header_size + text_size - data_size;
+ unsigned long move = 0x401000 + core;
+
+ memory_copy (& elf_data_sector_byte [ 8], & core, (int) sizeof (core));
+ memory_copy (& elf_data_sector_byte [16], & move, (int) sizeof (move));
+ memory_copy (& elf_data_sector_byte [24], & move, (int) sizeof (move));
+ memory_copy (& elf_data_sector_byte [32], & data, (int) sizeof (data));
+ memory_copy (& elf_data_sector_byte [40], & data, (int) sizeof (data));
+}
+
+static int (* build_instruction []) (int * array) = {
+ store_memory, store_relative, store_immediate,
+ build_double, build_double, build_double, build_double, build_double, build_double, build_double, build_double,
+ build_single, build_single, build_single, build_single, build_single, build_single, build_single, build_single,
+ build_float, build_float, build_float, build_float, build_float, build_float, build_float, build_float,
+ build_shift, build_shift, build_shift, build_shift, build_shift, build_shift, build_shift, build_shift,
+ build_static_1, build_static_1, build_static_1, build_static_1, build_static_1, build_static_1,
+ build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2,
+ build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2,
+ build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2,
+ build_static_2, build_static_2, build_static_2, build_static_2, build_static_2, build_static_2,
+ build_enter, build_call, build_in_out, build_in_out, build_jump, build_move, build_pop, build_push,
+ build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if,
+ build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if, build_jump_if,
+ build_move_if, build_move_if, build_move_if, build_move_if, build_move_if, build_move_if, build_move_if, build_move_if,
+ build_move_if, build_move_if, build_move_if, build_move_if, build_move_if, build_move_if, build_move_if, build_move_if,
+ build_set_if, build_set_if, build_set_if, build_set_if, build_set_if, build_set_if, build_set_if, build_set_if,
+ build_set_if, build_set_if, build_set_if, build_set_if, build_set_if, build_set_if, build_set_if, build_set_if,
+ build_swap, build_bit_scan, build_bit_scan, build_loop, build_loop, build_loop
+};
+
+static int assemble (int count, int * array) {
+ for (uint index = 0; index < count; ++index) {
+ index += build_instruction [array [index]] (& array [index]);
+ }
+
+ for (uint index = 1; index < empty_holes; ++index) {
+ int set = 0;
+ int get = empty_array [index];
+
+ memory_copy ((char *) & set, (char *) & text_sector_byte [get], (int) sizeof (set));
+
+ set += empty_store [empty_imbue [index]];
+
+ memory_copy ((char *) & text_sector_byte [get], (char *) & set, (int) sizeof (set));
+ }
+
+ return (log_success);
+}
--- /dev/null
+/// _ _ _ _ _ _
+/// __ _(_) __ _| |__ | (_) __ _| |__ | |_
+/// \ \/ / |/ _` | '_ \| | |/ _` | '_ \| __|
+/// > <| | (_| | | | | | | (_| | | | | |_
+/// /_/\_\_|\__, |_| |_|_|_|\__, |_| |_|\__|
+/// |___/ |___/
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xighlight - Generic source code terminal highlighter using VT100 escape sequences, very very slow...
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#include <xolatile/xtandard.h>
+#include <xolatile/xyntax.h>
+#include <xolatile/xanguage.h>
+
+static void conditionally_exit (language_structure * language, syntax_structure * syntax, bool terminate) {
+ syntax = syntax_deinitialize (syntax);
+ language = language_deinitialize (language);
+
+ if (terminate == true) {
+ exit (log_success);
+ }
+}
+
+static void print_common (void) {
+ print ("/B/4xighlight/-: /4Terminal syntax highlighter/-\n\n");
+ print ("\tAuthor: /4Ognjen 'xolatile' Milan Robovic/-\n");
+ print ("\tLicense: /4GNU//GPLv3/-\n\n");
+}
+
+static void print_help (void) {
+ print_common ();
+
+ print ("Example usage:\n\n");
+ print ("\t/6$ cat file.ext | xighlight [flags]/- /0---/- You need to pass language flag in this case.\n");
+ print ("\t/6$ xighlight [flags] < file.ext/- /0---/- You need to pass language flag in this case.\n");
+ print ("\t/6$ xighlight file.ext/- /0---/- Language is automatically detected in this case.\n\n");
+ print ("Supported languages:\n\n");
+
+ for (uint index = 0; index < language_count; ++index) {
+ char align [32] = "";
+
+ print ("\t/B/4%s/- /4%s/- /0---/- %s syntax highlighting\n",
+ language_short_option (index),
+ string_align_left (string_copy (align, language_long_option (index)), 9, ' '),
+ language_identifier (index));
+ }
+}
+
+static void print_version (void) {
+ print_common ();
+
+ print ("\tVersion: /40 (Zero)/-\n");
+}
+
+int main (int argc, char * * argv) {
+ uint select = language_count;
+ uint length = 0;
+ char * buffer = null;
+
+ syntax_structure * syntax = syntax_initialize (360);
+ language_structure * language = language_initialize (false);
+
+ for (int argument = 1; argument < argc; ++argument) {
+ if (argument_compare (argv [argument], "-h", "--help") == true) {
+ print_help ();
+ conditionally_exit (language, syntax, true);
+ } else if (argument_compare (argv [argument], "-v", "--version") == true) {
+ print_version ();
+ conditionally_exit (language, syntax, true);
+ }
+
+ for (uint index = 0; index < language_count; ++index) {
+ if (argument_compare (argv [argument], language_short_option (index), language_long_option (index)) == true) {
+ (* (language_highlighter (index))) (language, syntax);
+ select = index;
+ break;
+ }
+ }
+
+ if (file_exists (argv [argument]) == true) {
+ if (select == language_count) {
+ select = (uint) file_type (argv [argument]);
+ }
+ if (buffer == null) {
+ buffer = file_import (argv [argument]);
+ }
+ }
+ }
+
+ if (select == language_count) {
+ select = language_common;
+ }
+
+ if (buffer == null) {
+ buffer = record ();
+ }
+
+ language_conditionally_select (language, syntax, select);
+
+ for (uint offset = 0; buffer [offset] != '\0'; offset += length) {
+ select = syntax_select (syntax, & buffer [offset], & length);
+
+ if (select >= syntax->count) {
+ echo_colour (colour_white, effect_normal);
+ } else {
+ echo_colour (syntax->colour [select], syntax->effect [select]);
+ }
+
+ output (& buffer [offset], length);
+
+ echo_cancel ();
+ }
+
+ conditionally_exit (language, syntax, false);
+
+ buffer = deallocate (buffer);
+
+ return (log_success);
+}
--- /dev/null
+/// _
+/// __ _____ __ _ _ _ ___ ___ _ _| |_
+/// \ \/ / _ \ / _` | | | |/ _ \/ _ \| | | | __|
+/// > < (_) | (_| | |_| | __/ (_) | |_| | |_
+/// /_/\_\___/ \__, |\__,_|\___|\___/ \__,_|\__|
+/// |___/
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xogueout - Unfun game created for the sole purpose of testing my libraries...
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#include <xolatile/xtandard.h>
+#include <xolatile/xormat/png.h>
+#include <xolatile/xpengl.h>
+
+int main (void) {
+ opengl_structure * opengl = opengl_initialize (60, 60, false, 1024, 1024);
+
+ int x = 0;
+ int y = 0;
+
+ //~opengl_sprite_import (opengl, "");
+
+ opengl_configure (opengl, 640, 480, "Xogueout");
+
+ while (opengl->active == true) {
+ if (opengl->signal [signal_q] == true) break;
+
+ y = opengl->window_height - 64;
+ x = opengl->cursor_x;
+
+ x = maximum (x, 0);
+ x = minimum (x, opengl->window_width - 96);
+
+ opengl_render_rectangle (opengl, x, y, 96, 32, 0xff7700ff);
+
+ opengl_synchronize (opengl, 0x00000000);
+ }
+
+ opengl = opengl_deinitialize (opengl);
+
+ return (log_success);
+}
--- /dev/null
+/// __ _____ _ __ ___ _ __ ___ ___ _ __
+/// \ \/ / _ \| '_ ` _ \| '_ ` _ \ / _ \| '_ \
+/// > < (_) | | | | | | | | | | | (_) | | | |
+/// /_/\_\___/|_| |_| |_|_| |_| |_|\___/|_| |_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xommon - Tiny and elegant XCB wrapper library so I don't have to deal with other people decisions.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_atom.h>
+#include <xcb/xcb_image.h>
+//~#include <xcb/composite.h>
+
+#define common_font_width (8)
+#define common_font_height (16)
+#define common_font_tabulator (4)
+
+#ifndef common_gameplay_framerate
+#define common_gameplay_framerate (60)
+#endif
+
+#ifndef common_animation_framerate
+#define common_animation_framerate (3)
+#endif
+
+typedef enum {
+ common_window_fullscreen = 0x1,
+ common_window_transparent = 0x2,
+ common_window_resizable = 0x4,
+ common_window_decorated = 0x8
+} common_window_flag;
+
+typedef struct {
+ xcb_connection_t * connection;
+ xcb_screen_t * screen;
+ xcb_image_t * image;
+ xcb_window_t window;
+ xcb_gcontext_t context;
+ xcb_pixmap_t pixmap;
+
+ bool signal [signal_count];
+ bool cursor [cursor_count];
+
+ bool active;
+ uint window_width;
+ uint window_height;
+ uint framerate;
+ ulong frame_time;
+ ulong frame_begin;
+ ulong frame_end;
+ uint * framebuffer;
+ uint global_tick;
+ uint gameplay_tick;
+ uint animation_tick;
+ int cursor_x;
+ int cursor_y;
+ bool freeze_cursor;
+ bool freeze_signal;
+ uint sprite_count;
+ uint font_count;
+ uint dummy; /// TODO USE ME PLEASE
+ uint * * sprite_data;
+ uint * sprite_width;
+ uint * sprite_height;
+ uint * * font_index;
+ uint * * font_width;
+ uint * * font_height;
+ char * font_begin;
+ char * font_end;
+} common_structure;
+
+static uint common_center_x (const common_structure * common, uint size) {
+ return ((common->window_width - size) / 2);
+}
+
+static uint common_center_y (const common_structure * common, uint size) {
+ return ((common->window_height - size) / 2);
+}
+
+static bool common_cursor_inside (const common_structure * common, int x, int y, uint width, uint height) {
+ return ((common->cursor_x > x)
+ && (common->cursor_y > y)
+ && (common->cursor_x < x + (int) width)
+ && (common->cursor_y < y + (int) height));
+}
+
+static bool common_cursor_left_click (common_structure * common, int x, int y, uint width, uint height) {
+ if (common->cursor [cursor_left] == true) {
+ common->freeze_cursor = true;
+
+ return (common_cursor_inside (common, x, y, width, height) == true);
+ }
+
+ return (false);
+}
+
+static bool common_cursor_right_click (common_structure * common, int x, int y, uint width, uint height) {
+ if (common->cursor [cursor_right]) {
+ common->freeze_cursor = true;
+
+ return (common_cursor_inside (common, x, y, width, height));
+ }
+
+ return (false);
+}
+
+static uint common_sprite_raw_import (common_structure * common, uint * data, uint width, uint height) {
+ ++common->sprite_count;
+
+ common->sprite_data = reallocate (common->sprite_data, common->sprite_count * sizeof (* common->sprite_data));
+ common->sprite_width = reallocate (common->sprite_width, common->sprite_count * sizeof (* common->sprite_width));
+ common->sprite_height = reallocate (common->sprite_height, common->sprite_count * sizeof (* common->sprite_height));
+
+ common->sprite_data [common->sprite_count - 1] = data;
+ common->sprite_width [common->sprite_count - 1] = width;
+ common->sprite_height [common->sprite_count - 1] = height;
+
+ return (common->sprite_count - 1);
+}
+
+static uint common_font_raw_import (common_structure * common, uint * data, uint image_width, char begin, char end, uint empty) {
+ uint pointer = 0;
+ uint width = 0;
+ uint height = 0;
+ uint * buffer = null;
+
+ ++common->font_count;
+
+ common->font_index = reallocate (common->font_index, common->font_count * sizeof (* common->font_index));
+ common->font_width = reallocate (common->font_width, common->font_count * sizeof (* common->font_width));
+ common->font_height = reallocate (common->font_height, common->font_count * sizeof (* common->font_height));
+ common->font_begin = reallocate (common->font_begin, common->font_count * sizeof (* common->font_begin));
+ common->font_end = reallocate (common->font_end, common->font_count * sizeof (* common->font_end));
+
+ common->font_begin [common->font_count - 1] = begin;
+ common->font_end [common->font_count - 1] = end;
+
+ common->font_index [common->font_count - 1] = allocate ((ulong) (end - begin + 1) * sizeof (* * common->font_index));
+ common->font_width [common->font_count - 1] = allocate ((ulong) (end - begin + 1) * sizeof (* * common->font_width));
+ common->font_height [common->font_count - 1] = allocate ((ulong) (end - begin + 1) * sizeof (* * common->font_height));
+
+ for (char index = begin; index <= end; ++index) {
+ for ( ; data [pointer] == empty; ++pointer);
+ for (width = 0; data [pointer + width] != empty; ++width);
+ for (height = 0; data [pointer + height * image_width] != empty; ++height);
+
+ buffer = allocate (width * height * sizeof (* buffer));
+
+ for (uint y = 0; y < height; ++y) {
+ for (uint x = 0; x < width; ++x) {
+ buffer [y * width + x] = data [pointer + (y * image_width) + x];
+ }
+ }
+
+ common->font_index [common->font_count - 1] [index - begin] = common_sprite_raw_import (common, buffer, width, height);
+ common->font_width [common->font_count - 1] [index - begin] = width;
+ common->font_height [common->font_count - 1] [index - begin] = height;
+
+ pointer += width;
+
+ for (; data [pointer] == empty; ++pointer);
+
+ if (pointer % image_width == 2) {
+ pointer += height * image_width;
+ }
+ }
+
+ return (common->font_count - 1);
+}
+
+static uint common_sprite_import (common_structure * common, const char * path) {
+ uint width = 0;
+ uint height = 0;
+ uint * data = null;
+
+ char buffer [256] = "";
+
+#ifdef use_png_library
+ if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".png")) == true)) {
+ data = png_image_import (buffer, & width, & height);
+ }
+#endif
+
+#ifdef use_jxl_library
+ if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".jxl")) == true)) {
+ data = jxl_image_import (buffer, & width, & height);
+ }
+#endif
+
+ fatal_failure (data == null, "opengl_sprite_import: Unsupported image format.");
+
+ return (common_sprite_raw_import (common, data, width, height));
+}
+
+static uint common_font_import (common_structure * common, const char * path, char begin, char end, uint colour) {
+ uint width = 0;
+ uint height = 0;
+ uint result = 0;
+ uint * data = null;
+
+ char buffer [256] = "";
+
+#ifdef use_png_library
+ if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".png")) == true)) {
+ data = png_image_import (buffer, & width, & height);
+ }
+#endif
+
+#ifdef use_jxl_library
+ if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".jxl")) == true)) {
+ data = jxl_image_import (buffer, & width, & height);
+ }
+#endif
+
+ fatal_failure (data == null, "opengl_font_import: Unsupported image format.");
+
+ result = common_font_raw_import (common, data, width, begin, end, colour);
+
+ data = deallocate (data);
+
+ return (result);
+}
+
+static uint common_sprite_width (const common_structure * common, uint sprite) {
+ return (common->sprite_width [sprite]);
+}
+
+static uint common_sprite_height (const common_structure * common, uint sprite) {
+ return (common->sprite_height [sprite]);
+}
+
+static common_structure * common_initialize (void) {
+ common_structure * common = allocate (sizeof (* common));
+
+ return (common);
+}
+
+static common_structure * common_deinitialize (common_structure * common) {
+ for (uint index = 0; index < common->sprite_count; ++index) {
+ common->sprite_data [index] = deallocate (common->sprite_data [index]);
+ }
+
+ for (uint index = 0; index < common->font_count; ++index) {
+ common->font_index [index] = deallocate (common->font_index [index]);
+ common->font_width [index] = deallocate (common->font_width [index]);
+ common->font_height [index] = deallocate (common->font_height [index]);
+ }
+
+ common->font_index = deallocate (common->font_index);
+ common->font_width = deallocate (common->font_width);
+ common->font_height = deallocate (common->font_height);
+ common->font_begin = deallocate (common->font_begin);
+ common->font_end = deallocate (common->font_end);
+
+ common->sprite_data = deallocate (common->sprite_data);
+ common->sprite_width = deallocate (common->sprite_width);
+ common->sprite_height = deallocate (common->sprite_height);
+
+ common->framebuffer = deallocate (common->framebuffer);
+
+ xcb_free_gc (common->connection, common->context);
+ xcb_free_pixmap (common->connection, common->pixmap);
+ xcb_destroy_window (common->connection, common->window);
+
+ xcb_disconnect (common->connection);
+
+ return (deallocate (common));
+}
+
+static void common_configure (common_structure * common, uint width, uint height, const char * title, uint window_flags) {
+ const ulong font_bitmap [190] = {
+ 0x0000000000000000, 0x0000000000000000, 0x0000101010101010, 0x1000101000000000, 0x0024242400000000, 0x0000000000000000,
+ 0x00002424247e2424, 0x7e24242400000000, 0x0010107c9290907c, 0x1212927c10100000, 0x0000649468081010, 0x202c524c00000000,
+ 0x000018242418304a, 0x4444443a00000000, 0x0010101000000000, 0x0000000000000000, 0x0000081020202020, 0x2020100800000000,
+ 0x0000201008080808, 0x0808102000000000, 0x000000000024187e, 0x1824000000000000, 0x000000000010107c, 0x1010000000000000,
+ 0x0000000000000000, 0x0000101020000000, 0x000000000000007e, 0x0000000000000000, 0x0000000000000000, 0x0000101000000000,
+ 0x0000040408081010, 0x2020404000000000, 0x00003c4242464a52, 0x6242423c00000000, 0x0000081828080808, 0x0808083e00000000,
+ 0x00003c4242020408, 0x1020407e00000000, 0x00003c4242021c02, 0x0242423c00000000, 0x000002060a122242, 0x7e02020200000000,
+ 0x00007e4040407c02, 0x0202423c00000000, 0x00001c2040407c42, 0x4242423c00000000, 0x00007e0202040408, 0x0810101000000000,
+ 0x00003c4242423c42, 0x4242423c00000000, 0x00003c424242423e, 0x0202043800000000, 0x0000000000101000, 0x0000101000000000,
+ 0x0000000000101000, 0x0000101020000000, 0x0000000408102040, 0x2010080400000000, 0x00000000007e0000, 0x7e00000000000000,
+ 0x0000004020100804, 0x0810204000000000, 0x00003c4242420408, 0x0800080800000000, 0x00007c829ea2a2a2, 0xa69a807e00000000,
+ 0x00003c424242427e, 0x4242424200000000, 0x00007c4242427c42, 0x4242427c00000000, 0x00003c4242404040, 0x4042423c00000000,
+ 0x0000784442424242, 0x4242447800000000, 0x00007e4040407840, 0x4040407e00000000, 0x00007e4040407840, 0x4040404000000000,
+ 0x00003c424240404e, 0x4242423c00000000, 0x0000424242427e42, 0x4242424200000000, 0x0000381010101010, 0x1010103800000000,
+ 0x00000e0404040404, 0x0444443800000000, 0x0000424448506060, 0x5048444200000000, 0x0000404040404040, 0x4040407e00000000,
+ 0x000082c6aa929282, 0x8282828200000000, 0x000042424262524a, 0x4642424200000000, 0x00003c4242424242, 0x4242423c00000000,
+ 0x00007c424242427c, 0x4040404000000000, 0x00003c4242424242, 0x42424a3c02000000, 0x00007c424242427c, 0x5048444200000000,
+ 0x00003c4240403c02, 0x0242423c00000000, 0x0000fe1010101010, 0x1010101000000000, 0x0000424242424242, 0x4242423c00000000,
+ 0x0000424242424224, 0x2424181800000000, 0x0000828282828292, 0x92aac68200000000, 0x0000424224241818, 0x2424424200000000,
+ 0x0000828244442810, 0x1010101000000000, 0x00007e0202040810, 0x2040407e00000000, 0x0000382020202020, 0x2020203800000000,
+ 0x0000404020201010, 0x0808040400000000, 0x0000380808080808, 0x0808083800000000, 0x0000102844000000, 0x0000000000000000,
+ 0x0000000000000000, 0x0000007e00000000, 0x1008000000000000, 0x0000000000000000, 0x00000000003c023e, 0x4242423e00000000,
+ 0x00004040407c4242, 0x4242427c00000000, 0x00000000003c4240, 0x4040423c00000000, 0x00000202023e4242, 0x4242423e00000000,
+ 0x00000000003c4242, 0x7e40403c00000000, 0x00000e10107c1010, 0x1010101000000000, 0x00000000003e4242, 0x4242423e02023c00,
+ 0x00004040407c4242, 0x4242424200000000, 0x0000101000301010, 0x1010103800000000, 0x00000404000c0404, 0x0404040444443800,
+ 0x0000404040424448, 0x7048444200000000, 0x0000301010101010, 0x1010103800000000, 0x0000000000fc9292, 0x9292929200000000,
+ 0x00000000007c4242, 0x4242424200000000, 0x00000000003c4242, 0x4242423c00000000, 0x00000000007c4242, 0x4242427c40404000,
+ 0x00000000003e4242, 0x4242423e02020200, 0x00000000005e6040, 0x4040404000000000, 0x00000000003e4040, 0x3c02027c00000000,
+ 0x00001010107c1010, 0x1010100e00000000, 0x0000000000424242, 0x4242423e00000000, 0x0000000000424242, 0x2424181800000000,
+ 0x0000000000828292, 0x9292927c00000000, 0x0000000000424224, 0x1824424200000000, 0x0000000000424242, 0x4242423e02023c00,
+ 0x00000000007e0408, 0x1020407e00000000, 0x00000c1010102010, 0x1010100c00000000, 0x0000101010101010, 0x1010101000000000,
+ 0x0000300808080408, 0x0808083000000000, 0x000000000062928c, 0x0000000000000000
+ };
+
+ const uint event_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
+
+ uint mask_window_flags [2] = { 0 };
+
+ (void) window_flags;
+
+ uint * dumb_buffer = allocate (256 * sizeof (* dumb_buffer));
+
+ for (uint index = 0; index < 256; ++index) {
+ dumb_buffer [index] = 0xffffffff;
+ }
+
+ ++common->font_count;
+
+ common->font_index = reallocate (common->font_index, common->font_count * sizeof (* common->font_index));
+ common->font_width = reallocate (common->font_width, common->font_count * sizeof (* common->font_width));
+ common->font_height = reallocate (common->font_height, common->font_count * sizeof (* common->font_height));
+ common->font_begin = reallocate (common->font_begin, common->font_count * sizeof (* common->font_begin));
+ common->font_end = reallocate (common->font_end, common->font_count * sizeof (* common->font_end));
+
+ common->font_begin [common->font_count - 1] = ' ';
+ common->font_end [common->font_count - 1] = '~';
+
+ common->font_index [common->font_count - 1] = allocate (95 * sizeof (* * common->font_index));
+ common->font_width [common->font_count - 1] = allocate (95 * sizeof (* * common->font_width));
+ common->font_height [common->font_count - 1] = allocate (95 * sizeof (* * common->font_height));
+
+ for (uint index = 0; index < 95; ++index) {
+ uint * buffer = allocate (common_font_width * common_font_height * sizeof (* buffer));
+
+ for (uint value = 0; value < 2; ++value) {
+ for (uint bit = 64; bit > 0; --bit) {
+ uint destination = ((value << 3) - ((bit - 1) >> 3) + 7) * common_font_width - ((bit - 1) & 7) + 7;
+ uint source = (font_bitmap [2 * index + value] >> (bit - 1)) & 1;
+
+ buffer [destination] = (source) ? 0xffffffff : 0x00000000;
+ }
+ }
+
+ common->font_index [common->font_count - 1] [index] = common_sprite_raw_import (common, buffer, common_font_width, common_font_height);
+ common->font_width [common->font_count - 1] [index] = common_font_width;
+ common->font_height [common->font_count - 1] [index] = common_font_height;
+ }
+
+ common_sprite_raw_import (common, dumb_buffer, 16, 16);
+
+ common->window_width = width;
+ common->window_height = height;
+
+ //~if (window_flags == ~ 0u) {
+ //~flags = common_window_decorated | common_window_resizable;
+ //~} else {
+ //~flags = window_flags;
+ //~}
+
+ common->connection = xcb_connect (null, null);
+
+ common->screen = xcb_setup_roots_iterator (xcb_get_setup (common->connection)).data;
+
+ common->window = xcb_generate_id (common->connection);
+ common->context = xcb_generate_id (common->connection);
+ common->pixmap = xcb_generate_id (common->connection);
+
+ mask_window_flags [0] = common->screen->black_pixel;
+ mask_window_flags [1] = XCB_EVENT_MASK_NO_EVENT |
+ XCB_EVENT_MASK_EXPOSURE |
+ XCB_EVENT_MASK_RESIZE_REDIRECT |
+ XCB_EVENT_MASK_KEY_RELEASE |
+ XCB_EVENT_MASK_KEY_PRESS |
+ XCB_EVENT_MASK_BUTTON_RELEASE |
+ XCB_EVENT_MASK_BUTTON_PRESS;
+
+ xcb_create_window (common->connection, common->screen->root_depth, common->window, common->screen->root, 0, 0, (ushort) width,
+ (ushort) height, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, common->screen->root_visual, event_mask, mask_window_flags);
+
+ xcb_map_window (common->connection, common->window);
+
+ //~xcb_composite_redirect_window (common->connection, common->window, XCB_COMPOSITE_REDIRECT_MANUAL);
+
+ xcb_change_property (common->connection, XCB_PROP_MODE_REPLACE, common->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
+ (uint) string_length (title), title);
+
+ xcb_create_pixmap (common->connection, common->screen->root_depth, common->pixmap, common->window, (ushort) width, (ushort ) height);
+
+ xcb_create_gc (common->connection, common->context, common->pixmap, 0, null);
+
+ xcb_flush (common->connection);
+
+ common->framebuffer = allocate (width * height * sizeof (* common->framebuffer));
+
+ common->active = true;
+
+ common->frame_begin = nano_time ();
+}
+
+static void common_synchronize (common_structure * common, uint colour) {
+ const uint signal_code [signal_count] = {
+ 0,
+ 38, 56, 54, 40, 26, 41, 42, 43, 31, 44, 45, 46, 58, 57, 32, 33,
+ 24, 27, 39, 28, 30, 55, 25, 53, 29, 52, 19, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 9, 23, 36, 36, 61, 51, 47, 49, 65, 22, 60, 59,
+ 48, 66, 20, 21, 34, 35, 37, 105, 50, 62, 64, 108, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 95, 96, 111, 116, 113, 114, 77, 127, 118, 110,
+ 112, 119, 115, 117, 86, 82, 63, 106, 104, 91, 90, 87, 88, 89, 83, 84,
+ 85, 79, 80, 81
+ };
+
+ xcb_generic_event_t * generic_event = xcb_wait_for_event (common->connection);
+ //~xcb_generic_event_t * generic_event = null;
+
+ (void) colour;
+
+ //~for (; ; ) {
+ //~generic_event = xcb_poll_for_event (common->connection);
+
+ //~if (generic_event != null) {
+ //~if ((generic_event->response_type & 127) != 14) break;
+ //~}
+ //~}
+
+ xcb_flush (common->connection);
+
+ print ("%i\n", generic_event->response_type & 127);
+//~XCB_NO_EXPOSURE = 14
+ //~if (generic_event != null) {
+ switch (generic_event->response_type & 127) {
+ //~case XCB_EXPOSE: {
+ //~xcb_flush (common->connection);
+ //~} break;
+ //~case XCB_MOTION_NOTIFY: {
+ //~;
+ //~} break;
+ case (XCB_BUTTON_PRESS): {
+ xcb_button_press_event_t * button_press = (xcb_button_press_event_t *) generic_event;
+ if (button_press->detail == 1) common->cursor [cursor_left] = true;
+ if (button_press->detail == 2) common->cursor [cursor_middle] = true;
+ if (button_press->detail == 3) common->cursor [cursor_right] = true;
+ common->cursor_x = button_press->event_x;
+ common->cursor_y = button_press->event_y;
+ } break;
+ case (XCB_BUTTON_RELEASE): {
+ xcb_button_release_event_t * button_release = (xcb_button_release_event_t *) generic_event;
+ if (button_release->detail == 1) common->cursor [cursor_left] = false;
+ if (button_release->detail == 2) common->cursor [cursor_middle] = false;
+ if (button_release->detail == 3) common->cursor [cursor_right] = false;
+ common->cursor_x = button_release->event_x;
+ common->cursor_y = button_release->event_y;
+ } break;
+ case (XCB_KEY_PRESS): {
+ xcb_key_press_event_t * key_press = (xcb_key_press_event_t *) generic_event;
+ for (uint index = 0; index < signal_count; ++index) {
+ if (key_press->detail == signal_code [index]) {
+ common->signal [index] = true;
+ }
+ }
+ } break;
+ case (XCB_KEY_RELEASE): {
+ xcb_key_release_event_t * key_release = (xcb_key_release_event_t *) generic_event;
+ for (uint index = 0; index < signal_count; ++index) {
+ if (key_release->detail == signal_code [index]) {
+ common->signal [index] = false;
+ }
+ }
+ } break;
+ default: {
+ } break;
+ }
+
+ generic_event = deallocate (generic_event);
+ //~}
+
+ for (uint pixel = 0; pixel < common->window_width * common->window_height; ++pixel) {
+ uint r = (common->framebuffer [pixel] & 0x00ff0000) >> 16;
+ uint b = (common->framebuffer [pixel] & 0x000000ff) << 16;
+
+ common->framebuffer [pixel] = (common->framebuffer [pixel] & 0xff00ff00) | b | r;
+ }
+
+ common->image = xcb_image_create_native (common->connection, (ushort) common->window_width, (ushort) common->window_height,
+ XCB_IMAGE_FORMAT_Z_PIXMAP, common->screen->root_depth, common->framebuffer,
+ (uint) (common->window_width * common->window_height * sizeof (* common->framebuffer)),
+ (uchar *) common->framebuffer);
+
+ xcb_image_put (common->connection, common->pixmap, common->context, common->image, 0, 0, 0);
+
+ xcb_image_destroy (common->image);
+
+ xcb_copy_area (common->connection, common->pixmap, common->window, common->context, 0, 0, 0, 0, (ushort) common->window_width,
+ (ushort) common->window_height);
+
+ common->framebuffer = allocate (common->window_width * common->window_height * sizeof (* common->framebuffer));
+
+ common->frame_end = nano_time ();
+
+ common->frame_time = common->frame_end - common->frame_begin;
+
+ if (common->frame_time < 1000000000ul / common_gameplay_framerate) {
+ nano_wait (1000000000ul / common_gameplay_framerate - common->frame_time);
+ }
+
+ if (common->global_tick % common_gameplay_framerate == 0) {
+ common->framerate = (uint) (1000000000ul / common->frame_time);
+ }
+
+ ++common->global_tick;
+
+ common->global_tick = common->global_tick % (common_gameplay_framerate * common_animation_framerate);
+ common->gameplay_tick = common->global_tick % (common_gameplay_framerate);
+ common->animation_tick = common->global_tick / (common_gameplay_framerate / common_animation_framerate);
+
+ common->frame_begin = nano_time ();
+}
+
+static void common_render_base (common_structure * common, uint sprite, int x, int y, uint u, uint v, uint width, uint height, float scale_x, float scale_y, int flip_x,
+ int flip_y, uint upper_left, uint upper_right, uint lower_left, uint lower_right) {
+ (void) scale_x;
+ (void) scale_y;
+ (void) flip_x;
+ (void) flip_y;
+ /// FIX TO INTERPOLATE ALL 4 COLOURS
+ //~(void) upper_left;
+ (void) upper_right;
+ (void) lower_left;
+ (void) lower_right;
+
+ /// COLOUR INTERPOLATION WITH RBGA-ABGR CONVERSION
+ uint interpolate_pixels (uint pixel, uint modifier) {
+ const uint r = (((pixel & 0xff000000) >> 24) * ((modifier & 0x000000ff) >> 0)) / 0xff;
+ const uint g = (((pixel & 0x00ff0000) >> 16) * ((modifier & 0x0000ff00) >> 8)) / 0xff;
+ const uint b = (((pixel & 0x0000ff00) >> 8) * ((modifier & 0x00ff0000) >> 16)) / 0xff;
+ const uint a = (((pixel & 0x000000ff) >> 0) * ((modifier & 0xff000000) >> 24)) / 0xff;
+
+ return ((r << 24) | (g << 16) | (b << 8) | a);
+ }
+
+ if ((x + (int) width < 0) || (y + (int) height < 0) || (x > (int) common->window_width) || (y > (int) common->window_height)) return;
+
+ for (uint vertical = 0; vertical < height; ++vertical) {
+ if (vertical + y >= common->window_height) break;
+ if (vertical + v >= common->sprite_height [sprite]) break;
+
+ for (uint horizontal = 0; horizontal < width; ++horizontal) {
+ if (horizontal + x >= common->window_width) break;
+ if (horizontal + u >= common->sprite_width [sprite]) break;
+
+ const uint pixel = common->sprite_data [sprite] [(vertical + v) * common->sprite_width [sprite] + horizontal + u];
+ const uint at = (y + vertical) * common->window_width + (x + horizontal);
+
+ common->framebuffer [at] = (((pixel & 0xff000000) >> 24) > 0x77) ? interpolate_pixels (pixel, upper_left) : common->framebuffer [at];
+ }
+ }
+}
+
+static void common_render_rectangle (common_structure * common, int x, int y, uint width, uint height, uint colour) {
+ common_render_base (common, common->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16, (float) height / 16, 0, 0, colour, colour,
+ colour, colour);
+}
+
+static void common_render_rectangle_gradient_v (common_structure * common, int x, int y, uint width, uint height, uint colour_up, uint colour_down) {
+ common_render_base (common, common->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16, (float) height / 16, 0, 0, colour_up, colour_up,
+ colour_down, colour_down);
+}
+
+static void common_render_rectangle_gradient_h (common_structure * common, int x, int y, uint width, uint height, uint colour_left, uint colour_right) {
+ common_render_base (common, common->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16, (float) height / 16, 0, 0, colour_left,
+ colour_right, colour_left, colour_right);
+}
+
+static void common_render_sprite (common_structure * common, uint sprite, int x, int y) {
+ common_render_base (common, sprite, x, y, 0, 0, common->sprite_width [sprite], common->sprite_height [sprite], 1, 1, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu,
+ 0xffffffffu);
+}
+
+static void common_render_sprite_crop (common_structure * common, uint sprite, int x, int y, uint u, uint v, uint width, uint height) {
+ common_render_base (common, sprite, x, y, u, v, width, height, 1, 1, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static void common_render_sprite_colour (common_structure * common, uint sprite, uint colour, int x, int y) {
+ common_render_base (common, sprite, x, y, 0, 0, common->sprite_width [sprite], common->sprite_height [sprite], 1, 1, 0, 0, colour, colour, colour, colour);
+}
+
+static void common_render_sprite_crop_colour (common_structure * common, uint sprite, uint colour, int x, int y, uint u, uint v, uint width, uint height) {
+ common_render_base (common, sprite, x, y, u, v, width, height, 1, 1, 0, 0, colour, colour, colour, colour);
+}
+
+static void common_render_sprite_flip (common_structure * common, uint sprite, int x, int y, int flip_x, int flip_y) {
+ common_render_base (common, sprite, x, y, 0, 0, common->sprite_width [sprite], common->sprite_height [sprite], 1, 1, flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static void common_render_sprite_animate (common_structure * common, uint sprite, int x, int y, uint frames, uint state, uint states) {
+ uint width = common->sprite_width [sprite] / states;
+ uint height = common->sprite_height [sprite] / frames;
+ uint u = width * (state % states);
+ uint v = height * (common->animation_tick % frames);
+
+ common_render_sprite_crop (common, sprite, x, y, u, v, width, height);
+}
+
+static void common_render_sprite_preview (common_structure * common, uint sprite, int x, int y, uint u, uint v, uint width, uint height, float zoom) {
+ common_render_base (common, sprite, x, y, u, v, width, height, zoom, zoom, false, false, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static void common_render_sprite_control (common_structure * common, uint sprite, int x, int y, uint u, uint v, uint width, uint height, int flip_x, int flip_y) {
+ common_render_base (common, sprite, x, y, u, v, width, height, 1, 1, flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static uint common_render_string_width (common_structure * common, const char * string, uint font, float scale) {
+ uint length = 0;
+
+ if (string == null) {
+ return (0);
+ }
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ uint character = common->font_index [font] [string [index] - common->font_begin [font]];
+
+ length += (uint) ((float) common->sprite_width [character] * scale);
+ }
+
+ return (length);
+}
+
+static void common_render_string (common_structure * common, const char * string, uint font, int x, int y, float scale, uint colour) {
+ int offset = x;
+
+ if (string == null) return;
+
+ if (font == 0xffffffffu) {
+ font = common->font_count - 1;
+ }
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ uint character = 0;
+
+ if (string [index] == '\t') {
+ x += (int) (scale * (float) common_font_tabulator * (float) common->sprite_width [common->font_index [font] [' ' - common->font_begin [font]]]);
+ continue;
+ } else if (string [index] == '\n') {
+ x = offset;
+ y += (int) (scale * (float) common->sprite_height [common->font_index [font] [' ' - common->font_begin [font]]]);
+ continue;
+ } else if ((string [index] >= common->font_begin [font]) && (string [index] <= common->font_end [font])) {
+ character = common->font_index [font] [string [index] - common->font_begin [font]];
+ } else {
+ continue;
+ }
+
+ common_render_base (common, character, x, y, 0, 0, common->sprite_width [character], common->sprite_height [character],
+ scale, scale, 0, 0, colour, colour, colour, colour);
+
+ x += (int) (scale * (float) common->sprite_width [character]);
+ }
+}
--- /dev/null
+#include <xolatile/xtandard.h>
+
+static void echo_byte (uchar byte) {
+ output ("0123456789ABCDEF" + byte / 16, 1);
+ output ("0123456789ABCDEF" + byte % 16, 1);
+
+ output (" ", 1);
+}
+
+int main (int argc, char * * argv) {
+ int file = 0;
+ ulong size = 0;
+ uchar * buffer = null;
+
+ if (argc != 2) {
+ print ("> xop input_file\n");
+
+ return (log_failure);
+ }
+
+ file = file_open (argv [1], file_flag_read);
+ size = file_size (argv [1]);
+
+ buffer = allocate (size * sizeof (* buffer));
+
+ file_read (file, buffer, size);
+
+ file = file_close (file);
+
+ for (ulong offset = 0; offset < size; ++offset) {
+ if (buffer [offset] == 0x90) {
+ echo ("\n");
+ }
+
+ echo_byte (buffer [offset]);
+ }
+
+ echo ("\n");
+
+ buffer = deallocate (buffer);
+
+ return (log_success);
+}
--- /dev/null
+/// _
+/// __ _____ _ __ _ __ ___ __ _| |_
+/// \ \/ / _ \| '__| '_ ` _ \ / _` | __|
+/// > < (_) | | | | | | | | (_| | |_
+/// /_/\_\___/|_| |_| |_| |_|\__,_|\__|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xormat - Very simple file format wrapper for things I hate but have to use anyway...
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#ifdef use_png_library
+#include <xolatile/xormat/png.h>
+#endif
+
+#ifdef use_jxl_library
+#include <xolatile/xormat/jxl.h>
+#endif
+
+#ifdef use_jpg_library
+#include <xolatile/xormat/jpg.h>
+#endif
+
+#ifdef use_tga_library
+#include <xolatile/xormat/tga.h>
+#endif
+
+static void * format_image_import (const char * path, uint * width, uint * height) {
+ uint * data = null;
+
+#ifdef use_png_library
+ if (data == null) {
+ char buffer [256] = "";
+
+ if (file_exists (string_concatenate (string_copy (buffer, path), ".png")) == true) {
+ data = png_image_import (buffer, width, height);
+ }
+ }
+#endif
+
+#ifdef use_jxl_library
+ if (data == null) {
+ char buffer [256] = "";
+
+ if (file_exists (string_concatenate (string_copy (buffer, path), ".jxl")) == true) {
+ data = jxl_image_import (buffer, width, height);
+ }
+ }
+#endif
+
+#ifdef use_jpg_library
+ if (data == null) {
+ char buffer [256] = "";
+
+ if (file_exists (string_concatenate (string_copy (buffer, path), ".jpg")) == true) {
+ data = jpg_image_import (buffer, width, height);
+ }
+ }
+#endif
+
+#ifdef use_tga_library
+ if (data == null) {
+ char buffer [256] = "";
+
+ if (file_exists (string_concatenate (string_copy (buffer, path), ".tga")) == true) {
+ data = tga_image_import (buffer, width, height);
+ }
+ }
+#endif
+
+ if (data == null) {
+ switch (file_type (path)) {
+#ifdef use_png_library
+ case (file_type_png_image): {
+ if (file_exists (path) == true) {
+ data = png_image_import (path, width, height);
+ } else {
+ print ("/w File '/3%s/-' doesn't exist.\n", path);
+ }
+ } break;
+#endif
+#ifdef use_jxl_library
+ case (file_type_jxl_image): {
+ if (file_exists (path) == true) {
+ data = jxl_image_import (path, width, height);
+ } else {
+ print ("/w File '/3%s/-' doesn't exist.\n", path);
+ }
+ } break;
+#endif
+#ifdef use_jpg_library
+ case (file_type_jpg_image): {
+ if (file_exists (path) == true) {
+ data = jpg_image_import (path, width, height);
+ } else {
+ print ("/w File '/3%s/-' doesn't exist.\n", path);
+ }
+ } break;
+#endif
+#ifdef use_tga_library
+ case (file_type_tga_image): {
+ if (file_exists (path) == true) {
+ data = tga_image_import (path, width, height);
+ } else {
+ print ("/w File '/3%s/-' doesn't exist.\n", path);
+ }
+ } break;
+#endif
+ default: {
+ print ("/w File '/3%s/-' doesn't exist or file type isn't supported.\n", path);
+ } break;
+ }
+ }
+
+ return (data);
+}
--- /dev/null
+#include <jxl/decode.h>
+
+#ifndef use_jxl_library
+#define use_jxl_library
+#endif
+
+static void * jxl_image_import (const char * path, uint * width, uint * height) {
+ JxlDecoder * decoder = null;
+ JxlBasicInfo information = { 0 };
+ JxlPixelFormat format = { 4, JXL_TYPE_UINT8, JXL_NATIVE_ENDIAN, 0 };
+ JxlDecoderStatus status = JXL_DEC_ERROR;
+
+ fatal_failure (path == null, "jxl_image_import: File path is null pointer.");
+ fatal_failure (width == null, "jxl_image_import: Width is null pointer.");
+ fatal_failure (height == null, "jxl_image_import: Height is null pointer.");
+
+ ulong size = file_size (path);
+ uchar * data = file_record (path);
+ uint * pixel_array = null;
+ ulong output_size = 0;
+
+ decoder = JxlDecoderCreate (null);
+
+ fatal_failure (decoder == null, "jxl_image_import: Failed to create a decoder.");
+
+ status = JxlDecoderSubscribeEvents (decoder, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
+
+ fatal_failure (status != JXL_DEC_SUCCESS, "jxl_image_import: Failed to subscribe decoder basic information and full image events.");
+
+ status = JxlDecoderSetInput (decoder, data, size);
+
+ fatal_failure (status != JXL_DEC_SUCCESS, "jxl_image_import: Failed to set decoder input data and size.");
+
+ for (status = JxlDecoderProcessInput (decoder); true; status = JxlDecoderProcessInput (decoder)) {
+ fatal_failure (status == JXL_DEC_ERROR, "jxl_image_import: Decoder internal error.");
+ fatal_failure (status == JXL_DEC_NEED_MORE_INPUT, "jxl_image_import: Decoder needs more input data.");
+
+ if (status == JXL_DEC_BASIC_INFO) {
+ status = JxlDecoderGetBasicInfo(decoder, &information);
+ fatal_failure (status != JXL_DEC_SUCCESS, "jxl_image_import: Failed to get basic image information.");
+ continue;
+ }
+
+ if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
+ status = JxlDecoderImageOutBufferSize(decoder, & format, & output_size);
+ fatal_failure (status != JXL_DEC_SUCCESS, "jxl_image_import: Failed to get image output buffer size.");
+ if (pixel_array != null) {
+ pixel_array = deallocate (pixel_array);
+ }
+ pixel_array = allocate (output_size);
+ status = JxlDecoderSetImageOutBuffer(decoder, & format, pixel_array, output_size);
+ fatal_failure (status != JXL_DEC_SUCCESS, "jxl_image_import: Failed to set image output buffer data.");
+ continue;
+ }
+
+ if (status == JXL_DEC_FULL_IMAGE) continue;
+ if (status == JXL_DEC_SUCCESS) break;
+ }
+
+ * width = information.xsize;
+ * height = information.ysize;
+
+ JxlDecoderDestroy (decoder);
+
+ data = deallocate (data);
+
+ return (pixel_array);
+}
--- /dev/null
+#include <stdio.h>
+#include <png.h>
+
+#ifndef use_png_library
+#define use_png_library
+#endif
+
+static void * png_image_import (const char * path, uint * width, uint * height) {
+ FILE * file;
+ uint * data;
+ uint index;
+
+ png_byte colour_type = 0;
+ png_byte bit_depth = 0;
+ png_bytep * row_pointers = null;
+
+ png_structp structure = null;
+ png_infop information = null;
+
+ fatal_failure (path == null, "png_image_import: File path is null pointer.");
+ fatal_failure (width == null, "png_image_import: Width is null pointer.");
+ fatal_failure (height == null, "png_image_import: Height is null pointer.");
+
+ file = fopen (path, "rb");
+
+ fatal_failure (file == null, path);
+
+ structure = png_create_read_struct (PNG_LIBPNG_VER_STRING, null, null, null);
+ information = png_create_info_struct (structure);
+
+ png_init_io (structure, file);
+ png_read_info (structure, information);
+
+ * width = png_get_image_width (structure, information);
+ * height = png_get_image_height (structure, information);
+ colour_type = png_get_color_type (structure, information);
+ bit_depth = png_get_bit_depth (structure, information);
+
+ if (bit_depth == 16) {
+ png_set_strip_16 (structure);
+ }
+
+ if (colour_type == PNG_COLOR_TYPE_PALETTE) {
+ png_set_palette_to_rgb (structure);
+ }
+
+ if ((colour_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) {
+ png_set_expand_gray_1_2_4_to_8 (structure);
+ }
+
+ if (png_get_valid (structure, information, PNG_INFO_tRNS)) {
+ png_set_tRNS_to_alpha (structure);
+ }
+
+ if ((colour_type == PNG_COLOR_TYPE_RGB) || (colour_type == PNG_COLOR_TYPE_GRAY) || (colour_type == PNG_COLOR_TYPE_PALETTE)) {
+ png_set_filler (structure, 0xff, PNG_FILLER_AFTER);
+ }
+
+ if ((colour_type == PNG_COLOR_TYPE_GRAY) || (colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)) {
+ png_set_gray_to_rgb (structure);
+ }
+
+ png_read_update_info (structure, information);
+
+ row_pointers = allocate ((* height) * sizeof (* row_pointers));
+
+ for (index = 0; index < (* height); ++index) {
+ row_pointers [index] = allocate (png_get_rowbytes (structure, information));
+ }
+
+ png_read_image (structure, row_pointers);
+
+ fclose (file);
+
+ data = allocate ((* width) * (* height) * sizeof (* data));
+
+ for (index = 0; index < (* height); ++index) {
+ memory_copy (& data [index * (* width)], row_pointers [index], (* width) * sizeof (* data));
+
+ row_pointers [index] = deallocate (row_pointers [index]);
+ }
+
+ row_pointers = deallocate (row_pointers);
+
+ png_destroy_read_struct (& structure, & information, null);
+
+ return (data);
+}
+
+static void png_image_export (const char * path, uint * data, uint width, uint height) {
+ png_image image = { 0 };
+
+ fatal_failure (path == null, "png_image_export: File path is null pointer.");
+ fatal_failure (data == null, "png_image_export: Data is null pointer.");
+ fatal_failure (width == 0, "png_image_export: Width is equal to zero.");
+ fatal_failure (height == 0, "png_image_export: Height is equal to zero.");
+
+ image.version = PNG_IMAGE_VERSION;
+ image.format = PNG_FORMAT_RGBA;
+ image.width = width;
+ image.height = height;
+
+ png_image_write_to_file (& image, path, 0, data, 0, null);
+
+ png_image_free (& image);
+}
--- /dev/null
+/// _
+/// __ ___ __ ___ _ __ __ _| |
+/// \ \/ / '_ \ / _ \ '_ \ / _` | |
+/// > <| |_) | __/ | | | (_| | |
+/// /_/\_\ .__/ \___|_| |_|\__,_|_|
+/// |_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xpenal - Tiny and elegant OpenAL wrapper library so I don't go insane because of multithreading.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+PASTE THE SEMI-FINISHED CODE LATER...
--- /dev/null
+/// _
+/// __ ___ __ ___ _ __ __ _| |
+/// \ \/ / '_ \ / _ \ '_ \ / _` | |
+/// > <| |_) | __/ | | | (_| | |
+/// /_/\_\ .__/ \___|_| |_|\__, |_|
+/// |_| |___/
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xpengl - Tiny and elegant OpenGL + GLFW wrapper library so I don't go insane because of Khronos.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#include <GLFW/glfw3.h>
+
+#define opengl_font_width (8)
+#define opengl_font_height (16)
+
+//~typedef enum {
+ //~opengl_window_fullscreen = 0x1,
+ //~opengl_window_transparent = 0x2,
+ //~opengl_window_resizable = 0x4,
+ //~opengl_window_decorated = 0x8
+//~} opengl_window_flag;
+
+typedef struct {
+ GLFWwindow * window;
+
+ PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
+ PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
+ PFNGLGENBUFFERSPROC glGenBuffers;
+ PFNGLBINDBUFFERPROC glBindBuffer;
+ PFNGLCREATESHADERPROC glCreateShader;
+ PFNGLSHADERSOURCEPROC glShaderSource;
+ PFNGLCOMPILESHADERPROC glCompileShader;
+ PFNGLCREATEPROGRAMPROC glCreateProgram;
+ PFNGLATTACHSHADERPROC glAttachShader;
+ PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation;
+ PFNGLLINKPROGRAMPROC glLinkProgram;
+ PFNGLUSEPROGRAMPROC glUseProgram;
+ PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
+ PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
+ PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
+ PFNGLUNIFORM1IPROC glUniform1i;
+ PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
+ PFNGLDELETEBUFFERSPROC glDeleteBuffers;
+ PFNGLDELETESHADERPROC glDeleteShader;
+ PFNGLDELETEPROGRAMPROC glDeleteProgram;
+ PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
+ PFNGLBUFFERDATAPROC glBufferData;
+
+ bool signal [signal_count];
+ bool cursor [cursor_count];
+ int cursor_x;
+ int cursor_y;
+
+ bool using_precomputed_spritesheet;
+ ulong spritesheet_size;
+ ulong vertex_limit;
+ ulong index_limit;
+ uint gameplay_framerate;
+ uint animation_framerate;
+ uint tab_width;
+ uint default_font;
+ bool active;
+ uint window_width;
+ uint window_height;
+ float pixel_width;
+ float pixel_height;
+ uint framerate;
+ ulong frame_time;
+ ulong frame_begin;
+ ulong frame_end;
+ uint global_tick;
+ uint gameplay_tick;
+ uint animation_tick;
+ bool freeze_cursor;
+ bool freeze_signal;
+ uint vertex_object;
+ uint vertex_buffer;
+ uint index_buffer;
+ uint vertex_shader;
+ uint fragment_shader;
+ uint shader_program;
+ uint spritesheet;
+ uint vertex_count;
+ uint index_count;
+ float * vertex_array;
+ uint * index_array;
+ uint sprite_count;
+ uint font_count;
+ uint * spritesheet_data;
+ uint * * sprite_data;
+ uint * sprite_width;
+ uint * sprite_height;
+ float * sprite_u;
+ float * sprite_v;
+ uint * * font_index;
+ uint * * font_width;
+ uint * * font_height;
+ char * font_begin;
+ char * font_end;
+} opengl_structure;
+
+static uint opengl_sprite_raw_import (opengl_structure * opengl, uint * data, uint width, uint height) {
+ fatal_failure (opengl->active == true, "opengl_sprite_raw_import: OpenGL renderer is already initialized.");
+ fatal_failure (data == null, "opengl_sprite_raw_import: Data is null pointer.");
+ fatal_failure (width == 0, "opengl_sprite_raw_import: Font image width is zero.");
+ fatal_failure (height == 0, "opengl_sprite_raw_import: Font image height is zero.");
+
+ ++opengl->sprite_count;
+
+ opengl->sprite_data = reallocate (opengl->sprite_data, opengl->sprite_count * sizeof (* opengl->sprite_data));
+ opengl->sprite_width = reallocate (opengl->sprite_width, opengl->sprite_count * sizeof (* opengl->sprite_width));
+ opengl->sprite_height = reallocate (opengl->sprite_height, opengl->sprite_count * sizeof (* opengl->sprite_height));
+ opengl->sprite_u = reallocate (opengl->sprite_u, opengl->sprite_count * sizeof (* opengl->sprite_u));
+ opengl->sprite_v = reallocate (opengl->sprite_v, opengl->sprite_count * sizeof (* opengl->sprite_v));
+
+ opengl->sprite_data [opengl->sprite_count - 1] = data;
+ opengl->sprite_width [opengl->sprite_count - 1] = width;
+ opengl->sprite_height [opengl->sprite_count - 1] = height;
+ opengl->sprite_u [opengl->sprite_count - 1] = 0;
+ opengl->sprite_v [opengl->sprite_count - 1] = 0;
+
+ return (opengl->sprite_count - 1);
+}
+
+static uint opengl_font_raw_import (opengl_structure * opengl, uint * data, uint image_width, char begin, char end, uint empty) {
+ uint pointer = 0;
+ uint width = 0;
+ uint height = 0;
+
+ fatal_failure (opengl->active == true, "opengl_font_raw_import: OpenGL renderer is already initialized.");
+ fatal_failure (data == null, "opengl_font_raw_import: Data is null pointer.");
+ fatal_failure (image_width == 0, "opengl_font_raw_import: Font image width is zero.");
+ fatal_failure (begin >= end, "opengl_font_raw_import: Font character range is inverted.");
+
+ ++opengl->font_count;
+
+ opengl->font_index = reallocate (opengl->font_index, opengl->font_count * sizeof (* opengl->font_index));
+ opengl->font_width = reallocate (opengl->font_width, opengl->font_count * sizeof (* opengl->font_width));
+ opengl->font_height = reallocate (opengl->font_height, opengl->font_count * sizeof (* opengl->font_height));
+ opengl->font_begin = reallocate (opengl->font_begin, opengl->font_count * sizeof (* opengl->font_begin));
+ opengl->font_end = reallocate (opengl->font_end, opengl->font_count * sizeof (* opengl->font_end));
+
+ opengl->font_begin [opengl->font_count - 1] = begin;
+ opengl->font_end [opengl->font_count - 1] = end;
+
+ opengl->font_index [opengl->font_count - 1] = allocate ((ulong) (end - begin + 1) * sizeof (* * opengl->font_index));
+ opengl->font_width [opengl->font_count - 1] = allocate ((ulong) (end - begin + 1) * sizeof (* * opengl->font_width));
+ opengl->font_height [opengl->font_count - 1] = allocate ((ulong) (end - begin + 1) * sizeof (* * opengl->font_height));
+
+ for (char index = begin; index <= end; ++index) {
+ for ( ; data [pointer] == empty; ++pointer);
+ for (width = 0; data [pointer + width] != empty; ++width);
+ for (height = 0; data [pointer + height * image_width] != empty; ++height);
+
+ uint * buffer = allocate (width * height * sizeof (* buffer));
+
+ for (uint y = 0; y < height; ++y) {
+ for (uint x = 0; x < width; ++x) {
+ buffer [y * width + x] = data [pointer + (y * image_width) + x];
+ }
+ }
+
+ opengl->font_index [opengl->font_count - 1] [index - begin] = opengl_sprite_raw_import (opengl, buffer, width, height);
+ opengl->font_width [opengl->font_count - 1] [index - begin] = width;
+ opengl->font_height [opengl->font_count - 1] [index - begin] = height;
+
+ pointer += width;
+
+ for (; data [pointer] == empty; ++pointer);
+
+ if (pointer % image_width == 2) {
+ pointer += height * image_width;
+ }
+ }
+
+ return (opengl->font_count - 1);
+}
+
+static uint opengl_sprite_import (opengl_structure * opengl, const char * path) {
+ uint width = 0;
+ uint height = 0;
+ uint * data = null;
+
+ char buffer [256] = "";
+
+ if (opengl->using_precomputed_spritesheet == true) {
+ return (++opengl->sprite_count - 1);
+ }
+
+#ifdef use_png_library
+ if (file_exists (string_concatenate (string_copy (buffer, path), ".png")) == true) {
+ data = png_image_import (buffer, & width, & height);
+ } else {
+ print ("/w File '/3%s/-' doesn't exist.\n", buffer);
+ }
+#endif
+
+#ifdef use_jxl_library
+ if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".jxl")) == true)) {
+ data = jxl_image_import (buffer, & width, & height);
+ }
+#endif
+
+ fatal_failure (data == null, "opengl_sprite_import: Unsupported image format.");
+
+ return (opengl_sprite_raw_import (opengl, data, width, height));
+}
+
+static uint opengl_font_import (opengl_structure * opengl, const char * path, char begin, char end, uint colour) {
+ uint width = 0;
+ uint height = 0;
+ uint result = 0;
+ uint * data = null;
+
+ char buffer [256] = "";
+
+ if (opengl->using_precomputed_spritesheet == true) {
+ for (char index = begin; index <= end; ++index) {
+ opengl->font_index [opengl->font_count] [index - begin] = ++opengl->sprite_count - 1;
+ }
+
+ return (++opengl->font_count - 1);
+ }
+
+#ifdef use_png_library
+ if (file_exists (string_concatenate (string_copy (buffer, path), ".png")) == true) {
+ data = png_image_import (buffer, & width, & height);
+ } else {
+ print ("/w File '/3%s/-' doesn't exist.\n", buffer);
+ }
+#endif
+
+#ifdef use_jxl_library
+ if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".jxl")) == true)) {
+ data = jxl_image_import (buffer, & width, & height);
+ }
+#endif
+
+ fatal_failure (data == null, "opengl_font_import: Unsupported image format.");
+
+ result = opengl_font_raw_import (opengl, data, width, begin, end, colour);
+
+ data = deallocate (data);
+
+ return (result);
+}
+
+static uint opengl_sprite_width (opengl_structure * opengl, uint sprite) {
+ return (opengl->sprite_width [sprite]);
+}
+
+static uint opengl_sprite_height (opengl_structure * opengl, uint sprite) {
+ return (opengl->sprite_height [sprite]);
+}
+
+static uint opengl_center_x (opengl_structure * opengl, uint size) {
+ return ((opengl->window_width - size) / 2);
+}
+
+static uint opengl_center_y (opengl_structure * opengl, uint size) {
+ return ((opengl->window_height - size) / 2);
+}
+
+static bool opengl_cursor_inside (opengl_structure * opengl, int x, int y, uint width, uint height) {
+ return ((opengl->cursor_x > x) &&
+ (opengl->cursor_y > y) &&
+ (opengl->cursor_x < x + (int) width) &&
+ (opengl->cursor_y < y + (int) height));
+}
+
+static bool opengl_cursor_left_click (opengl_structure * opengl, int x, int y, uint width, uint height) {
+ if (opengl->cursor [cursor_left] == true) {
+ opengl->freeze_cursor = true;
+
+ return (opengl_cursor_inside (opengl, x, y, width, height) == true);
+ }
+
+ return (false);
+}
+
+static bool opengl_cursor_right_click (opengl_structure * opengl, int x, int y, uint width, uint height) {
+ if (opengl->cursor [cursor_right]) {
+ opengl->freeze_cursor = true;
+
+ return (opengl_cursor_inside (opengl, x, y, width, height));
+ }
+
+ return (false);
+}
+
+static void opengl_import_spritesheet (opengl_structure * opengl, const char * data_file) {
+ int file = file_open (data_file, file_flag_read);
+
+ fatal_failure (opengl->active == true, "opengl_import_spritesheet: OpenGL renderer is already initialized.");
+
+ file_read (file, & opengl->spritesheet_size, sizeof (opengl->spritesheet_size));
+
+ file_read (file, & opengl->sprite_count, sizeof (opengl->sprite_count));
+
+ opengl->sprite_width = allocate (opengl->sprite_count * sizeof (* opengl->sprite_width));
+ opengl->sprite_height = allocate (opengl->sprite_count * sizeof (* opengl->sprite_height));
+ opengl->sprite_u = allocate (opengl->sprite_count * sizeof (* opengl->sprite_u));
+ opengl->sprite_v = allocate (opengl->sprite_count * sizeof (* opengl->sprite_v));
+
+ file_read (file, opengl->sprite_width, opengl->sprite_count * sizeof (* opengl->sprite_width));
+ file_read (file, opengl->sprite_height, opengl->sprite_count * sizeof (* opengl->sprite_height));
+ file_read (file, opengl->sprite_u, opengl->sprite_count * sizeof (* opengl->sprite_u));
+ file_read (file, opengl->sprite_v, opengl->sprite_count * sizeof (* opengl->sprite_v));
+
+ file_read (file, & opengl->font_count, sizeof (opengl->font_count));
+
+ opengl->font_index = allocate (opengl->font_count * sizeof (* opengl->font_index));
+ opengl->font_width = allocate (opengl->font_count * sizeof (* opengl->font_width));
+ opengl->font_height = allocate (opengl->font_count * sizeof (* opengl->font_height));
+ opengl->font_begin = allocate (opengl->font_count * sizeof (* opengl->font_begin));
+ opengl->font_end = allocate (opengl->font_count * sizeof (* opengl->font_end));
+
+ file_read (file, opengl->font_begin, opengl->font_count * sizeof (* opengl->font_begin));
+ file_read (file, opengl->font_end, opengl->font_count * sizeof (* opengl->font_end));
+
+ for (uint index = 0; index < opengl->font_count; ++index) {
+ uint range = (uint) (opengl->font_end [index] - opengl->font_begin [index]) + 1;
+
+ opengl->font_index [index] = allocate (range * sizeof (* * opengl->font_index));
+ opengl->font_width [index] = allocate (range * sizeof (* * opengl->font_width));
+ opengl->font_height [index] = allocate (range * sizeof (* * opengl->font_height));
+
+ for (uint subindex = 0; subindex < range; ++subindex) {
+ file_read (file, & opengl->font_index [index] [subindex], sizeof (* * opengl->font_index));
+ file_read (file, & opengl->font_width [index] [subindex], sizeof (* * opengl->font_width));
+ file_read (file, & opengl->font_height [index] [subindex], sizeof (* * opengl->font_height));
+ }
+ }
+
+ file = file_close (file);
+
+ opengl->sprite_count = 0;
+ opengl->font_count = 0;
+}
+
+static void opengl_export_spritesheet (opengl_structure * opengl, const char * data_file) {
+ int file = file_open (data_file, file_flag_write | file_flag_create | file_flag_truncate);
+
+ fatal_failure (opengl->spritesheet_data == null, "opengl_export_spritesheet: OpenGL renderer can't access spritesheet data.");
+
+ file_write (file, & opengl->spritesheet_size, sizeof (opengl->spritesheet_size));
+
+ file_write (file, & opengl->sprite_count, sizeof (opengl->sprite_count));
+
+ file_write (file, opengl->sprite_width, opengl->sprite_count * sizeof (* opengl->sprite_width));
+ file_write (file, opengl->sprite_height, opengl->sprite_count * sizeof (* opengl->sprite_height));
+ file_write (file, opengl->sprite_u, opengl->sprite_count * sizeof (* opengl->sprite_u));
+ file_write (file, opengl->sprite_v, opengl->sprite_count * sizeof (* opengl->sprite_v));
+
+ file_write (file, & opengl->font_count, sizeof (opengl->font_count));
+
+ file_write (file, opengl->font_begin, opengl->font_count * sizeof (* opengl->font_begin));
+ file_write (file, opengl->font_end, opengl->font_count * sizeof (* opengl->font_end));
+
+ for (uint index = 0; index < opengl->font_count; ++index) {
+ for (uint subindex = 0; subindex < (uint) (opengl->font_end [index] - opengl->font_begin [index]) + 1; ++subindex) {
+ file_write (file, & opengl->font_index [index] [subindex], sizeof (* * opengl->font_index));
+ file_write (file, & opengl->font_width [index] [subindex], sizeof (* * opengl->font_width));
+ file_write (file, & opengl->font_height [index] [subindex], sizeof (* * opengl->font_height));
+ }
+ }
+
+ file = file_close (file);
+
+ print ("/c Exported internal binary data of OpenGL spritesheet.");
+}
+
+static opengl_structure * opengl_initialize (uint gameplay_framerate, uint animation_framerate, bool use_precomputed_spritesheet,
+ uint maximum_quads_on_screen, uint spritesheet_side) {
+ opengl_structure * opengl = allocate (sizeof (* opengl));
+
+ opengl->using_precomputed_spritesheet = use_precomputed_spritesheet;
+
+ opengl->spritesheet_size = spritesheet_side;
+ opengl->gameplay_framerate = gameplay_framerate;
+ opengl->animation_framerate = animation_framerate;
+ opengl->vertex_limit = maximum_quads_on_screen * 32;
+ opengl->index_limit = maximum_quads_on_screen * 6;
+ opengl->tab_width = 4;
+ opengl->default_font = ~0u;
+
+ if (use_precomputed_spritesheet == true) {
+ print ("[/0Comment/-] Importing spritesheet image and information...\n");
+
+ opengl_import_spritesheet (opengl, "binary/spritesheet.bin");
+ }
+
+ print ("[/2Success/-] Initialized OpenGL renderer.\n");
+
+ return (opengl);
+}
+
+static opengl_structure * opengl_deinitialize (opengl_structure * opengl) {
+ opengl->active = false;
+
+ for (uint index = 0; index < opengl->font_count; ++index) {
+ opengl->font_index [index] = deallocate (opengl->font_index [index]);
+ opengl->font_width [index] = deallocate (opengl->font_width [index]);
+ opengl->font_height [index] = deallocate (opengl->font_height [index]);
+ }
+
+ opengl->font_index = deallocate (opengl->font_index);
+ opengl->font_width = deallocate (opengl->font_width);
+ opengl->font_height = deallocate (opengl->font_height);
+ opengl->font_begin = deallocate (opengl->font_begin);
+ opengl->font_end = deallocate (opengl->font_end);
+
+ opengl->sprite_width = deallocate (opengl->sprite_width);
+ opengl->sprite_height = deallocate (opengl->sprite_height);
+ opengl->sprite_u = deallocate (opengl->sprite_u);
+ opengl->sprite_v = deallocate (opengl->sprite_v);
+
+ if (opengl->using_precomputed_spritesheet == false) {
+ opengl->spritesheet_data = deallocate (opengl->spritesheet_data);
+ }
+
+ opengl->vertex_array = deallocate (opengl->vertex_array);
+ opengl->index_array = deallocate (opengl->index_array);
+
+ glDeleteTextures (1, & opengl->spritesheet);
+
+ opengl->glDeleteProgram (opengl->shader_program);
+ opengl->glDeleteShader (opengl->fragment_shader);
+ opengl->glDeleteShader (opengl->vertex_shader);
+
+ opengl->glDeleteBuffers (1, & opengl->index_buffer);
+ opengl->glDeleteBuffers (1, & opengl->vertex_buffer);
+ opengl->glDeleteVertexArrays (1, & opengl->vertex_object);
+
+ glfwDestroyWindow (opengl->window);
+
+ glfwTerminate ();
+
+ print ("[/2Success/-] Deinitialized OpenGL renderer.\n");
+
+ return (deallocate (opengl));
+}
+
+static void opengl_configure (opengl_structure * opengl, uint window_width, uint window_height, const char * window_title) {
+ const ulong font_bitmap [190] = {
+ 0x0000000000000000, 0x0000000000000000, 0x0000101010101010, 0x1000101000000000, 0x0024242400000000, 0x0000000000000000,
+ 0x00002424247e2424, 0x7e24242400000000, 0x0010107c9290907c, 0x1212927c10100000, 0x0000649468081010, 0x202c524c00000000,
+ 0x000018242418304a, 0x4444443a00000000, 0x0010101000000000, 0x0000000000000000, 0x0000081020202020, 0x2020100800000000,
+ 0x0000201008080808, 0x0808102000000000, 0x000000000024187e, 0x1824000000000000, 0x000000000010107c, 0x1010000000000000,
+ 0x0000000000000000, 0x0000101020000000, 0x000000000000007e, 0x0000000000000000, 0x0000000000000000, 0x0000101000000000,
+ 0x0000040408081010, 0x2020404000000000, 0x00003c4242464a52, 0x6242423c00000000, 0x0000081828080808, 0x0808083e00000000,
+ 0x00003c4242020408, 0x1020407e00000000, 0x00003c4242021c02, 0x0242423c00000000, 0x000002060a122242, 0x7e02020200000000,
+ 0x00007e4040407c02, 0x0202423c00000000, 0x00001c2040407c42, 0x4242423c00000000, 0x00007e0202040408, 0x0810101000000000,
+ 0x00003c4242423c42, 0x4242423c00000000, 0x00003c424242423e, 0x0202043800000000, 0x0000000000101000, 0x0000101000000000,
+ 0x0000000000101000, 0x0000101020000000, 0x0000000408102040, 0x2010080400000000, 0x00000000007e0000, 0x7e00000000000000,
+ 0x0000004020100804, 0x0810204000000000, 0x00003c4242420408, 0x0800080800000000, 0x00007c829ea2a2a2, 0xa69a807e00000000,
+ 0x00003c424242427e, 0x4242424200000000, 0x00007c4242427c42, 0x4242427c00000000, 0x00003c4242404040, 0x4042423c00000000,
+ 0x0000784442424242, 0x4242447800000000, 0x00007e4040407840, 0x4040407e00000000, 0x00007e4040407840, 0x4040404000000000,
+ 0x00003c424240404e, 0x4242423c00000000, 0x0000424242427e42, 0x4242424200000000, 0x0000381010101010, 0x1010103800000000,
+ 0x00000e0404040404, 0x0444443800000000, 0x0000424448506060, 0x5048444200000000, 0x0000404040404040, 0x4040407e00000000,
+ 0x000082c6aa929282, 0x8282828200000000, 0x000042424262524a, 0x4642424200000000, 0x00003c4242424242, 0x4242423c00000000,
+ 0x00007c424242427c, 0x4040404000000000, 0x00003c4242424242, 0x42424a3c02000000, 0x00007c424242427c, 0x5048444200000000,
+ 0x00003c4240403c02, 0x0242423c00000000, 0x0000fe1010101010, 0x1010101000000000, 0x0000424242424242, 0x4242423c00000000,
+ 0x0000424242424224, 0x2424181800000000, 0x0000828282828292, 0x92aac68200000000, 0x0000424224241818, 0x2424424200000000,
+ 0x0000828244442810, 0x1010101000000000, 0x00007e0202040810, 0x2040407e00000000, 0x0000382020202020, 0x2020203800000000,
+ 0x0000404020201010, 0x0808040400000000, 0x0000380808080808, 0x0808083800000000, 0x0000102844000000, 0x0000000000000000,
+ 0x0000000000000000, 0x0000007e00000000, 0x1008000000000000, 0x0000000000000000, 0x00000000003c023e, 0x4242423e00000000,
+ 0x00004040407c4242, 0x4242427c00000000, 0x00000000003c4240, 0x4040423c00000000, 0x00000202023e4242, 0x4242423e00000000,
+ 0x00000000003c4242, 0x7e40403c00000000, 0x00000e10107c1010, 0x1010101000000000, 0x00000000003e4242, 0x4242423e02023c00,
+ 0x00004040407c4242, 0x4242424200000000, 0x0000101000301010, 0x1010103800000000, 0x00000404000c0404, 0x0404040444443800,
+ 0x0000404040424448, 0x7048444200000000, 0x0000301010101010, 0x1010103800000000, 0x0000000000fc9292, 0x9292929200000000,
+ 0x00000000007c4242, 0x4242424200000000, 0x00000000003c4242, 0x4242423c00000000, 0x00000000007c4242, 0x4242427c40404000,
+ 0x00000000003e4242, 0x4242423e02020200, 0x00000000005e6040, 0x4040404000000000, 0x00000000003e4040, 0x3c02027c00000000,
+ 0x00001010107c1010, 0x1010100e00000000, 0x0000000000424242, 0x4242423e00000000, 0x0000000000424242, 0x2424181800000000,
+ 0x0000000000828292, 0x9292927c00000000, 0x0000000000424224, 0x1824424200000000, 0x0000000000424242, 0x4242423e02023c00,
+ 0x00000000007e0408, 0x1020407e00000000, 0x00000c1010102010, 0x1010100c00000000, 0x0000101010101010, 0x1010101000000000,
+ 0x0000300808080408, 0x0808083000000000, 0x000000000062928c, 0x0000000000000000
+ };
+
+ const char * vertex_shader =
+ "# version 330 core\n"
+ "in vec2 vertex_xy;\n"
+ "in vec2 vertex_uv;\n"
+ "in vec4 vertex_rgba;\n"
+ "out vec2 fragment_uv;\n"
+ "out vec4 fragment_rgba;\n"
+ "void main () {\n"
+ " gl_Position = vec4 (vertex_xy, 0, 1);\n"
+ " fragment_uv = vertex_uv;\n"
+ " fragment_rgba = vertex_rgba;\n"
+ "}\n";
+
+ const char * fragment_shader =
+ "# version 330 core\n"
+ "uniform sampler2D texture_p;\n"
+ "in vec2 fragment_uv;\n"
+ "in vec4 fragment_rgba;\n"
+ "out vec4 data;\n"
+ "void main () {\n"
+ " data = texture (texture_p, fragment_uv) * fragment_rgba;\n"
+ "}\n";
+
+ uint * dumb_buffer = null;
+ uint * order = null;
+
+ uint xy_attribute = 0;
+ uint uv_attribute = 0;
+ uint rgba_attribute = 0;
+ //~uint flags = 0;
+
+ uint u = 0;
+ uint v = 0;
+
+ if (opengl->using_precomputed_spritesheet == true) {
+ for (uint index = 0; index < 95; ++index) {
+ opengl->font_index [opengl->font_count] [index] = ++opengl->sprite_count - 1;
+ }
+
+ ++opengl->sprite_count;
+ ++opengl->font_count;
+
+ goto ignore_import;
+ }
+
+ dumb_buffer = allocate (256 * sizeof (* dumb_buffer));
+
+ for (uint index = 0; index < 256; ++index) {
+ dumb_buffer [index] = 0xffffffff;
+ }
+
+ ++opengl->font_count;
+
+ const uint current = opengl->font_count - 1;
+
+ opengl->font_index = reallocate (opengl->font_index, opengl->font_count * sizeof (* opengl->font_index));
+ opengl->font_width = reallocate (opengl->font_width, opengl->font_count * sizeof (* opengl->font_width));
+ opengl->font_height = reallocate (opengl->font_height, opengl->font_count * sizeof (* opengl->font_height));
+ opengl->font_begin = reallocate (opengl->font_begin, opengl->font_count * sizeof (* opengl->font_begin));
+ opengl->font_end = reallocate (opengl->font_end, opengl->font_count * sizeof (* opengl->font_end));
+
+ opengl->font_begin [opengl->font_count - 1] = ' ';
+ opengl->font_end [opengl->font_count - 1] = '~';
+
+ opengl->font_index [opengl->font_count - 1] = allocate (95 * sizeof (* * opengl->font_index));
+ opengl->font_width [opengl->font_count - 1] = allocate (95 * sizeof (* * opengl->font_width));
+ opengl->font_height [opengl->font_count - 1] = allocate (95 * sizeof (* * opengl->font_height));
+
+ for (uint index = 0; index < 95; ++index) {
+ uint * buffer = allocate (opengl_font_width * opengl_font_height * sizeof (* buffer));
+
+ for (uint value = 0; value < 2; ++value) {
+ for (uint bit = 64; bit > 0; --bit) {
+ uint destination = ((value << 3) - ((bit - 1) >> 3) + 7) * opengl_font_width - ((bit - 1) & 7) + 7;
+ uint source = (font_bitmap [2 * index + value] >> (bit - 1)) & 1;
+
+ buffer [destination] = (source) ? 0xffffffff : 0x00000000;
+ }
+ }
+
+ opengl->font_index [current] [index] = opengl_sprite_raw_import (opengl, buffer, opengl_font_width, opengl_font_height);
+ opengl->font_width [current] [index] = opengl_font_width;
+ opengl->font_height [current] [index] = opengl_font_height;
+ }
+
+ opengl_sprite_raw_import (opengl, dumb_buffer, 16, 16);
+
+ opengl->spritesheet_data = allocate (opengl->spritesheet_size * opengl->spritesheet_size * sizeof (* opengl->spritesheet_data));
+
+ order = allocate (opengl->sprite_count * sizeof (* order));
+
+ for (uint index = 0; index < opengl->sprite_count; ++index) {
+ order [index] = index;
+ }
+
+ for (uint index = 0; index < opengl->sprite_count; ++index) {
+ for (uint subindex = 0; subindex < opengl->sprite_count; ++subindex) {
+ if (opengl->sprite_height [order [index]] < opengl->sprite_height [order [subindex]]) {
+ uint temporary = order [index];
+
+ order [index] = order [subindex];
+ order [subindex] = temporary;
+ }
+ }
+ }
+
+ for (uint index = 0; index < opengl->sprite_count; ++index) {
+ if (u + opengl->sprite_width [order [index]] >= opengl->spritesheet_size) {
+ u *= 0;
+ v += opengl->sprite_height [order [index]];
+ }
+
+ opengl->sprite_u [order [index]] = (float) u / (float) opengl->spritesheet_size;
+ opengl->sprite_v [order [index]] = (float) v / (float) opengl->spritesheet_size;
+
+ for (uint y = 0; y < opengl->sprite_height [order [index]]; ++y) {
+ for (uint x = 0; x < opengl->sprite_width [order [index]]; ++x) {
+ uint destination = (v + y) * opengl->spritesheet_size + (u + x);
+ uint source = y * opengl->sprite_width [order [index]] + x;
+
+ opengl->spritesheet_data [destination] = opengl->sprite_data [order [index]] [source];
+ }
+ }
+
+ u += opengl->sprite_width [order [index]];
+
+ opengl->sprite_data [order [index]] = deallocate (opengl->sprite_data [order [index]]);
+ }
+
+ opengl->sprite_data = deallocate (opengl->sprite_data);
+ order = deallocate (order);
+
+ ignore_import:
+
+ opengl->window_width = window_width;
+ opengl->window_height = window_height;
+
+ opengl->pixel_width = 2.0f / (float) window_width;
+ opengl->pixel_height = 2.0f / (float) window_height;
+
+ //~if (window_flags == 0) {
+ //~flags = opengl_window_decorated | opengl_window_resizable;
+ //~} else {
+ //~flags = window_flags;
+ //~}
+
+ glfwInit ();
+
+ glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 3);
+ glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+ glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, 1);
+
+ opengl->window = glfwCreateWindow ((int) window_width, (int) window_height, window_title, null, null);
+
+ glfwSetWindowSizeLimits (opengl->window, 320, 240, 1920, 1080);
+
+ fatal_failure (opengl->window == null, "Failed to create GLFW window.\n");
+
+ glfwMakeContextCurrent (opengl->window);
+
+ opengl->glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) glfwGetProcAddress ("glGenVertexArrays");
+ opengl->glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) glfwGetProcAddress ("glBindVertexArray");
+ opengl->glGenBuffers = (PFNGLGENBUFFERSPROC) glfwGetProcAddress ("glGenBuffers");
+ opengl->glBindBuffer = (PFNGLBINDBUFFERPROC) glfwGetProcAddress ("glBindBuffer");
+ opengl->glCreateShader = (PFNGLCREATESHADERPROC) glfwGetProcAddress ("glCreateShader");
+ opengl->glShaderSource = (PFNGLSHADERSOURCEPROC) glfwGetProcAddress ("glShaderSource");
+ opengl->glCompileShader = (PFNGLCOMPILESHADERPROC) glfwGetProcAddress ("glCompileShader");
+ opengl->glCreateProgram = (PFNGLCREATEPROGRAMPROC) glfwGetProcAddress ("glCreateProgram");
+ opengl->glAttachShader = (PFNGLATTACHSHADERPROC) glfwGetProcAddress ("glAttachShader");
+ opengl->glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) glfwGetProcAddress ("glBindFragDataLocation");
+ opengl->glLinkProgram = (PFNGLLINKPROGRAMPROC) glfwGetProcAddress ("glLinkProgram");
+ opengl->glUseProgram = (PFNGLUSEPROGRAMPROC) glfwGetProcAddress ("glUseProgram");
+ opengl->glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) glfwGetProcAddress ("glGetAttribLocation");
+ opengl->glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) glfwGetProcAddress ("glEnableVertexAttribArray");
+ opengl->glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) glfwGetProcAddress ("glVertexAttribPointer");
+ opengl->glUniform1i = (PFNGLUNIFORM1IPROC) glfwGetProcAddress ("glUniform1i");
+ opengl->glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) glfwGetProcAddress ("glDeleteVertexArrays");
+ opengl->glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) glfwGetProcAddress ("glDeleteBuffers");
+ opengl->glDeleteShader = (PFNGLDELETESHADERPROC) glfwGetProcAddress ("glDeleteShader");
+ opengl->glDeleteProgram = (PFNGLDELETEPROGRAMPROC) glfwGetProcAddress ("glDeleteProgram");
+ opengl->glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) glfwGetProcAddress ("glGetUniformLocation");
+ opengl->glBufferData = (PFNGLBUFFERDATAPROC) glfwGetProcAddress ("glBufferData");
+
+ glViewport (0, 0, (int) window_width, (int) window_height);
+
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable (GL_CULL_FACE);
+ glEnable (GL_BLEND);
+
+ opengl->glGenVertexArrays (1, & opengl->vertex_object);
+ opengl->glBindVertexArray (opengl->vertex_object);
+
+ opengl->glGenBuffers (1, & opengl->vertex_buffer);
+ opengl->glBindBuffer (GL_ARRAY_BUFFER, opengl->vertex_buffer);
+
+ opengl->glGenBuffers (1, & opengl->index_buffer);
+ opengl->glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, opengl->index_buffer);
+
+ opengl->vertex_shader = opengl->glCreateShader (GL_VERTEX_SHADER);
+
+ opengl->glShaderSource (opengl->vertex_shader, 1, & vertex_shader, null);
+ opengl->glCompileShader (opengl->vertex_shader);
+
+ opengl->fragment_shader = opengl->glCreateShader (GL_FRAGMENT_SHADER);
+
+ opengl->glShaderSource (opengl->fragment_shader, 1, & fragment_shader, null);
+ opengl->glCompileShader (opengl->fragment_shader);
+
+ opengl->shader_program = opengl->glCreateProgram ();
+
+ opengl->glAttachShader (opengl->shader_program, opengl->vertex_shader);
+ opengl->glAttachShader (opengl->shader_program, opengl->fragment_shader);
+
+ opengl->glBindFragDataLocation (opengl->shader_program, 0, "data");
+
+ opengl->glLinkProgram (opengl->shader_program);
+ opengl->glUseProgram (opengl->shader_program);
+
+ xy_attribute = (uint) opengl->glGetAttribLocation (opengl->shader_program, "vertex_xy");
+
+ opengl->glEnableVertexAttribArray (xy_attribute);
+
+ opengl->glVertexAttribPointer (xy_attribute, 2, GL_FLOAT, GL_FALSE, 8 * sizeof (float), (void *) 0);
+
+ uv_attribute = (uint) opengl->glGetAttribLocation (opengl->shader_program, "vertex_uv");
+
+ opengl->glEnableVertexAttribArray (uv_attribute);
+
+ opengl->glVertexAttribPointer (uv_attribute, 2, GL_FLOAT, GL_FALSE, 8 * sizeof (float), (void *) (2 * sizeof (float)));
+
+ rgba_attribute = (uint) opengl->glGetAttribLocation (opengl->shader_program, "vertex_rgba");
+
+ opengl->glEnableVertexAttribArray (rgba_attribute);
+
+ opengl->glVertexAttribPointer (rgba_attribute, 4, GL_FLOAT, GL_FALSE, 8 * sizeof (float), (void *) (4 * sizeof (float)));
+
+ opengl->vertex_array = allocate (opengl->vertex_limit * sizeof (opengl->vertex_array));
+ opengl->index_array = allocate (opengl->index_limit * sizeof (opengl->index_array));
+
+ glGenTextures (1, & opengl->spritesheet);
+
+ glBindTexture (GL_TEXTURE_2D, opengl->spritesheet);
+
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, opengl->spritesheet_size, opengl->spritesheet_size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ opengl->spritesheet_data);
+
+ opengl->glUniform1i (opengl->glGetUniformLocation (opengl->shader_program, "texture_p"), 0);
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ if (opengl->using_precomputed_spritesheet == true) {
+ opengl->spritesheet_data = deallocate (opengl->spritesheet_data);
+ }
+
+ opengl->active = true;
+
+ opengl->frame_begin = nano_time ();
+
+ glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
+
+ glClear (GL_COLOR_BUFFER_BIT);
+
+ print ("[/2Success/-] Configured OpenGL renderer.\n");
+}
+
+static void opengl_synchronize (opengl_structure * opengl, uint colour) {
+ const int signal_code [signal_count] = {
+ 0,
+ GLFW_KEY_A, GLFW_KEY_B, GLFW_KEY_C, GLFW_KEY_D,
+ GLFW_KEY_E, GLFW_KEY_F, GLFW_KEY_G, GLFW_KEY_H,
+ GLFW_KEY_I, GLFW_KEY_J, GLFW_KEY_K, GLFW_KEY_L,
+ GLFW_KEY_M, GLFW_KEY_N, GLFW_KEY_O, GLFW_KEY_P,
+ GLFW_KEY_Q, GLFW_KEY_R, GLFW_KEY_S, GLFW_KEY_T,
+ GLFW_KEY_U, GLFW_KEY_V, GLFW_KEY_W, GLFW_KEY_X,
+ GLFW_KEY_Y, GLFW_KEY_Z, GLFW_KEY_0, GLFW_KEY_1,
+ GLFW_KEY_2, GLFW_KEY_3, GLFW_KEY_4, GLFW_KEY_5,
+ GLFW_KEY_6, GLFW_KEY_7, GLFW_KEY_8, GLFW_KEY_9,
+ GLFW_KEY_ESCAPE, GLFW_KEY_TAB, GLFW_KEY_ENTER, GLFW_KEY_ENTER,
+ GLFW_KEY_SLASH, GLFW_KEY_BACKSLASH, GLFW_KEY_SEMICOLON, GLFW_KEY_GRAVE_ACCENT,
+ GLFW_KEY_SPACE, GLFW_KEY_BACKSPACE, GLFW_KEY_PERIOD, GLFW_KEY_COMMA,
+ GLFW_KEY_APOSTROPHE, GLFW_KEY_CAPS_LOCK, GLFW_KEY_MINUS, GLFW_KEY_EQUAL,
+ GLFW_KEY_LEFT_BRACKET, GLFW_KEY_RIGHT_BRACKET, GLFW_KEY_LEFT_CONTROL, GLFW_KEY_RIGHT_CONTROL,
+ GLFW_KEY_LEFT_SHIFT, GLFW_KEY_RIGHT_SHIFT, GLFW_KEY_LEFT_ALT, GLFW_KEY_RIGHT_ALT,
+ GLFW_KEY_F1, GLFW_KEY_F2, GLFW_KEY_F3, GLFW_KEY_F4,
+ GLFW_KEY_F5, GLFW_KEY_F6, GLFW_KEY_F7, GLFW_KEY_F8,
+ GLFW_KEY_F9, GLFW_KEY_F10, GLFW_KEY_F11, GLFW_KEY_F12,
+ GLFW_KEY_UP, GLFW_KEY_DOWN, GLFW_KEY_LEFT, GLFW_KEY_RIGHT,
+ GLFW_KEY_NUM_LOCK, GLFW_KEY_PAUSE, GLFW_KEY_INSERT, GLFW_KEY_HOME,
+ GLFW_KEY_PAGE_UP, GLFW_KEY_DELETE, GLFW_KEY_END, GLFW_KEY_PAGE_DOWN,
+ GLFW_KEY_KP_ADD, GLFW_KEY_KP_SUBTRACT, GLFW_KEY_KP_MULTIPLY, GLFW_KEY_KP_DIVIDE,
+ GLFW_KEY_KP_ENTER, GLFW_KEY_KP_DECIMAL, GLFW_KEY_KP_0, GLFW_KEY_KP_1,
+ GLFW_KEY_KP_2, GLFW_KEY_KP_3, GLFW_KEY_KP_4, GLFW_KEY_KP_5,
+ GLFW_KEY_KP_6, GLFW_KEY_KP_7, GLFW_KEY_KP_8, GLFW_KEY_KP_9
+ };
+
+ float r = (float) ((colour >> 24) & 0xff) / 255.0f;
+ float g = (float) ((colour >> 16) & 0xff) / 255.0f;
+ float b = (float) ((colour >> 8) & 0xff) / 255.0f;
+ float a = (float) ((colour >> 0) & 0xff) / 255.0f;
+
+ int new_window_width = 0;
+ int new_window_height = 0;
+
+ glClearColor (r, g, b, a);
+
+ glClear (GL_COLOR_BUFFER_BIT);
+
+ glfwPollEvents ();
+
+ glfwSetWindowShouldClose (opengl->window, opengl->active == false);
+
+ glfwGetWindowSize (opengl->window, & new_window_width, & new_window_height);
+
+ if ((opengl->window_width != (uint) new_window_width) || (opengl->window_height != (uint) new_window_height)) {
+ if ((new_window_width <= 0) || (new_window_height <= 0)) return;
+
+ glViewport (0, 0, new_window_width, new_window_height);
+
+ opengl->window_width = (uint) new_window_width;
+ opengl->window_height = (uint) new_window_height;
+
+ opengl->pixel_width = 2.0f / (float) new_window_width;
+ opengl->pixel_height = 2.0f / (float) new_window_height;
+ }
+
+ opengl->cursor [cursor_left] = (bool) (glfwGetMouseButton (opengl->window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
+ opengl->cursor [cursor_middle] = (bool) (glfwGetMouseButton (opengl->window, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
+ opengl->cursor [cursor_right] = (bool) (glfwGetMouseButton (opengl->window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
+
+ if (opengl->freeze_cursor == false) {
+ double x = 0.0;
+ double y = 0.0;
+
+ glfwGetCursorPos (opengl->window, & x, & y);
+
+ opengl->cursor_x = (int) x;
+ opengl->cursor_y = (int) y;
+
+ //~if ((opengl->cursor_x < 0) || (opengl->cursor_x > (int) opengl->window_width) ||
+ //~(opengl->cursor_y < 0) || (opengl->cursor_y > (int) opengl->window_height)) {
+ //~opengl->cursor_x = 0;
+ //~opengl->cursor_y = 0;
+ //~}
+ } else {
+ if ((opengl->cursor [cursor_left] == false)
+ && (opengl->cursor [cursor_middle] == false)
+ && (opengl->cursor [cursor_right] == false)) {
+ opengl->freeze_cursor = false;
+ }
+ }
+
+ if (opengl->freeze_signal == false) {
+ for (uint index = 0; index < signal_count; ++index) {
+ opengl->signal [index] = (bool) (glfwGetKey (opengl->window, signal_code [index]) == GLFW_PRESS);
+ }
+ }
+
+ opengl->glBufferData (GL_ARRAY_BUFFER, opengl->vertex_count * 4, opengl->vertex_array, GL_DYNAMIC_DRAW);
+ opengl->glBufferData (GL_ELEMENT_ARRAY_BUFFER, opengl->index_count * 4, opengl->index_array, GL_DYNAMIC_DRAW);
+
+ opengl->glBindBuffer (GL_ARRAY_BUFFER, opengl->vertex_buffer);
+
+ glDrawElements (GL_TRIANGLES, (int) opengl->index_count * 4, GL_UNSIGNED_INT, null);
+
+ glfwSwapBuffers (opengl->window);
+
+ opengl->vertex_count = 0;
+ opengl->index_count = 0;
+
+ opengl->frame_end = nano_time ();
+
+ opengl->frame_time = opengl->frame_end - opengl->frame_begin;
+
+ if (opengl->frame_time < 1000000000ul / opengl->gameplay_framerate) {
+ nano_wait (1000000000ul / opengl->gameplay_framerate - opengl->frame_time);
+ }
+
+ if (opengl->global_tick % opengl->gameplay_framerate == 0) {
+ opengl->framerate = (uint) (1000000000ul / opengl->frame_time);
+ }
+
+ ++opengl->global_tick;
+
+ opengl->global_tick = opengl->global_tick % (opengl->gameplay_framerate * opengl->animation_framerate);
+ opengl->gameplay_tick = opengl->global_tick % (opengl->gameplay_framerate);
+ opengl->animation_tick = opengl->global_tick / (opengl->gameplay_framerate / opengl->animation_framerate);
+
+ opengl->frame_begin = nano_time ();
+}
+
+static void opengl_render_base (opengl_structure * opengl, uint sprite, int x, int y, uint u, uint v, uint width, uint height,
+ float scale_x, float scale_y, int flip_x, int flip_y,
+ uint colour_upper_left, uint colour_upper_right, uint colour_lower_left, uint colour_lower_right) {
+ float screen_x = 0.0f;
+ float screen_y = 0.0f;
+ float unwrap_x = 0.0f;
+ float unwrap_y = 0.0f;
+ float screen_width = 0.0f;
+ float screen_height = 0.0f;
+ float unwrap_width = 0.0f;
+ float unwrap_height = 0.0f;
+
+ if ((x > (int) opengl->window_width) || (y > (int) opengl->window_height)) return;
+
+ if ((x < (int) - ((float) width * scale_x)) || (y < (int) - ((float) height * scale_y))) return;
+
+ if (sprite >= opengl->sprite_count) return;
+ if (opengl->vertex_count + 32 >= opengl->vertex_limit) return;
+ if (opengl->index_count + 6 >= opengl->index_limit) return;
+
+ screen_x = + ((float) x * opengl->pixel_width - 1);
+ screen_y = - ((float) y * opengl->pixel_height - 1);
+
+ unwrap_x = opengl->sprite_u [sprite] + (float) u / (float) opengl->spritesheet_size;
+ unwrap_y = opengl->sprite_v [sprite] + (float) v / (float) opengl->spritesheet_size;
+
+ screen_width = +((float) width * opengl->pixel_width * scale_x);
+ screen_height = -((float) height * opengl->pixel_height * scale_y);
+
+ unwrap_width = (float) width / (float) opengl->spritesheet_size;
+ unwrap_height = (float) height / (float) opengl->spritesheet_size;
+
+ opengl->vertex_array [opengl->vertex_count + 0] = screen_x;
+ opengl->vertex_array [opengl->vertex_count + 1] = screen_y;
+ opengl->vertex_array [opengl->vertex_count + 2] = unwrap_x + unwrap_width * (float) (flip_y != 0);
+ opengl->vertex_array [opengl->vertex_count + 3] = unwrap_y + unwrap_height * (float) (flip_x != 0);
+ opengl->vertex_array [opengl->vertex_count + 4] = normal_r (colour_upper_left);
+ opengl->vertex_array [opengl->vertex_count + 5] = normal_g (colour_upper_left);
+ opengl->vertex_array [opengl->vertex_count + 6] = normal_b (colour_upper_left);
+ opengl->vertex_array [opengl->vertex_count + 7] = normal_a (colour_upper_left);
+
+ opengl->vertex_array [opengl->vertex_count + 8] = screen_x + screen_width;
+ opengl->vertex_array [opengl->vertex_count + 9] = screen_y;
+ opengl->vertex_array [opengl->vertex_count + 10] = unwrap_x + unwrap_width * (float) (flip_y == 0);
+ opengl->vertex_array [opengl->vertex_count + 11] = unwrap_y + unwrap_height * (float) (flip_x != 0);
+ opengl->vertex_array [opengl->vertex_count + 12] = normal_r (colour_upper_right);
+ opengl->vertex_array [opengl->vertex_count + 13] = normal_g (colour_upper_right);
+ opengl->vertex_array [opengl->vertex_count + 14] = normal_b (colour_upper_right);
+ opengl->vertex_array [opengl->vertex_count + 15] = normal_a (colour_upper_right);
+
+ opengl->vertex_array [opengl->vertex_count + 16] = screen_x;
+ opengl->vertex_array [opengl->vertex_count + 17] = screen_y + screen_height;
+ opengl->vertex_array [opengl->vertex_count + 18] = unwrap_x + unwrap_width * (float) (flip_y != 0);
+ opengl->vertex_array [opengl->vertex_count + 19] = unwrap_y + unwrap_height * (float) (flip_x == 0);
+ opengl->vertex_array [opengl->vertex_count + 20] = normal_r (colour_lower_left);
+ opengl->vertex_array [opengl->vertex_count + 21] = normal_g (colour_lower_left);
+ opengl->vertex_array [opengl->vertex_count + 22] = normal_b (colour_lower_left);
+ opengl->vertex_array [opengl->vertex_count + 23] = normal_a (colour_lower_left);
+
+ opengl->vertex_array [opengl->vertex_count + 24] = screen_x + screen_width;
+ opengl->vertex_array [opengl->vertex_count + 25] = screen_y + screen_height;
+ opengl->vertex_array [opengl->vertex_count + 26] = unwrap_x + unwrap_width * (float) (flip_y == 0);
+ opengl->vertex_array [opengl->vertex_count + 27] = unwrap_y + unwrap_height * (float) (flip_x == 0);
+ opengl->vertex_array [opengl->vertex_count + 28] = normal_r (colour_lower_right);
+ opengl->vertex_array [opengl->vertex_count + 29] = normal_g (colour_lower_right);
+ opengl->vertex_array [opengl->vertex_count + 30] = normal_b (colour_lower_right);
+ opengl->vertex_array [opengl->vertex_count + 31] = normal_a (colour_lower_right);
+
+ opengl->index_array [opengl->index_count + 0] = (opengl->vertex_count >> 3) + 2;
+ opengl->index_array [opengl->index_count + 1] = (opengl->vertex_count >> 3) + 1;
+ opengl->index_array [opengl->index_count + 2] = (opengl->vertex_count >> 3) + 0;
+ opengl->index_array [opengl->index_count + 3] = (opengl->vertex_count >> 3) + 1;
+ opengl->index_array [opengl->index_count + 4] = (opengl->vertex_count >> 3) + 2;
+ opengl->index_array [opengl->index_count + 5] = (opengl->vertex_count >> 3) + 3;
+
+ opengl->vertex_count += 32;
+ opengl->index_count += 6;
+}
+
+static void opengl_render_rectangle (opengl_structure * opengl, int x, int y, uint width, uint height, uint colour) {
+ opengl_render_base (opengl, opengl->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16.0f, (float) height / 16.0f, 0, 0,
+ colour, colour, colour, colour);
+}
+
+static void opengl_render_rectangle_vertical_gradient (opengl_structure * opengl, int x, int y, uint width, uint height,
+ uint colour_up, uint colour_down) {
+ opengl_render_base (opengl, opengl->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16.0f, (float) height / 16.0f, 0, 0,
+ colour_up, colour_up, colour_down, colour_down);
+}
+
+static void opengl_render_rectangle_horizontal_gradient (opengl_structure * opengl, int x, int y, uint width, uint height,
+ uint colour_left, uint colour_right) {
+ opengl_render_base (opengl, opengl->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16.0f, (float) height / 16.0f, 0, 0,
+ colour_left, colour_right, colour_left, colour_right);
+}
+
+static void opengl_render_sprite (opengl_structure * opengl, uint sprite, int x, int y) {
+ opengl_render_base (opengl, sprite, x, y, 0, 0, opengl->sprite_width [sprite], opengl->sprite_height [sprite], 1.0f, 1.0f, 0, 0,
+ 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static void opengl_render_sprite_crop (opengl_structure * opengl, uint sprite, int x, int y, uint u, uint v, uint width, uint height) {
+ opengl_render_base (opengl, sprite, x, y, u, v, width, height, 1.0f, 1.0f, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static void opengl_render_sprite_flip (opengl_structure * opengl, uint sprite, int x, int y, int flip_x, int flip_y) {
+ opengl_render_base (opengl, sprite, x, y, 0, 0, opengl->sprite_width [sprite], opengl->sprite_height [sprite], 1.0f, 1.0f,
+ flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static void opengl_render_sprite_colour (opengl_structure * opengl, uint sprite, int x, int y, uint colour) {
+ opengl_render_base (opengl, sprite, x, y, 0, 0, opengl->sprite_width [sprite], opengl->sprite_height [sprite], 1.0f, 1.0f, 0, 0,
+ colour, colour, colour, colour);
+}
+
+static void opengl_render_sprite_control (opengl_structure * opengl, uint sprite, int x, int y, uint u, uint v, uint width, uint height,
+ int flip_x, int flip_y) {
+ opengl_render_base (opengl, sprite, x, y, u, v, width, height, 1.0f, 1.0f, flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
+}
+
+static void opengl_render_sprite_crop_colour (opengl_structure * opengl, uint sprite, uint colour, int x, int y, uint u, uint v, uint width, uint height) {
+ opengl_render_base (opengl, sprite, x, y, u, v, width, height, 1.0f, 1.0f, 0, 0, colour, colour, colour, colour);
+}
+
+static void opengl_render_sprite_animate (opengl_structure * opengl, uint sprite, int x, int y, uint frames, uint state, uint states) {
+ uint width = opengl->sprite_width [sprite] / states;
+ uint height = opengl->sprite_height [sprite] / frames;
+ uint u = width * (state % states);
+ uint v = height * (opengl->animation_tick % frames);
+
+ opengl_render_sprite_crop (opengl, sprite, x, y, u, v, width, height);
+}
+
+static uint opengl_render_character_width (opengl_structure * opengl, char character, uint font, float scale) {
+ if ((character < opengl->font_begin [font]) || (character > opengl->font_end [font])) {
+ return (0);
+ } else {
+ const uint index = opengl->font_index [font] [character - opengl->font_begin [font]];
+
+ return ((uint) (scale * (float) opengl->sprite_width [index]));
+ }
+}
+
+static uint opengl_render_character_height (opengl_structure * opengl, char character, uint font, float scale) {
+ if ((character < opengl->font_begin [font]) || (character > opengl->font_end [font])) {
+ return (0);
+ } else {
+ const uint index = opengl->font_index [font] [character - opengl->font_begin [font]];
+
+ return ((uint) (scale * (float) opengl->sprite_height [index]));
+ }
+}
+
+static uint opengl_render_string_width (opengl_structure * opengl, const char * string, uint font, float scale) {
+ uint width = 0;
+ uint match = 0;
+
+ if (string == null) {
+ return (0);
+ }
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ if (string [index] == '\t') {
+ width += opengl->tab_width * opengl_render_character_width (opengl, ' ', font, scale);
+ } else if (string [index] == '\n') {
+ match = maximum (width, match);
+ width = 0;
+ } else {
+ width += opengl_render_character_width (opengl, string [index], font, scale);
+ }
+ }
+
+ return (maximum (width, match));
+}
+
+static uint opengl_render_string_height (opengl_structure * opengl, const char * string, uint font, float scale) {
+ uint height = opengl_render_character_height (opengl, ' ', font, scale);
+
+ if ((string == null) || (string [0] == '\0')) {
+ return (0);
+ }
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ if (string [index] == '\n') {
+ height += opengl_render_character_height (opengl, ' ', font, scale);
+ }
+ }
+
+ return (height);
+}
+
+static void opengl_render_character_base (opengl_structure * opengl, char character, uint font, int x, int y, float scale,
+ uint colour_upper_left, uint colour_upper_right, uint colour_lower_left, uint colour_lower_right) {
+ if ((character < opengl->font_begin [font]) || (character > opengl->font_end [font])) return;
+
+ if (font == opengl->default_font) {
+ font = opengl->font_count - 1;
+ }
+
+ const uint index = opengl->font_index [font] [character - opengl->font_begin [font]];
+ const uint width = opengl->sprite_width [index];
+ const uint height = opengl->sprite_height [index];
+
+ opengl_render_base (opengl, index, x, y, 0, 0, width, height, scale, scale, 0, 0, colour_upper_left, colour_upper_right,
+ colour_lower_left, colour_lower_right);
+}
+
+static void opengl_render_character (opengl_structure * opengl, char character, uint font, int x, int y, float scale, uint colour) {
+ opengl_render_character_base (opengl, character, font, x, y, scale, colour, colour, colour, colour);
+}
+
+static void opengl_render_character_vertical_gradient (opengl_structure * opengl, char character, uint font, int x, int y, float scale,
+ uint colour_up, uint colour_down) {
+ opengl_render_character_base (opengl, character, font, x, y, scale, colour_up, colour_up, colour_down, colour_down);
+}
+
+static void opengl_render_character_horizontal_gradient (opengl_structure * opengl, char character, uint font, int x, int y, float scale,
+ uint colour_left, uint colour_right) {
+ opengl_render_character_base (opengl, character, font, x, y, scale, colour_left, colour_right, colour_left, colour_right);
+}
+
+static void opengl_render_string_base (opengl_structure * opengl, const char * string, uint font, int x, int y, float scale,
+ uint colour_upper_left, uint colour_upper_right, uint colour_lower_left, uint colour_lower_right) {
+ int offset = x;
+
+ if (string == null) return;
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ if (string [index] == '\t') {
+ x += opengl->tab_width * opengl_render_character_width (opengl, ' ', font, scale);
+ continue;
+ } else if (string [index] == '\n') {
+ x = offset;
+ y += opengl_render_character_height (opengl, ' ', font, scale);
+ continue;
+ } else {
+ opengl_render_character_base (opengl, string [index], font, x, y, scale, colour_upper_left, colour_upper_right,
+ colour_lower_left, colour_lower_right);
+
+ x += opengl_render_character_width (opengl, string [index], font, scale);
+ }
+ }
+}
+
+static void opengl_render_string (opengl_structure * opengl, const char * string, uint font, int x, int y, float scale, uint colour) {
+ opengl_render_string_base (opengl, string, font, x, y, scale, colour, colour, colour, colour);
+}
+
+static void opengl_render_string_vertical_gradient (opengl_structure * opengl, const char * string, uint font, int x, int y, float scale,
+ uint colour_up, uint colour_down) {
+ opengl_render_string_base (opengl, string, font, x, y, scale, colour_up, colour_up, colour_down, colour_down);
+}
+
+static void opengl_render_string_horizontal_gradient (opengl_structure * opengl, const char * string, uint font, int x, int y, float scale,
+ uint colour_left, uint colour_right) {
+ opengl_render_string_base (opengl, string, font, x, y, scale, colour_left, colour_right, colour_left, colour_right);
+}
+
+static void opengl_render_string_full_vertical_gradient (opengl_structure * opengl, const char * string, uint font, int x, int y, float scale,
+ uint colour_up, uint colour_down) {
+ int offset = x;
+ uint back = 0;
+ uint up = 0;
+ uint down = 0;
+
+ const float interpolator = 1.0f / (float) string_full_height (string);
+
+ if (string == null) return;
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ if (string [index] == '\t') {
+ x += opengl->tab_width * opengl_render_character_width (opengl, ' ', font, scale);
+ continue;
+ } else if (string [index] == '\n') {
+ back += 1;
+ x = offset;
+ y += opengl_render_character_height (opengl, ' ', font, scale);
+ continue;
+ } else {
+ up = colour_linear_interpolation (colour_up, colour_down, (float) (back + 0) * interpolator);
+ down = colour_linear_interpolation (colour_up, colour_down, (float) (back + 1) * interpolator);
+
+ opengl_render_character_vertical_gradient (opengl, string [index], font, x, y, scale, up, down);
+
+ x += opengl_render_character_width (opengl, string [index], font, scale);
+ }
+ }
+}
+
+static void opengl_render_string_full_horizontal_gradient (opengl_structure * opengl, const char * string, uint font, int x, int y, float scale,
+ uint colour_left, uint colour_right) {
+ int offset = x;
+ uint back = 0;
+ uint left = 0;
+ uint right = 0;
+
+ const float interpolator = 1.0f / (float) string_full_width (string, opengl->tab_width);
+
+ if (string == null) return;
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ if (string [index] == '\t') {
+ x += opengl->tab_width * opengl_render_character_width (opengl, ' ', font, scale);
+ continue;
+ } else if (string [index] == '\n') {
+ back = 0;
+ x = offset;
+ y += opengl_render_character_height (opengl, ' ', font, scale);
+ continue;
+ } else {
+ back += 1;
+ left = colour_linear_interpolation (colour_left, colour_right, (float) (back + 0) * interpolator);
+ right = colour_linear_interpolation (colour_left, colour_right, (float) (back + 1) * interpolator);
+
+ opengl_render_character_horizontal_gradient (opengl, string [index], font, x, y, scale, left, right);
+
+ x += opengl_render_character_width (opengl, string [index], font, scale);
+ }
+ }
+}
+
+static void opengl_render_framerate (opengl_structure * opengl, uint font, int x, int y, float scale, uint colour) {
+ opengl_render_string (opengl, number_to_string (opengl->framerate), font, x, y, scale, colour);
+}
+
+#undef opengl_font_width
+#undef opengl_font_height
--- /dev/null
+/// _
+/// __ ___ __ | |__ ___ _ __ ___
+/// \ \/ / '_ \| '_ \ / _ \ '__/ _ \
+/// > <| |_) | | | | __/ | | __/
+/// /_/\_\ .__/|_| |_|\___|_| \___|
+/// |_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xphere - Spherical coordinate system header-only literally library for use in CPU-computed ray tracing...
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+typedef struct {
+ float distance;
+ float horizontal;
+ float vertical;
+} sphere_vector;
+
+static bool sphere_epsilon (float error) {
+ return (error < 0.000001);
+}
+
+static float sphere_distance (float x, float y, float z) {
+ return (square_root (x * x + y * y + z * z));
+}
+
+static float sphere_horizontal (float x, float z) {
+ return ((sphere_epsilon (z)) ? (sign (x) * pi / 2.0f) : (arc_tangent (x / z)));
+}
+
+static float sphere_vertical (float y, float z) {
+ return ((sphere_epsilon (z)) ? (sign (y) * pi / 2.0f) : (arc_tangent (y / z)));
+}
+
+static float sphere_x (float horizontal, float z) {
+ return (z * tangent (horizontal));
+}
+
+static float sphere_y (float vertical, float z) {
+ return (z * tangent (vertical));
+}
+
+static float sphere_z (float distance, float horizontal, float vertical) {
+ const float x_over_z = tangent (horizontal);
+ const float y_over_z = tangent (vertical);
+
+ return (distance * square_root (1.0f / (x_over_z * x_over_z + y_over_z * y_over_z + 1.0f)));
+}
+
+static void sphere_transpose_x (float * distance, float * horizontal, float x) {
+ const float origin = (* distance) * (* distance);
+ const float offset = x * x;
+ const float square = origin + offset + 2 * x * (* distance) * cosine (* horizontal);
+
+ * distance = square_root (square);
+
+ * horizontal = arc_sine ((square + offset - origin) / (2 * (* distance) * x));
+}
+
+static void sphere_transpose_y (float * distance, float * vertical, float y) {
+ const float origin = (* distance) * (* distance);
+ const float offset = y * y;
+
+ * distance = square_root (origin + offset + 2 * y * (* distance) * cosine (* vertical));
+}
+
+static void sphere_transpose_z (float * distance, float * horizontal, float * vertical, float z) {
+ const float origin = (* distance) * (* distance);
+ const float offset = z * z;
+ const float side_a = secant (* vertical);
+ const float side_b = tangent (* horizontal);
+
+ * distance = square_root (origin + offset + 2 * z * (* distance) * square_root (1.0f / (side_a * side_a + sibe_b * side_b)));
+}
+
+static void sphere_convert (sphere_vector * vector, float x, float y, float z) {
+ vector->distance = sphere_distance (x, y, z);
+ vector->horizontal = sphere_horizontal (x, z);
+ vector->vertical = sphere_vertical ( y, z);
+}
--- /dev/null
+/// _ _
+/// __ ___ __ _ __(_) |_ ___
+/// \ \/ / '_ \| '__| | __/ _ \
+/// > <| |_) | | | | || __/
+/// /_/\_\ .__/|_| |_|\__\___|
+/// |_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xprite - Custom file format for semi-efficient and very fast encoding and decoding of simple images.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+static unsigned int sprite_colour [128] = {
+ 0x00000000, 0xff222222, 0xff444444, 0xff666666, 0xff888888, 0xffaaaaaa, 0xffcccccc, 0xffeeeeee,
+ 0x11000000, 0xff000022, 0xff000044, 0xff000066, 0xff000088, 0xff0000aa, 0xff0000cc, 0xff0000ee,
+ 0x22000000, 0xff002200, 0xff004400, 0xff006600, 0xff008800, 0xff00aa00, 0xff00cc00, 0xff00ee00,
+ 0x33000000, 0xff220000, 0xff440000, 0xff660000, 0xff880000, 0xffaa0000, 0xffcc0000, 0xffee0000,
+ 0x44000000, 0xff002222, 0xff004444, 0xff006666, 0xff008888, 0xff00aaaa, 0xff00cccc, 0xff00eeee,
+ 0x55000000, 0xff222200, 0xff444400, 0xff666600, 0xff888800, 0xffaaaa00, 0xffcccc00, 0xffeeee00,
+ 0x66000000, 0xff220022, 0xff440044, 0xff660066, 0xff880088, 0xffaa00aa, 0xffcc00cc, 0xffee00ee,
+ 0x77000000, 0xff001122, 0xff002244, 0xff003366, 0xff004488, 0xff0055aa, 0xff0066cc, 0xff0077ee,
+ 0x88000000, 0xff110022, 0xff220044, 0xff330066, 0xff440088, 0xff5500aa, 0xff6600cc, 0xff7700ee,
+ 0x99000000, 0xff002211, 0xff004422, 0xff006633, 0xff008844, 0xff00aa55, 0xff00cc66, 0xff00ee77,
+ 0xaa000000, 0xff112200, 0xff224400, 0xff336600, 0xff448800, 0xff55aa00, 0xff66cc00, 0xff77ee00,
+ 0xbb000000, 0xff220011, 0xff440022, 0xff660033, 0xff880044, 0xffaa0055, 0xffcc0066, 0xffee0077,
+ 0xcc000000, 0xff221100, 0xff442200, 0xff663300, 0xff884400, 0xffaa5500, 0xffcc6600, 0xffee7700,
+ 0xdd000000, 0xff112222, 0xff224444, 0xff336666, 0xff448888, 0xff55aaaa, 0xff66cccc, 0xff77eeee,
+ 0xee000000, 0xff222211, 0xff444422, 0xff666633, 0xff888844, 0xffaaaa55, 0xffcccc66, 0xffeeee77,
+ 0xff000000, 0xff221122, 0xff442244, 0xff663366, 0xff884488, 0xffaa55aa, 0xffcc66cc, 0xffee77ee
+};
+
+static void * sprite_import (char * path, int * width, int * height) {
+ unsigned char check_width = 0;
+ unsigned char check_height = 0;
+
+ int file, move;
+
+ unsigned int * data = null;
+
+ file = file_open (path, file_flag_read);
+
+ file_read (file, & check_width, (int) sizeof (check_width));
+ file_read (file, & check_height, (int) sizeof (check_height));
+
+ * width = (int) check_width;
+ * height = (int) check_height;
+
+ fatal_failure ((* width) == 0, "sprite_import: Invalid sprite width.");
+ fatal_failure ((* height) == 0, "sprite_import: Invalid sprite height.");
+
+ data = allocate ((* width) * (* height) * (int) sizeof (* data));
+
+ for (move = 0; move < (* width) * (* height); ++move) {
+ int colour = 0;
+ int repeat = 0;
+
+ file_read (file, & colour, 1);
+
+ if ((colour & 0x80) == 0) {
+ data [move] = sprite_colour [colour];
+ } else {
+ int offset;
+
+ file_read (file, & repeat, 1);
+
+ colour &= 0x7f;
+ repeat += 1;
+
+ for (offset = 0; offset < repeat; ++offset) {
+ data [move + offset] = sprite_colour [colour];
+ }
+
+ move += repeat - 1;
+ }
+ }
+
+ file = file_close (file);
+
+ return (data);
+}
+
+static void sprite_export (const char * path, int width, int height, unsigned int * data) {
+ int file, move;
+
+ file = file_open (path, file_flag_edit | file_flag_truncate | file_flag_create);
+
+ fatal_failure ((width <= 0) || (width >= 256), "sprite_export: Invalid sprite width.");
+ fatal_failure ((height <= 0) || (height >= 256), "sprite_export: Invalid sprite height.");
+
+ file_write (file, & width, 1);
+ file_write (file, & height, 1);
+
+ for (move = 0; move < width * height; ++move) {
+ int colour = 0;
+ int repeat = 0;
+
+ for (repeat = 1; (move + repeat < width * height) && (data [move] == data [move + repeat]) && (repeat < 256); ++repeat);
+
+ for (colour = 0; (data [move] != sprite_colour [colour]) && (colour < 128); ++colour);
+
+ if (colour == 128) colour = 127;
+
+ if (repeat == 1) {
+ file_write (file, & colour, 1);
+ } else {
+ colour |= 0x80;
+ repeat -= 1;
+ move += repeat;
+
+ file_write (file, & colour, 1);
+ file_write (file, & repeat, 1);
+
+ }
+ }
+
+ file = file_close (file);
+}
+
+static void sprite_swap_channels (unsigned int * data, int width, int height) {
+ int move;
+
+ for (move = 0; move < width * height; ++move) {
+ data [move] = (data [move] & 0xff00ff00) | ((data [move] & 0xff0000) >> 16) | ((data [move] & 0xff) << 16);
+ }
+}
--- /dev/null
+/// __ ___ __ ___ ___ ___ ___ ___ ___ _ __
+/// \ \/ / '__/ _ \ / __/ _ \/ __/ __|/ _ \| '__|
+/// > <| | | (_) | (_| __/\__ \__ \ (_) | |
+/// /_/\_\_| \___/ \___\___||___/___/\___/|_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xrocessor - Probably the most minimalistic general preprocessor aimed at Ada, Pascal and EAXHLA language syntax.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+//~#define token_limit (32)
+
+//~#include <xolatile/xtandard.h>
+//~#include <xolatile/xrena.h>
+
+static int parse_comment (const char * buffer);
+static int parse_include (const char * buffer);
+static int parse_use (const char * buffer);
+static int parse_alias (const char * buffer);
+static int parse_macro (const char * buffer);
+static int parse_scope (const char * buffer);
+static int parse_unscope (const char * buffer);
+static int parse_default (const char * buffer);
+static void parse_buffer (const char * buffer, int limit);
+
+enum {
+ token_comment, token_include, token_use, token_alias, token_macro, token_scope, token_unscope, token_default
+};
+
+static const char * token_key [token_default] = {
+ "---", "include ", "use ", "alias ", "macro ", "scope ", "unscope "
+};
+
+static int (* parse_key [token_default + 1]) (const char * buffer) = {
+ parse_comment, parse_include, parse_use, parse_alias, parse_macro, parse_scope, parse_unscope, parse_default
+};
+
+static int token_count = 0;
+
+static struct {
+ const char * data;
+ int size;
+ int type;
+} * token_array [token_limit],
+ * token_value [token_limit];
+
+static int parse_default (const char * buffer) {
+ int select;
+
+ for (select = 0; select < token_count; ++select) {
+ if (string_compare_limit (buffer, token_array [select]->data, token_array [select]->size) == true) {
+ if (token_array [select]->type == token_alias) {
+ if (character_is_separator (buffer [-1]) == false) continue;
+ if (character_is_separator (buffer [token_array [select]->size]) == false) continue;
+
+ output (token_value [select]->data, token_value [select]->size);
+
+ return (token_array [select]->size);
+ }
+
+ if (token_array [select]->type == token_macro) {
+ if (character_is_separator (buffer [-1]) == false) continue;
+ if (character_is_separator (buffer [token_array [select]->size]) == false) continue;
+
+ parse_buffer (token_value [select]->data, token_value [select]->size);
+
+ return (token_array [select]->size);
+ }
+ }
+ }
+
+ output (buffer, 1);
+
+ return (1);
+}
+
+static int parse_comment (const char * buffer) {
+ int offset;
+
+ for (offset = 3; buffer [offset] != '\0'; ++offset) {
+ if (buffer [offset] == '\n') break;
+ }
+
+ return (offset + 1);
+}
+
+static int parse_use (const char * buffer) {
+ int offset;
+ int length;
+
+ for (offset = 4; (buffer [offset] != '\0') && (character_is_blank (buffer [offset]) == true); ++offset);
+
+ ++token_count;
+
+ token_array [token_count - 1] = arena_add (sizeof (* * token_array));
+
+ token_array [token_count - 1]->data = & buffer [offset];
+ token_array [token_count - 1]->type = token_use;
+
+ for (length = 0; (buffer [offset + length] != '\0') && (character_is_blank (buffer [offset + length]) == false); ++length);
+
+ token_array [token_count - 1]->size = length;
+
+ return (offset + length + 1);
+}
+
+static int parse_include (const char * buffer) {
+ int length;
+ int offset;
+ char * data;
+
+ for (offset = 8; (buffer [offset] != '\0') && (character_is_blank (buffer [offset]) == true); ++offset);
+
+ fatal_failure (buffer [offset] != '"', "parse_include: Not a string.");
+
+ ++token_count;
+
+ token_array [token_count - 1] = arena_add (sizeof (* * token_array));
+
+ token_array [token_count - 1]->data = & buffer [offset + 1];
+ token_array [token_count - 1]->type = token_include;
+
+ for (length = 1; (buffer [offset + length] != '\0') && (buffer [offset + length] != '"'); ++length);
+
+ token_array [token_count - 1]->size = length - 1;
+
+ data = arena_add_file (token_array [token_count - 1]->data, token_array [token_count - 1]->size);
+
+ parse_buffer (data, -1);
+
+ return (offset + length + 1);
+}
+
+static int parse_alias (const char * buffer) {
+ int offset;
+ int length;
+
+ for (offset = 6; (buffer [offset] != '\0') && (character_is_blank (buffer [offset]) == true); ++offset);
+
+ ++token_count;
+
+ token_array [token_count - 1] = arena_add (sizeof (* * token_array));
+ token_value [token_count - 1] = arena_add (sizeof (* * token_value));
+
+ token_array [token_count - 1]->data = & buffer [offset];
+ token_array [token_count - 1]->type = token_alias;
+
+ for (length = 0; (buffer [offset + length] != '\0') && (character_is_blank (buffer [offset + length]) == false); ++length);
+
+ token_array [token_count - 1]->size = length;
+
+ for (offset += length; (buffer [offset] != '\0') && (character_is_blank (buffer [offset]) == true); ++offset);
+
+ token_value [token_count - 1]->data = & buffer [offset];
+ token_value [token_count - 1]->type = token_alias;
+
+ for (length = 0; (buffer [offset + length] != '\0') && (character_is_blank (buffer [offset + length]) == false); ++length);
+
+ token_value [token_count - 1]->size = length;
+
+ return (offset + length + 1);
+}
+
+static int parse_macro (const char * buffer) {
+ int offset;
+ int length;
+
+ for (offset = 6; (buffer [offset] != '\0') && (character_is_blank (buffer [offset]) == true); ++offset);
+
+ ++token_count;
+
+ token_array [token_count - 1] = arena_add (sizeof (* * token_array));
+ token_value [token_count - 1] = arena_add (sizeof (* * token_value));
+
+ token_array [token_count - 1]->data = & buffer [offset];
+ token_array [token_count - 1]->type = token_macro;
+
+ for (length = 0; (buffer [offset + length] != '\0') && (character_is_blank (buffer [offset + length]) == false); ++length);
+
+ token_array [token_count - 1]->size = length;
+
+ for (offset += length; (buffer [offset] != '\0') && (character_is_blank (buffer [offset]) == true); ++offset);
+
+ token_value [token_count - 1]->data = & buffer [offset];
+ token_value [token_count - 1]->type = token_macro;
+
+ for (length = 0; buffer [offset + length] != '\0'; ++length) {
+ if (string_compare_limit (& buffer [offset + length], "end macro", 9) == true) {
+ break;
+ }
+ }
+
+ token_value [token_count - 1]->size = length;
+
+ return (offset + length + 9 + 1);
+}
+
+static int parse_scope (const char * buffer) {
+ int offset;
+ int length;
+ int select;
+
+ for (offset = 6; (buffer [offset] != '\0') && (character_is_blank (buffer [offset]) == true); ++offset);
+
+ for (length = 0; (buffer [offset + length] != '\0') && (character_is_blank (buffer [offset + length]) == false); ++length);
+
+ for (select = 0; select < token_count; ++select) {
+ if ((string_compare_limit (token_array [select]->data, & buffer [offset], length) == true) && (token_array [select]->type == token_use)) {
+ for (; buffer [offset + length] != '\0'; ++length) {
+ if (string_compare_limit (& buffer [offset + length], "end scope", 9) == true) {
+ return (offset + length + 9 + 1);
+ }
+ }
+ }
+ }
+
+ return (offset + length + 1);
+}
+
+static int parse_unscope (const char * buffer) {
+ int offset;
+ int length;
+ int select;
+
+ for (offset = 8; (buffer [offset] != '\0') && (character_is_blank (buffer [offset]) == true); ++offset);
+
+ for (length = 0; (buffer [offset + length] != '\0') && (character_is_blank (buffer [offset + length]) == false); ++length);
+
+ for (select = 0; select < token_count; ++select) {
+ if ((string_compare_limit (token_array [select]->data, & buffer [offset], length) == true) && (token_array [select]->type == token_use)) {
+ return (offset + length + 1);
+ }
+ }
+
+ for (; buffer [offset + length] != '\0'; ++length) {
+ if (string_compare_limit (& buffer [offset + length], "end unscope", 11) == true) {
+ return (offset + length + 11 + 1);
+ }
+ }
+
+ return (offset + length + 1);
+}
+
+static void parse_buffer (const char * buffer, int limit) {
+ int offset;
+ int length;
+ int select;
+
+ for (length = offset = 0; (buffer [offset] != '\0') && (offset != limit); offset += length) {
+ for (select = 0; select < token_default; ++select) {
+ length = string_length (token_key [select]);
+ if (string_compare_limit (& buffer [offset], token_key [select], length) == true) {
+ break;
+ }
+ }
+
+ if (string_compare_limit (& buffer [offset], "end macro", 9) == true) {
+ length = 9;
+ continue;
+ }
+
+ if (string_compare_limit (& buffer [offset], "end scope", 9) == true) {
+ length = 9;
+ continue;
+ }
+
+ if (string_compare_limit (& buffer [offset], "end unscope", 11) == true) {
+ length = 11;
+ continue;
+ }
+
+ length = parse_key [select] (& buffer [offset]);
+ }
+}
+
+//~int main (int argc, char * * argv) {
+ //~int offset;
+ //~char * buffer;
+
+ //~if (argc != 2) return (2);
+
+ //~buffer = arena_add_file (argv [1], string_length (argv [1]));
+
+ //~parse_buffer (buffer, -1);
+
+ //~for (offset = 0; offset < token_count; ++offset) {
+ //~print ("/6entity %s:: %i == ", token_key [token_array [offset]->type], token_array [offset]->size);
+ //~output (token_array [offset]->data, token_array [offset]->size);
+ //~if ((token_array [offset]->type == token_alias) || (token_array [offset]->type == token_macro)) {
+ //~print (" -> ");
+ //~output (token_value [offset]->data, token_value [offset]->size);
+ //~}
+ //~print ("/-\n");
+ //~}
+
+ //~return (log_success);
+//~}
--- /dev/null
+/// __ ___ __ ___ ___ ___
+/// \ \/ / '__/ _ \/ __/ __|
+/// > <| | | (_) \__ \__ \
+/// /_/\_\_| \___/|___/___/
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xross - Even I don't know what this is, my suggestion is to never use it...
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+typedef enum {
+ cross_window_fullscreen = 0x1,
+ cross_window_transparent = 0x2,
+ cross_window_resizable = 0x4,
+ cross_window_decorated = 0x8
+} cross_window_flag;
+
+#ifdef use_raptor_renderer
+
+#define cross_structure raptor_structure
+#define cross_initialize raptor_initialize
+#define cross_deinitialize raptor_deinitialize
+#define cross_sprite_raw_import raptor_sprite_raw_import
+#define cross_font_raw_import raptor_font_raw_import
+#define cross_sprite_import raptor_sprite_import
+#define cross_font_import raptor_font_import
+#define cross_sprite_width raptor_sprite_width
+#define cross_sprite_height raptor_sprite_height
+#define cross_character_width raptor_character_width
+#define cross_character_height raptor_character_height
+#define cross_string_width raptor_string_width
+#define cross_string_height raptor_string_height
+#define cross_center_x raptor_center_x
+#define cross_center_y raptor_center_y
+#define cross_cursor_inside raptor_cursor_inside
+#define cross_cursor_left_click raptor_cursor_left_click
+#define cross_cursor_right_click raptor_cursor_right_click
+#define cross_configure raptor_configure
+#define cross_render_base raptor_render_base
+#define cross_render_rectangle raptor_render_rectangle
+#define cross_render_sprite raptor_render_sprite
+#define cross_render_sprite_scale raptor_render_sprite_scale
+#define cross_render_sprite_crop raptor_render_sprite_crop
+#define cross_render_sprite_colour raptor_render_sprite_colour
+#define cross_render_sprite_crop_colour raptor_render_sprite_crop_colour
+#define cross_render_sprite_flip raptor_render_sprite_flip
+#define cross_render_sprite_animate raptor_render_sprite_animate
+#define cross_render_character raptor_render_character
+#define cross_render_string raptor_render_string
+#define cross_render_framerate raptor_render_framerate
+#define cross_synchronize raptor_synchronize
+#define cross_render_rectangle_vertical_gradient raptor_render_rectangle_vertical_gradient
+
+#include "xaptor.h"
+
+#endif
+
+#ifdef use_common_renderer
+
+#define cross_structure common_structure
+#define cross_font_width common_font_width
+#define cross_font_height common_font_height
+#define cross_font_tabulator common_font_tabulator
+#define cross_gameplay_framerate common_gameplay_framerate
+#define cross_animation_framerate common_animation_framerate
+#define cross_center_x common_center_x
+#define cross_center_y common_center_y
+#define cross_cursor_inside common_cursor_inside
+#define cross_cursor_left_click common_cursor_left_click
+#define cross_cursor_right_click common_cursor_right_click
+#define cross_sprite_raw_import common_sprite_raw_import
+#define cross_font_raw_import common_font_raw_import
+#define cross_sprite_import common_sprite_import
+#define cross_font_import common_font_import
+#define cross_sprite_width common_sprite_width
+#define cross_sprite_height common_sprite_height
+#define cross_initialize common_initialize
+#define cross_deinitialize common_deinitialize
+#define cross_configure common_configure
+#define cross_synchronize common_synchronize
+#define cross_render_base common_render_base
+#define cross_render_rectangle common_render_rectangle
+#define cross_render_rectangle_gradient_v common_render_rectangle_gradient_v
+#define cross_render_rectangle_gradient_h common_render_rectangle_gradient_h
+#define cross_render_sprite common_render_sprite
+#define cross_render_sprite_crop common_render_sprite_crop
+#define cross_render_sprite_colour common_render_sprite_colour
+#define cross_render_sprite_crop_colour common_render_sprite_crop_colour
+#define cross_render_sprite_flip common_render_sprite_flip
+#define cross_render_sprite_animate common_render_sprite_animate
+#define cross_render_sprite_preview common_render_sprite_preview
+#define cross_render_sprite_control common_render_sprite_control
+#define cross_render_string_width common_render_string_width
+#define cross_render_string common_render_string
+
+#include "xommon.h"
+
+#endif
+
+#ifdef use_opengl_renderer
+
+#define cross_structure opengl_structure
+#define cross_font_width opengl_font_width
+#define cross_font_height opengl_font_height
+#define cross_font_tabulator opengl_font_tabulator
+#define cross_gameplay_framerate opengl_gameplay_framerate
+#define cross_animation_framerate opengl_animation_framerate
+#define cross_center_x opengl_center_x
+#define cross_center_y opengl_center_y
+#define cross_cursor_inside opengl_cursor_inside
+#define cross_cursor_left_click opengl_cursor_left_click
+#define cross_cursor_right_click opengl_cursor_right_click
+#define cross_sprite_raw_import opengl_sprite_raw_import
+#define cross_font_raw_import opengl_font_raw_import
+#define cross_sprite_import opengl_sprite_import
+#define cross_font_import opengl_font_import
+#define cross_sprite_width opengl_sprite_width
+#define cross_sprite_height opengl_sprite_height
+#define cross_initialize opengl_initialize
+#define cross_deinitialize opengl_deinitialize
+#define cross_configure opengl_configure
+#define cross_synchronize opengl_synchronize
+#define cross_render_base opengl_render_base
+#define cross_render_rectangle opengl_render_rectangle
+#define cross_render_rectangle_gradient_v opengl_render_rectangle_gradient_v
+#define cross_render_rectangle_gradient_h opengl_render_rectangle_gradient_h
+#define cross_render_sprite opengl_render_sprite
+#define cross_render_sprite_crop opengl_render_sprite_crop
+#define cross_render_sprite_colour opengl_render_sprite_colour
+#define cross_render_sprite_crop_colour opengl_render_sprite_crop_colour
+#define cross_render_sprite_flip opengl_render_sprite_flip
+#define cross_render_sprite_animate opengl_render_sprite_animate
+#define cross_render_sprite_preview opengl_render_sprite_preview
+#define cross_render_sprite_control opengl_render_sprite_control
+#define cross_render_character opengl_render_character
+#define cross_render_string_width opengl_render_string_width
+#define cross_render_string opengl_render_string
+
+#include "xpengl.h"
+
+#endif
+
+#ifdef use_vulkan_renderer
+
+#define cross_structure vulkan_structure
+#define cross_font_width vulkan_font_width
+#define cross_font_height vulkan_font_height
+#define cross_font_tabulator vulkan_font_tabulator
+#define cross_gameplay_framerate vulkan_gameplay_framerate
+#define cross_animation_framerate vulkan_animation_framerate
+#define cross_center_x vulkan_center_x
+#define cross_center_y vulkan_center_y
+#define cross_cursor_inside vulkan_cursor_inside
+#define cross_cursor_left_click vulkan_cursor_left_click
+#define cross_cursor_right_click vulkan_cursor_right_click
+#define cross_sprite_raw_import vulkan_sprite_raw_import
+#define cross_font_raw_import vulkan_font_raw_import
+#define cross_sprite_import vulkan_sprite_import
+#define cross_font_import vulkan_font_import
+#define cross_sprite_width vulkan_sprite_width
+#define cross_sprite_height vulkan_sprite_height
+#define cross_initialize vulkan_initialize
+#define cross_deinitialize vulkan_deinitialize
+#define cross_configure vulkan_configure
+#define cross_synchronize vulkan_synchronize
+#define cross_render_base vulkan_render_base
+#define cross_render_rectangle vulkan_render_rectangle
+#define cross_render_rectangle_gradient_v vulkan_render_rectangle_gradient_v
+#define cross_render_rectangle_gradient_h vulkan_render_rectangle_gradient_h
+#define cross_render_sprite vulkan_render_sprite
+#define cross_render_sprite_crop vulkan_render_sprite_crop
+#define cross_render_sprite_colour vulkan_render_sprite_colour
+#define cross_render_sprite_crop_colour vulkan_render_sprite_crop_colour
+#define cross_render_sprite_flip vulkan_render_sprite_flip
+#define cross_render_sprite_animate vulkan_render_sprite_animate
+#define cross_render_sprite_preview vulkan_render_sprite_preview
+#define cross_render_sprite_control vulkan_render_sprite_control
+#define cross_render_character vulkan_render_character
+#define cross_render_string_width vulkan_render_string_width
+#define cross_render_string vulkan_render_string
+
+#include "xulkan.h"
+
+#endif
--- /dev/null
+#include <xolatile/xtandard.h>
+
+static void echo_base (int character, int base, int colour, int effect) {
+ print ("/0 | /-");
+
+ echo_colour (colour, effect);
+
+ if (base == 2) {
+ echo (format_to_string (character, 0, base, 7, '0'));
+ } else if (base == 8) {
+ echo (format_to_string (character, 0, base, 3, '0'));
+ } else if (base == 16) {
+ echo (format_to_string (character, 0, base, 2, '0'));
+ } else {
+ echo (format_to_string (character, 0, base, 3, ' '));
+ }
+
+ echo_cancel ();
+}
+
+static void echo_code (int character) {
+ const char * code [] = {
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
+ " "
+ };
+
+ if (character == 127) {
+ print ("/0 | /4DEL/-");
+ } else if (character_is_visible (character) == false) {
+ print ("/0 | /4%s/-", code [character]);
+ if (string_length (code [character]) == 2) {
+ echo (" ");
+ }
+ } else {
+ print ("/0 | /4%c /-", character);
+ }
+}
+
+static void echo_name (int character) {
+ const char * name [] = {
+ "Null", "Start of heading", "Start of text", "End of text",
+ "End of transmission", "Enquiry", "Acknowledge", "Bell",
+ "Backspace", "Horizontal tab", "Line feed", "Vertical tab",
+ "Form feed", "Carriage return", "Shift out", "Shift in",
+ "Data link escape", "Device control 1", "Device control 2", "Device control 3",
+ "Device control 4", "Negative acknowledge", "Synchronous idle", "End transmission block",
+ "Cancel", "End of medium", "Substitute", "Escape",
+ "File separator", "Group separator", "Record separator", "Unit separator",
+ "Space", "Exclamation mark", "Speech mark", "Number sign",
+ "Dollar sign", "Percent", "Ampersand", "Quote",
+ "Open parenthesis", "Close parenthesis", "Asterisk", "Plus",
+ "Comma", "Minus", "Period", "Slash",
+ "Zero", "One", "Two", "Three",
+ "Four", "Five", "Six", "Seven",
+ "Eight", "Nine", "Colon", "Semicolon",
+ "Open angled bracket", "Equal", "Close angled bracket", "Question mark",
+ "At sign", "Uppercase A", "Uppercase B", "Uppercase C",
+ "Uppercase D", "Uppercase E", "Uppercase F", "Uppercase G",
+ "Uppercase H", "Uppercase I", "Uppercase J", "Uppercase K",
+ "Uppercase L", "Uppercase M", "Uppercase N", "Uppercase O",
+ "Uppercase P", "Uppercase Q", "Uppercase R", "Uppercase S",
+ "Uppercase T", "Uppercase U", "Uppercase V", "Uppercase W",
+ "Uppercase X", "Uppercase Y", "Uppercase Z", "Opening bracket",
+ "Backslash", "Closing bracket", "Caret", "Underscore",
+ "Grave", "Lowercase a", "Lowercase b", "Lowercase c",
+ "Lowercase d", "Lowercase e", "Lowercase f", "Lowercase g",
+ "Lowercase h", "Lowercase i", "Lowercase j", "Lowercase k",
+ "Lowercase l", "Lowercase m", "Lowercase n", "Lowercase o",
+ "Lowercase p", "Lowercase q", "Lowercase r", "Lowercase s",
+ "Lowercase t", "Lowercase u", "Lowercase v", "Lowercase w",
+ "Lowercase x", "Lowercase y", "Lowercase z", "Opening brace",
+ "Vertical bar", "Closing brace", "Tilde", "Delete"
+ };
+
+ print ("/0 | /5%s/-", name [character]);
+
+ output (" ", 24 - string_length (name [character]));
+}
+
+int main (void) {
+ int character;
+
+ for (character = 0; character < 128; ++character) {
+ echo_base (character, 2, colour_white, effect_normal);
+ echo_base (character, 8, colour_cyan, effect_normal);
+ echo_base (character, 10, colour_cyan, effect_italic);
+ echo_base (character, 16, colour_cyan, effect_bold);
+
+ echo_code (character);
+ echo_name (character);
+
+ if (character % 2 != 0) {
+ echo ("\n");
+ }
+ }
+
+ return (log_success);
+}
--- /dev/null
+/// _ _ _
+/// | | | | | |
+/// __ _| |_ __ _ _ __ __| | __ _ _ __ __| |
+/// \ \/ / __/ _` | '_ \ / _` |/ _` | '__/ _` |
+/// > <| || (_| | | | | (_| | (_| | | | (_| |
+/// /_/\_\\__\__,_|_| |_|\__,_|\__,_|_| \__,_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xtandard - Tiny, safe and somewhat sane unity header for what GNU/Linux already provides.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+#define _GNU_SOURCE
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <dirent.h>
+
+#define null ((void *) 0)
+
+#define standard_input (STDIN_FILENO)
+#define standard_output (STDOUT_FILENO)
+#define standard_error (STDERR_FILENO)
+
+#define file_flag_read (O_RDONLY)
+#define file_flag_write (O_WRONLY)
+#define file_flag_edit (O_RDWR)
+#define file_flag_create (O_CREAT)
+#define file_flag_append (O_APPEND)
+#define file_flag_truncate (O_TRUNC)
+
+#define file_seek_current (SEEK_CUR)
+#define file_seek_set (SEEK_SET)
+#define file_seek_end (SEEK_END)
+
+#define echo(text) output ((text), sizeof ((text)) - 1)
+
+#define maximum(x, y) (((x) > (y)) ? (x) : (y))
+#define minimum(x, y) (((x) < (y)) ? (x) : (y))
+
+#define array_length(array) (sizeof ((array)) / sizeof (* (array)))
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+typedef char pstring [256];
+
+typedef enum {
+ false,
+ true
+} bool;
+
+typedef enum {
+ log_success, log_warning, log_failure, log_comment,
+ log_count
+} log_enumeration;
+
+typedef enum {
+ file_type_c_source, file_type_c_header, file_type_ada_sexy_body, file_type_ada_specification,
+ file_type_cpp_source, file_type_cpp_header, file_type_fortran_90_source, file_type_fortran_90_module,
+ file_type_pascal_source, file_type_d_source, file_type_go_source, file_type_jai_source,
+ file_type_assembly, file_type_eax_assembly, file_type_gnu_assembly, file_type_flat_assembly,
+ file_type_haskell_script, file_type_perl_script, file_type_cube_script, file_type_lua_script,
+ file_type_shell_script, file_type_python_script, file_type_tcl_script, file_type_forth_source,
+ file_type_text, file_type_markdown, file_type_html, file_type_glsl,
+ file_type_xrocessor, file_type_xhla, file_type_xcript, file_type_xocument,
+ file_type_xiri, file_type_xofya, file_type_xienna, file_type_xenka,
+ file_type_xiyagi, file_type_xoule, file_type_xikoku, file_type_xdo,
+ file_type_png_image, file_type_jxl_image, file_type_jpg_image, file_type_tga_image,
+ file_type_wav_sound, file_type_ogg_sound, file_type_flac_sound, file_type_mp3_sound,
+ file_type_obj_model, file_type_iqm_model, file_type_md5_model, file_type_ply_model,
+ file_type_elf_object, file_type_spir_v_bytecode,
+ file_type_count
+} file_type_enumeration;
+
+typedef enum {
+ effect_normal, effect_bold, effect_italic, effect_undefined_code,
+ effect_underline, effect_blink, effect_reverse, effect_invisible_text,
+ effect_count
+} effect_enumeration;
+
+typedef enum {
+ colour_grey, colour_red, colour_green, colour_yellow,
+ colour_blue, colour_pink, colour_cyan, colour_white,
+ colour_count
+} colour_enumeration;
+
+typedef enum {
+ character_null, character_start_header, character_start_text, character_end_text,
+ character_end_transmission, character_enquiry, character_acknowledge, character_bell,
+ character_backspace, character_tab_horizontal, character_line_feed, character_tab_vertical,
+ character_form_feed, character_carriage_return, character_shift_out, character_shift_in,
+ character_data_link_escape, character_device_control_1, character_device_control_2, character_device_control_3,
+ character_device_control_4, character_not_acknowledge, character_synchronous_idle, character_end_transmission_block,
+ character_cancel, character_end_medium, character_substitute, character_escape,
+ character_file_separator, character_group_separator, character_record_separator, character_unit_separator
+} character_enumeration;
+
+typedef enum {
+ cursor_none,
+ cursor_left, cursor_middle, cursor_right,
+ cursor_wheel_up, cursor_wheel_down,
+ cursor_count
+} cursor_enumeration;
+
+typedef enum {
+ signal_none,
+ signal_a, signal_b, signal_c, signal_d,
+ signal_e, signal_f, signal_g, signal_h,
+ signal_i, signal_j, signal_k, signal_l,
+ signal_m, signal_n, signal_o, signal_p,
+ signal_q, signal_r, signal_s, signal_t,
+ signal_u, signal_v, signal_w, signal_x,
+ signal_y, signal_z, signal_0, signal_1,
+ signal_2, signal_3, signal_4, signal_5,
+ signal_6, signal_7, signal_8, signal_9,
+ signal_escape, signal_tabulator, signal_return, signal_new_line,
+ signal_slash, signal_backslash, signal_semicolon, signal_backquote,
+ signal_space, signal_backspace, signal_dot, signal_comma,
+ signal_cite, signal_caps_lock, signal_minus, signal_equal,
+ signal_left_bracket, signal_right_bracket, signal_left_control, signal_right_control,
+ signal_left_shift, signal_right_shift, signal_left_alt, signal_right_alt,
+ signal_f1, signal_f2, signal_f3, signal_f4,
+ signal_f5, signal_f6, signal_f7, signal_f8,
+ signal_f9, signal_f10, signal_f11, signal_f12,
+ signal_arrow_up, signal_arrow_down, signal_arrow_left, signal_arrow_right,
+ signal_num_lock, signal_pause_break, signal_insert, signal_home,
+ signal_page_up, signal_delete, signal_end, signal_page_down,
+ signal_key_add, signal_key_subtract, signal_key_multiply, signal_key_divide,
+ signal_key_enter, signal_key_dot, signal_key_0, signal_key_1,
+ signal_key_2, signal_key_3, signal_key_4, signal_key_5,
+ signal_key_6, signal_key_7, signal_key_8, signal_key_9,
+ signal_count
+} signal_enumeration;
+
+static const char * cursor_name [cursor_count] = {
+ "---",
+ "Left button", "Middle button", "Right button",
+ "Scroll up", "Scroll down"
+
+};
+
+static const char * signal_name [signal_count] = {
+ "---",
+ "A", "B", "C", "D",
+ "E", "F", "G", "H",
+ "I", "J", "K", "L",
+ "M", "N", "O", "P",
+ "Q", "R", "S", "T",
+ "U", "V", "W", "X",
+ "Y", "Z", "0", "1",
+ "2", "3", "4", "5",
+ "6", "7", "8", "9",
+ "Escape", "Tabulator", "Return", "New line",
+ "Slash", "Backslash", "Semicolon", "Backquote",
+ "Space", "Backspace", "Dot", "Comma",
+ "Cite", "Caps lock", "Minus", "Equal",
+ "Left bracket", "Right bracket", "Left control", "Right control",
+ "Left shift", "Right shift", "Left alt", "Right alt",
+ "F1", "F2", "F3", "F4",
+ "F5", "F6", "F7", "F8",
+ "F9", "F10", "F11", "F12",
+ "Arrow up", "Arrow down", "Arrow left", "Arrow right",
+ "Num lock", "Pause break", "Insert", "Home",
+ "Page up", "Delete", "End", "Page down",
+ "Key add", "Key subtract", "Key multiply", "Key divide",
+ "Key enter", "Key dot", "Key 0", "Key 1",
+ "Key 2", "Key 3", "Key 4", "Key 5",
+ "Key 6", "Key 7", "Key 8", "Key 9"
+};
+
+static void randomize_seed_by_time (void) {
+ srand ((uint) time (null));
+}
+
+static int randomize (int from, int to) {
+ return (rand () % (to - from + 1) + from);
+}
+
+static uint urandomize (uint from, uint to) {
+ return ((uint) rand () % (to - from + 1) + from);
+}
+
+static float frandomize (float from, float to) {
+ return (((float) rand () / (float) RAND_MAX) * (to - from) + from);
+}
+
+static int upper_bound (int a, int b) {
+ return ((a > b) ? a : b);
+}
+
+static int lower_bound (int a, int b) {
+ return ((a < b) ? a : b);
+}
+
+static void input (void * data, ulong size) {
+ read (standard_input, data, size);
+}
+
+static void output (const void * data, ulong size) {
+ write (standard_output, data, size);
+}
+
+static void clean_up (void (* procedure) (void)) {
+ atexit (procedure);
+}
+
+#ifdef use_fatal_failure
+static void fatal_failure (bool condition, const char * message) {
+ if (condition == true) {
+ echo ("[\x1b[1;31m FATAL \x1b[0m] ");
+
+ for (int index = 0; message [index] != '\0'; ++index) {
+ output (& message [index], 1);
+ }
+
+ echo ("\n");
+
+ exit (log_failure);
+ }
+}
+#else
+#define fatal_failure(...)
+#endif
+
+static void execute (const char * command) {
+ int status = 0;
+
+ system (command);
+
+ fatal_failure (status != 0, "execute: System returned an error code.");
+}
+
+static uint tick_tock (void) {
+ return ((uint) clock ());
+}
+
+static ulong nano_time (void) {
+ struct timespec time = { 0 };
+
+ ulong result = 0;
+
+ clock_gettime (CLOCK_MONOTONIC, & time);
+
+ result = 1000000000ul * (ulong) time.tv_sec + (ulong) time.tv_nsec;
+
+ return (result);
+}
+
+static void nano_wait (ulong time) {
+ struct timespec wait = {
+ time / 1000000000,
+ time % 1000000000
+ };
+
+ while (nanosleep (& wait, null)) continue;
+}
+
+static float normal_r (uint colour) { return ((float) ((colour >> 24) & 0xff) / 255.0f); }
+static float normal_g (uint colour) { return ((float) ((colour >> 16) & 0xff) / 255.0f); }
+static float normal_b (uint colour) { return ((float) ((colour >> 8) & 0xff) / 255.0f); }
+static float normal_a (uint colour) { return ((float) ((colour >> 0) & 0xff) / 255.0f); }
+
+static uint channel_r (uint colour) { return ((colour >> 24) & 0xff); }
+static uint channel_g (uint colour) { return ((colour >> 16) & 0xff); }
+static uint channel_b (uint colour) { return ((colour >> 8) & 0xff); }
+static uint channel_a (uint colour) { return ((colour >> 0) & 0xff); }
+
+static uint colour_channel_reverse (uint colour) {
+ uint r = channel_r (colour);
+ uint g = channel_g (colour);
+ uint b = channel_b (colour);
+ uint a = channel_a (colour);
+
+ return ((a << 24) | (b << 16) | (g << 8) | (r << 0));
+}
+
+static uint colour_linear_interpolation (uint colour_a, uint colour_b, float scale) {
+ if (scale <= 0.0f) {
+ return (colour_a);
+ }
+
+ if (scale >= 1.0f) {
+ return (colour_b);
+ }
+
+ uint r = (uint) ((1.0f - scale) * channel_r (colour_a) + scale * channel_r (colour_b));
+ uint g = (uint) ((1.0f - scale) * channel_g (colour_a) + scale * channel_g (colour_b));
+ uint b = (uint) ((1.0f - scale) * channel_b (colour_a) + scale * channel_b (colour_b));
+ uint a = (uint) ((1.0f - scale) * channel_a (colour_a) + scale * channel_a (colour_b));
+
+ return ((r << 24) | (g << 16) | (b << 8) | (a << 0));
+}
+
+static void * allocate (ulong size) {
+ char * data = null;
+
+ fatal_failure (size <= 0, "allocate: Size is equal or below zero.");
+
+ data = calloc (size, sizeof (* data));
+
+ fatal_failure (data == null, "allocate: Function 'calloc' returned null pointer.");
+
+ return (data);
+}
+
+static void * reallocate (void * data, ulong size) {
+ fatal_failure (size <= 0, "reallocate: Size is equal or below zero.");
+
+ data = realloc (data, size);
+
+ fatal_failure (data == null, "reallocate: Function 'realloc' returned null pointer.");
+
+ return (data);
+}
+
+static void * deallocate (void * data) {
+ fatal_failure (data == null, "deallocate: Data is null pointer.");
+
+ free (data);
+
+ return (null);
+}
+
+static void * record (void) {
+ char * buffer = null;
+ ulong offset = 0;
+ ulong memory = 64 * 1024;
+
+ buffer = reallocate (buffer, memory);
+
+ do {
+ if ((offset + 1) % memory == 0) {
+ buffer = reallocate (buffer, ((offset + 1) / memory + 1) * memory);
+ }
+
+ buffer [offset] = '\0';
+
+ input (& buffer [offset], sizeof (* buffer));
+
+ ++offset;
+ } while (buffer [offset - 1] != '\0');
+
+ buffer [offset - 1] = '\0';
+
+ return (buffer);
+}
+
+static bool character_compare_array (char character, const char * character_array) {
+ for (ulong index = 0; character_array [index] != '\0'; ++index) {
+ if (character == character_array [index]) {
+ return (true);
+ }
+ }
+
+ return (false);
+}
+
+static bool character_is_uppercase (char character) {
+ return ((character >= 'A') && (character <= 'Z'));
+}
+
+static bool character_is_lowercase (char character) {
+ return ((character >= 'a') && (character <= 'z'));
+}
+
+static bool character_is_digit (char character) {
+ return ((character >= '0') && (character <= '9'));
+}
+
+static bool character_is_letter (char character) {
+ return (((character >= 'A') && (character <= 'Z')) || ((character >= 'a') && (character <= 'z')));
+}
+
+static bool character_is_blank (char character) {
+ return ((character == ' ') || (character == '\t') || (character == '\r') || (character == '\n'));
+}
+
+static bool character_is_symbol (char character) {
+ return (((character >= '!') && (character <= '/')) || ((character >= ':') && (character <= '@'))
+ || ((character >= '[') && (character <= '`')) || ((character >= '{') && (character <= '~')));
+}
+
+static bool character_is_separator (char character) {
+ return ((character != '_') && ((character_is_blank (character) == true) || (character_is_symbol (character) == true)));
+}
+
+static bool character_is_identifier (char character) {
+ return ((character == '_') || (character_is_letter (character) == true) || (character_is_digit (character) == true));
+}
+
+static bool character_is_visible (char character) {
+ return ((character >= '!') && (character <= '~'));
+}
+
+static char * capitalize (char * string) {
+ fatal_failure (string == null, "capitalize: String is null pointer.");
+
+ string [0] -= (character_is_lowercase (string [0]) == true) ? ' ' : '\0';
+
+ return (string);
+}
+
+static char * uppercase (char * string) {
+ fatal_failure (string == null, "uppercase: String is null pointer.");
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ string [index] += (character_is_lowercase (string [index]) == true) ? ' ' : '\0';
+ }
+
+ return (string);
+}
+
+static char * lowercase (char * string) {
+ fatal_failure (string == null, "lowercase: String is null pointer.");
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ string [index] -= (character_is_uppercase (string [index]) == true) ? ' ' : '\0';
+ }
+
+ return (string);
+}
+
+static ulong string_length (const char * string) {
+ ulong length = 0;
+
+ fatal_failure (string == null, "string_length: String is null pointer.");
+
+ for (length = 0; string [length] != '\0'; ++length);
+
+ return (length);
+}
+
+static char * string_nullify (char * string, ulong length) {
+ fatal_failure (string == null, "string_nullify: String is null pointer.");
+ fatal_failure (length <= 0, "string_nullify: Length is equal or below zero.");
+
+ for (ulong index = 0; index < length; ++index) {
+ string [index] = '\0';
+ }
+
+ return (string);
+}
+
+static char * string_reverse_limit (char * string, ulong limit) {
+ fatal_failure (string == null, "string_reverse_limit: String is null pointer.");
+ fatal_failure (limit <= 0, "string_reverse_limit: Limit is equal or below zero.");
+
+ for (ulong index = 0; index < limit / 2; ++index) {
+ char temporary = string [index];
+
+ string [index] = string [limit - 1 - index];
+ string [limit - 1 - index] = temporary;
+ }
+
+ return (string);
+}
+
+static char * string_reverse (char * string) {
+ return (string_reverse_limit (string, string_length (string)));
+}
+
+static bool string_compare_limit (const char * string_a, const char * string_b, ulong limit) {
+ fatal_failure (string_a == null, "string_compare_limit: First source string is null pointer.");
+ fatal_failure (string_b == null, "string_compare_limit: Second source string is null pointer.");
+ fatal_failure (limit <= 0, "string_compare_limit: Limit is equal or below zero.");
+
+ for (ulong index = 0; index < limit; ++index) {
+ if (string_a [index] != string_b [index]) {
+ return (false);
+ }
+ }
+
+ return (true);
+}
+
+static bool string_compare (const char * string_a, const char * string_b) {
+ return (string_compare_limit (string_a, string_b, string_length (string_a) + 1));
+}
+
+static char * string_copy_limit (char * destination, const char * source, ulong limit) {
+ fatal_failure (destination == null, "string_copy_limit: Destination string is null pointer.");
+ fatal_failure (source == null, "string_copy_limit: Source string is null pointer.");
+ fatal_failure (limit <= 0, "string_copy_limit: Limit is equal or below zero.");
+
+ for (ulong index = 0; index < limit; ++index) {
+ destination [index] = source [index];
+ }
+
+ return (destination);
+}
+
+static char * string_copy (char * destination, const char * source) {
+ return (string_copy_limit (destination, source, string_length (source) + 1));
+}
+
+static char * string_concatenate_limit (char * destination, const char * source, ulong limit) {
+ ulong offset = string_length (destination);
+
+ fatal_failure (destination == null, "string_concatenate_limit: Destination string is null pointer.");
+ fatal_failure (source == null, "string_concatenate_limit: Source string is null pointer.");
+ fatal_failure (limit <= 0, "string_concatenate_limit: Limit is equal or below zero.");
+
+ for (ulong index = 0; index < limit; ++index) {
+ destination [offset + index] = source [index];
+ }
+
+ return (destination);
+}
+
+static char * string_concatenate (char * destination, const char * source) {
+ return (string_concatenate_limit (destination, source, string_length (source) + 1));
+}
+
+static char * string_duplicate (const char * string) {
+ char * duplicate = null;
+
+ duplicate = allocate ((string_length (string) + 1) * sizeof (* duplicate));
+
+ string_copy (duplicate, string);
+
+ return (duplicate);
+}
+
+static char * string_duplicate_limit (const char * string, uint limit) {
+ char * duplicate = null;
+
+ duplicate = allocate ((limit + 1) * sizeof (* duplicate));
+
+ string_copy_limit (duplicate, string, limit);
+
+ return (duplicate);
+}
+
+static char * string_align_left (char * string, ulong amount, char character) {
+ ulong length = string_length (string);
+
+ for (ulong offset = length; offset < amount; ++offset) {
+ string [offset] = character;
+ }
+
+ string [amount] = '\0';
+
+ return (string);
+}
+
+static void memory_nullify (void * memory, ulong size) {
+ char * cast = (char *) memory;
+
+ fatal_failure (memory == null, "memory_nullify: Memory is null pointer.");
+
+ for (ulong offset = 0; offset < size; ++offset) {
+ cast [offset] = (char) 0;
+ }
+}
+
+static int memory_compare (void * memory_0, const void * memory_1, ulong size) {
+ char * cast_0 = ( char *) memory_0;
+ const char * cast_1 = (const char *) memory_1;
+
+ fatal_failure (memory_0 == null, "memory_compare: Memory is null pointer.");
+ fatal_failure (memory_1 == null, "memory_compare: Source is null pointer.");
+
+ for (ulong offset = 0; offset < size; ++offset) {
+ if (cast_0 [offset] != cast_1 [offset]) {
+ return (false);
+ }
+ }
+
+ return (true);
+}
+
+static void memory_copy (void * destination, const void * source, ulong size) {
+ char * cast_0 = ( char *) destination;
+ const char * cast_1 = (const char *) source;
+
+ fatal_failure (destination == null, "memory_copy: Destination is null pointer.");
+ fatal_failure (source == null, "memory_copy: Source is null pointer.");
+
+ for (ulong offset = 0; offset < size; ++offset) {
+ cast_0 [offset] = cast_1 [offset];
+ }
+}
+
+static char * string_remove_extension (char * string) {
+ ulong length = string_length (string);
+
+ for (--length; string [length] != '.'; --length);
+
+ string [length] = '\0';
+
+ return (string);
+}
+
+static void echo_clear (void) {
+ echo ("\033[2J\033[H");
+}
+
+static void echo_colour (colour_enumeration colour, effect_enumeration effect) {
+ char format [8] = "\033[ ;3 m";
+
+ format [2] = (char) (effect % effect_count) + '0';
+ format [5] = (char) (colour % colour_count) + '0';
+
+ echo (format);
+}
+
+static void echo_cancel (void) {
+ echo ("\033[0m");
+}
+
+static void show_cursor (bool show) {
+ if (show == true) {
+ echo ("\033[?25h");
+ } else {
+ echo ("\033[?25l");
+ }
+}
+
+static int file_open (const char * path, int mode) {
+ fatal_failure (path == null, "file_open: File path is null pointer.");
+
+ return (open (path, mode, 0777));
+}
+
+static int file_close (int file) {
+ fatal_failure (file == -1, "file_close: Invalid file descriptor.");
+
+ close (file);
+
+ return (-1);
+}
+
+static void file_read (int file, void * data, ulong size) {
+ fatal_failure (file <= -1, "file_read: File descriptor is closed or invalid.");
+ fatal_failure (data == null, "file_read: Data is null pointer.");
+ fatal_failure (size == 0, "file_read: Size is zero.");
+
+ read (file, data, size);
+}
+
+static void file_write (int file, const void * data, ulong size) {
+ fatal_failure (file <= -1, "file_write: File descriptor is closed or invalid.");
+ fatal_failure (data == null, "file_write: Data is null pointer.");
+ fatal_failure (size == 0, "file_write: Size is zero.");
+
+ write (file, data, size);
+}
+
+static void file_echo (int file, const char * data) {
+ file_write (file, data, string_length (data));
+}
+
+static ulong file_seek (int file, int whence) {
+ fatal_failure (file == -1, "file_seek: Invalid file descriptor.");
+
+ return ((ulong) lseek (file, 0, whence));
+}
+
+static ulong file_size (const char * path) {
+ struct stat data = { 0 };
+
+ fatal_failure (path == null, "file_size: File path is null pointer.");
+
+ lstat (path, & data);
+
+ return ((ulong) data.st_size);
+}
+
+static file_type_enumeration file_type (const char * path) {
+ const char * extensions [file_type_count] = {
+ ".c", ".h", ".adb", ".ads", ".cpp", ".hpp", ".f90", ".mod",
+ ".pas", ".d", ".go", ".jai", ".asm", ".eax", ".gas", ".fasm",
+ ".hs", ".el", ".cfg", ".lua", ".sh", ".py", ".tcl", ".4th",
+ ".txt", ".md", ".html", ".glsl", ".x", ".xhla", ".xs", ".xd",
+ ".xiri", ".xofya", ".xienna", ".xenka", ".xiyagi", ".xoule", ".xikoku", ".xdo",
+ ".png", ".jxl", ".jpg", ".tga", ".wav", ".ogg", ".flac", ".mp3",
+ ".obj", ".iqm", ".md5", ".ply", ".o", ".spv"
+ };
+
+ fatal_failure (path == null, "file_type: File path is null pointer.");
+
+ for (; * path != '.'; ++path);
+
+ for (file_type_enumeration type = 0; type != file_type_count; ++type) {
+ if (string_compare (path, extensions [type])) {
+ return (type);
+ }
+ }
+
+ return (~ 0u);
+}
+
+static bool file_exists (const char * path) {
+ fatal_failure (path == null, "file_record: File path is null pointer.");
+
+ return ((access (path, F_OK) == 0) ? true : false);
+}
+
+static void file_remove (const char * path) {
+ unlink (path);
+}
+
+static void * file_record (const char * path) {
+ int file = -1;
+ ulong size = 0;
+ char * data = null;
+
+ fatal_failure (path == null, "file_record: File path is null pointer.");
+
+ file = file_open (path, file_flag_read);
+ size = file_size (path);
+ data = allocate (size);
+
+ file_read (file, data, size);
+
+ file = file_close (file);
+
+ return (data);
+}
+
+static char * file_import (const char * path) {
+ int file = -1;
+ ulong size = 0;
+ char * data = null;
+
+ fatal_failure (path == null, "file_import: File path is null pointer.");
+
+ file = file_open (path, file_flag_edit);
+ size = file_size (path) + 1;
+ data = allocate (size);
+
+ file_read (file, data, size - 1);
+
+ data [size - 1] = '\0';
+
+ file = file_close (file);
+
+ return (data);
+}
+
+static void file_export (const char * path, const char * data) {
+ int file = -1;
+
+ fatal_failure (path == null, "file_export: File path is null pointer.");
+ fatal_failure (data == null, "file_export: Data is null pointer.");
+
+ file = file_open (path, file_flag_write | file_flag_create | file_flag_truncate);
+
+ file_write (file, data, string_length (data));
+
+ file = file_close (file);
+}
+
+static void * folder_open (const char * path) {
+ DIR * folder = null;
+
+ fatal_failure (path == null, "folder_open: Folder path is null pointer.");
+
+ folder = opendir (path);
+
+ return ((void *) folder);
+}
+
+static char * folder_read (void * handle) {
+ struct dirent * file = null;
+
+ DIR * folder = (DIR *) handle;
+
+ fatal_failure (handle == null, "folder_read: Folder handle is null pointer.");
+
+ file = readdir (folder);
+
+ if (file == null) {
+ return (null);
+ } else {
+ return (file->d_name);
+ }
+}
+
+static void * folder_close (void * handle) {
+ DIR * folder = (DIR *) handle;
+
+ fatal_failure (handle == null, "folder_read: Folder handle is null pointer.");
+
+ closedir (folder);
+
+ return (null);
+}
+
+static char * * folder_create_path_list (const char * folder, uint * path_count, bool sort) {
+ void * handle = null;
+ char * * path_array = 0;
+
+ (void) sort;
+
+ fatal_failure (folder == null, "folder_create_path_list: Folder handle is null pointer.");
+ fatal_failure (path_count == null, "folder_create_path_list: Path count address is null pointer.");
+
+ handle = folder_open (folder);
+
+ for (char * path = folder_read (handle); path != null; path = folder_read (handle)) {
+ if (path [0] != '.') {
+ (* path_count) += 1;
+
+ path_array = reallocate (path_array, (* path_count) * sizeof (* path_array));
+
+ path_array [(* path_count) - 1] = allocate ((string_length (path) + 1) * sizeof (* * path_array));
+
+ string_copy (path_array [(* path_count) - 1], path);
+ }
+ }
+
+ handle = folder_close (handle);
+
+ return (path_array);
+}
+
+static char * * folder_remove_path_list (char * * path_array, uint path_count) {
+ for (uint index = 0; index < path_count; ++index) {
+ path_array [index] = deallocate (path_array [index]);
+ }
+
+ return (deallocate (path_array));
+}
+
+static char * configuration_format (const char * path) {
+ static char buffer [512] = "";
+
+ string_copy (buffer, getenv ("HOME"));
+ string_concatenate (buffer, "/.config/xolatile/");
+ string_concatenate (buffer, path);
+
+ return (buffer);
+}
+
+static bool configuration_exists (const char * path) {
+ return (file_exists (configuration_format (path)));
+}
+
+static void configuration_remove (const char * path) {
+ file_remove (configuration_format (path));
+}
+
+static char * configuration_import (const char * path) {
+ return (file_import (configuration_format (path)));
+}
+
+static void configuration_export (const char * path, const char * data) {
+ file_export (configuration_format (path), data);
+}
+
+static bool argument_compare (const char * argument, const char * short_option, const char * long_option) {
+ return ((string_compare (argument, short_option) == true) || (string_compare (argument, long_option) == true));
+}
+
+static uint string_full_width (const char * string, uint tab_width) {
+ uint width = 0;
+ uint count = 0;
+
+ do {
+ if (* string == '\t') {
+ count += tab_width;
+ } else if (* string == '\n') {
+ width = (++count > width) ? count : width;
+ count = 0;
+ } else {
+ ++count;
+ }
+ } while (* (++string) != '\0');
+
+ return (width - 1);
+}
+
+static uint string_full_height (const char * string) {
+ uint height = 0;
+
+ do {
+ if (* string == '\n') {
+ ++height;
+ }
+ } while (* (++string) != '\0');
+
+ return (height + 1);
+}
+
+static uint string_limit_to_number (const char * string, uint limit) {
+ uint number = 0;
+
+ for (uint index = 0; (string [index] != '\0') && (index < limit); ++index) {
+ number *= 10;
+ number += (uint) (string [index] - '0');
+ }
+
+ return (number);
+}
+
+static uint string_to_number (const char * string) {
+ return (string_limit_to_number (string, string_length (string)));
+}
+
+static char * number_to_string (int number) {
+ static char string [34] = "";
+
+ uint index = 0;
+ bool sign = false;
+
+ string_nullify (string, sizeof (string));
+
+ if (number == 0) {
+ string [0] = '0';
+ string [1] = '\0';
+ return (string);
+ }
+
+ if (number < 0) {
+ number *= -1;
+ sign = true;
+ } else {
+ sign = false;
+ }
+
+ for (index = 0; (number != 0) && (index < (uint) sizeof (string) - 1); ++index) {
+ string [index] = (char) (number % 10) + '0';
+ number /= 10;
+ }
+
+ if (sign == true) {
+ string [index] = '-';
+ ++index;
+ }
+
+ string [index] = '\0';
+
+ string_reverse (string);
+
+ return (string);
+}
+
+static char * format_to_string (int number, bool sign, uint base, ulong amount, char character) {
+ static char string [36];
+
+ int i;
+
+ string_nullify (string, sizeof (string));
+
+ if (number == 0) {
+ string [0] = '0';
+ string [1] = '\0';
+
+ string_align_left (string, amount, character);
+
+ return (string);
+ }
+
+ if (number < 0) {
+ number *= -1;
+ }
+
+ for (i = (string [0] == '-'); number != 0; ++i) {
+ string [i] = "0123456789ABCDEF" [number % base];
+ number /= base;
+ }
+
+ if (sign == true) {
+ string [i] = '-';
+ ++i;
+ }
+
+ string [i] = '\0';
+
+ string_reverse (string);
+
+ string_align_left (string, amount, character);
+
+ return (string);
+}
+
+static char * format (const char * base, ...) {
+ static char string [1024];
+
+ va_list list;
+
+ string_nullify (string, 1024);
+
+ va_start (list, base);
+
+ for (; * base != character_null; ++base) {
+ switch (* base) {
+ case ('%'): {
+ ++base;
+ switch (* base) {
+ case ('%'): string_concatenate (string, "%"); break;
+ case ('i'): string_concatenate (string, number_to_string (va_arg (list, int))); break;
+ case ('s'): string_concatenate (string, va_arg (list, char *)); break;
+ default: string_concatenate (string, "?"); break;
+ }
+ } break;
+ default: {
+ string_concatenate_limit (string, base, 1);
+ } break;
+ }
+ }
+
+ va_end (list);
+
+ return (string);
+}
+
+static void print (const char * format, ...) {
+ va_list list;
+
+ va_start (list, format);
+
+ for (; * format != character_null; ++format) {
+ switch (* format) {
+ case ('%'): {
+ ++format;
+ switch (* format) {
+ case ('%'): {
+ output ("%", 1);
+ } break;
+ case ('i'): {
+ char * string = number_to_string (va_arg (list, int));
+ output (string, string_length (string));
+ } break;
+ case ('t'): {
+ int toggle = (va_arg (list, int));
+ echo_colour ((toggle == true) ? colour_green : colour_red, effect_normal);
+ output ((toggle == true) ? "+" : "-", 1);
+ echo_cancel ();
+ } break;
+ case ('b'): {
+ int boolean = (va_arg (list, int));
+ output ((boolean == true) ? "true" : "false", (boolean == true) ? 4 : 5);
+ } break;
+ case ('c'): {
+ char character = (char) va_arg (list, int);
+ output (& character, 1);
+ } break;
+ case ('s'): {
+ char * string = va_arg (list, char *);
+ output (string, string_length (string));
+ } break;
+ default: {
+ output ("?", 1);
+ } break;
+ }
+ } break;
+ case ('/'): {
+ ++format;
+ switch (* format) {
+ case ('/'): echo ("/"); break;
+ case ('s'): echo ("[\x1b[1;32mSuccess\x1b[0m]"); break;
+ case ('f'): echo ("[\x1b[1;31mFailure\x1b[0m]"); break;
+ case ('w'): echo ("[\x1b[1;33mWarning\x1b[0m]"); break;
+ case ('c'): echo ("[\x1b[1;30mComment\x1b[0m]"); break;
+ case ('A'): echo ("\x1b[0m"); break;
+ case ('B'): echo ("\x1b[1m"); break;
+ case ('C'): echo ("\x1b[2m"); break;
+ case ('D'): echo ("\x1b[3m"); break;
+ case ('E'): echo ("\x1b[4m"); break;
+ case ('F'): echo ("\x1b[5m"); break;
+ case ('G'): echo ("\x1b[6m"); break;
+ case ('H'): echo ("\x1b[7m"); break;
+ case ('0'): echo ("\x1b[30m"); break;
+ case ('1'): echo ("\x1b[31m"); break;
+ case ('2'): echo ("\x1b[32m"); break;
+ case ('3'): echo ("\x1b[33m"); break;
+ case ('4'): echo ("\x1b[34m"); break;
+ case ('5'): echo ("\x1b[35m"); break;
+ case ('6'): echo ("\x1b[36m"); break;
+ case ('7'): echo ("\x1b[37m"); break;
+ case ('-'): echo ("\x1b[0m"); break;
+ default: echo ("?"); break;
+ }
+ } break;
+ default: {
+ output (format, 1);
+ } break;
+ }
+ }
+
+ va_end (list);
+}
+
+static void uint_exchange (uint * a, uint * b) {
+ uint c = * a;
+
+ * a = * b;
+ * b = c;
+}
+
+static void float_exchange (float * a, float * b) {
+ float c = * a;
+
+ * a = * b;
+ * b = c;
+}
+
+#ifdef use_mathematics
+
+#include <math.h>
+
+#define pi (3.14159265f)
+
+static float sign (float x) { return ((x > 0.0f) ? +1.0f : -1.0f); }
+
+static float square_root (float x) { return (sqrtf (x)); }
+static float cube_root (float x) { return (cbrtf (x)); }
+
+static float sine (float x) { return (sinf (x)); }
+static float cosine (float x) { return (cosf (x)); }
+static float tangent (float x) { return (tanf (x)); }
+
+static float arc_sine (float x) { return (asinf (x)); }
+static float arc_cosine (float x) { return (acosf (x)); }
+static float arc_tangent (float x) { return (atanf (x)); }
+
+static float cosecant (float x) { return (1.0f / sinf (x)); }
+static float secant (float x) { return (1.0f / cosf (x)); }
+static float cotangent (float x) { return (1.0f / tanf (x)); }
+
+#endif
--- /dev/null
+/// _
+/// __ ___ _(_)
+/// \ \/ / | | | |
+/// > <| |_| | |
+/// /_/\_\\__,_|_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xui - Tiny GUI unity header, I'm not sure if it's immediate or not... Probably not.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+typedef enum {
+ ui_window_left, ui_window_right, ui_window_upper, ui_window_lower,
+ ui_window_upper_left, ui_window_upper_right, ui_window_lower_left, ui_window_lower_right,
+ ui_frame_left, ui_frame_right, ui_frame_upper, ui_frame_lower,
+ ui_frame_upper_left, ui_frame_upper_right, ui_frame_lower_left, ui_frame_lower_right,
+ ui_status_left, ui_status_right, ui_status_upper, ui_status_lower,
+ ui_status_upper_left, ui_status_upper_right, ui_status_lower_left, ui_status_lower_right,
+ ui_status_middle,
+ ui_menu_left, ui_menu_right, ui_menu_upper, ui_menu_lower,
+ ui_menu_upper_left, ui_menu_upper_right, ui_menu_lower_left, ui_menu_lower_right,
+ ui_menu_middle,
+ ui_button_left, ui_button_right, ui_button_upper, ui_button_lower,
+ ui_button_upper_left, ui_button_upper_right, ui_button_lower_left, ui_button_lower_right,
+ ui_button_middle,
+ ui_fill_bar_left, ui_fill_bar_middle, ui_fill_bar_right, ui_fill_bar_base,
+ ui_tiny_fill_bar_middle, ui_tiny_fill_bar_left, ui_tiny_fill_bar_right, ui_tiny_fill_middle,
+ ui_check_box_off, ui_check_box_on,
+ ui_end_turn_button,
+ ui_icon_frame, ui_overicon_frame, ui_ubericon_frame,
+ ui_scroll_bar_lower, ui_scroll_bar_middle, ui_scroll_bar_upper, ui_scroll_bar_slider,
+ ui_separator_left, ui_separator_middle, ui_separator_right, ui_separator_center,
+ ui_title_bar_left, ui_title_bar_middle, ui_title_bar_right,
+ ui_subcount
+} ui_subtype;
+
+typedef enum {
+ ui_window = ui_window_left,
+ ui_frame = ui_frame_left,
+ ui_status = ui_status_left,
+ ui_menu = ui_menu_left,
+ ui_button = ui_button_left
+} ui_type;
+
+typedef struct {
+ bool freeview;
+ uint ignore;
+ uint camera_x;
+ uint camera_y;
+ char * help_box_none;
+ char * help_box_text;
+ uint help_box_icon;
+ uint side_panel;
+ uint font;
+ uint monofont;
+ uint sprite [ui_subcount];
+ uint width [ui_subcount];
+ uint height [ui_subcount];
+ uint separator_size;
+ uint icon_size;
+ uint overicon_size;
+ uint ubericon_size;
+ uint title_bar_size;
+ uint fill_bar_size;
+ uint scroll_bar_size;
+ uint camera_speed;
+} ui_structure;
+
+static ui_structure * ui_initialize (cross_structure * cross) {
+ const char * subtype_file_name [ui_subcount] = {
+ "window_left", "window_right", "window_upper", "window_lower",
+ "window_upper_left", "window_upper_right", "window_lower_left", "window_lower_right",
+ "frame_left", "frame_right", "frame_upper", "frame_lower",
+ "frame_upper_left", "frame_upper_right", "frame_lower_left", "frame_lower_right",
+ "status_left", "status_right", "status_upper", "status_lower",
+ "status_upper_left", "status_upper_right", "status_lower_left", "status_lower_right",
+ "status_middle",
+ "menu_left", "menu_right", "menu_upper", "menu_lower",
+ "menu_upper_left", "menu_upper_right", "menu_lower_left", "menu_lower_right",
+ "menu_middle",
+ "button_left", "button_right", "button_upper", "button_lower",
+ "button_upper_left", "button_upper_right", "button_lower_left", "button_lower_right",
+ "button_middle",
+ "fill_bar_left", "fill_bar_middle", "fill_bar_right", "fill_bar_base",
+ "tiny_fill_bar_left", "tiny_fill_bar_middle", "tiny_fill_bar_right", "tiny_fill_bar_base",
+ "check_box_off", "check_box_on",
+ "end_turn_button",
+ "cursor",
+ "icon_frame", "overicon_frame", "ubericon_frame",
+ "scroll_bar_lower", "scroll_bar_middle", "scroll_bar_upper", "scroll_bar_slider",
+ "separator_left", "separator_middle", "separator_right", "separator_center",
+ "title_bar_left", "title_bar_middle", "title_bar_right"
+ };
+
+ ui_structure * ui = allocate (sizeof (* ui));
+
+ ui->freeview = false;
+ ui->ignore = ~ 0u;
+ ui->camera_x = 0;
+ ui->camera_y = 0;
+ ui->help_box_none = string_duplicate ("---");
+ ui->help_box_text = ui->help_box_none;
+ ui->help_box_icon = ui->ignore;
+ ui->side_panel = 400;
+
+ ui->font = cross_font_import (cross, configuration_format ("xui/regular"), ' ', '~', 0xffee0000u);
+ ui->monofont = cross_font_import (cross, configuration_format ("xui/monospace"), ' ', '~', 0xffeeee00u);
+
+ for (uint index = 0; index < ui_subcount; ++index) {
+ const char * file_name = configuration_format (format ("xui/%s", subtype_file_name [index]));
+
+ ui->sprite [index] = cross_sprite_import (cross, file_name);
+
+ ui->width [index] = cross_sprite_width (cross, ui->sprite [index]);
+ ui->height [index] = cross_sprite_height (cross, ui->sprite [index]);
+ }
+
+ ui->separator_size = ui->height [ui_separator_middle];
+ ui->icon_size = ui->height [ui_icon_frame];
+ ui->overicon_size = ui->height [ui_overicon_frame];
+ ui->ubericon_size = ui->height [ui_ubericon_frame];
+ ui->title_bar_size = ui->height [ui_title_bar_middle];
+ ui->fill_bar_size = ui->height [ui_fill_bar_middle];
+ ui->scroll_bar_size = ui->width [ui_scroll_bar_middle];
+
+ print ("[/2Success/-] Initialized UI structure.\n");
+
+ return (ui);
+}
+
+static ui_structure * ui_deinitialize (ui_structure * ui) {
+ ui->help_box_none = deallocate (ui->help_box_none);
+
+ print ("[/2Success/-] Deinitialized UI information.\n");
+
+ return (deallocate (ui));
+}
+
+static int ui_offset_x (const cross_structure * cross, const ui_structure * ui) {
+ return (ui->camera_x - cross->window_width / 2);
+}
+
+static int ui_offset_y (const cross_structure * cross, const ui_structure * ui) {
+ return (ui->camera_y - cross->window_height / 2);
+}
+
+static uint ui_side_panel (const ui_structure * ui) {
+ return (ui->side_panel); /// MAKE IT WINDOW SIZE DEPENDENT?
+}
+
+static void ui_camera_upper (ui_structure * ui) { ui->freeview = true; ui->camera_y -= ui->camera_speed; }
+static void ui_camera_lower (ui_structure * ui) { ui->freeview = true; ui->camera_y += ui->camera_speed; }
+static void ui_camera_left (ui_structure * ui) { ui->freeview = true; ui->camera_x -= ui->camera_speed; }
+static void ui_camera_right (ui_structure * ui) { ui->freeview = true; ui->camera_x += ui->camera_speed; }
+
+static void ui_render (cross_structure * cross, const ui_structure * ui, ui_subtype index, int x, int y) {
+ cross_render_sprite (cross, ui->sprite [index], x, y);
+}
+
+static void ui_render_colour (cross_structure * cross, const ui_structure * ui, ui_subtype index, uint colour, int x, int y) {
+ cross_render_sprite_colour (cross, ui->sprite [index], colour, x, y);
+}
+
+static void ui_subrender (cross_structure * cross, const ui_structure * ui, ui_subtype index, int x, int y, uint u, uint v, uint width, uint height) {
+ cross_render_sprite_crop (cross, ui->sprite [index], x, y, u, v, width, height);
+}
+
+static void ui_subrender_colour (cross_structure * cross, const ui_structure * ui, ui_subtype index, uint colour, int x, int y, uint u, uint v, uint width, uint height) {
+ cross_render_sprite_crop_colour (cross, ui->sprite [index], colour, x, y, u, v, width, height);
+}
+
+static void ui_render_horizontal (cross_structure * cross, const ui_structure * ui, ui_subtype index, int x, int y, uint width) {
+ const int entire = (width / ui->width [index]) * ui->width [index];
+
+ for (uint margin = 0; margin < width / ui->width [index]; ++margin) {
+ ui_render (cross, ui, index, x + margin * ui->width [index], y);
+ }
+
+ if (width % ui->width [index] > 0) {
+ ui_subrender (cross, ui, index, x + entire, y, 0, 0, width % ui->width [index], ui->height [index]);
+ }
+}
+
+static void ui_render_horizontal_colour (cross_structure * cross, const ui_structure * ui, ui_subtype index, uint colour, int x, int y, uint width) {
+ const int entire = (width / ui->width [index]) * ui->width [index];
+
+ for (uint margin = 0; margin < width / ui->width [index]; ++margin) {
+ ui_render_colour (cross, ui, index, colour, x + margin * ui->width [index], y);
+ }
+
+ if (width % ui->width [index] > 0) {
+ ui_subrender_colour (cross, ui, index, colour, x + entire, y, 0, 0, width % ui->width [index], ui->height [index]);
+ }
+}
+
+static void ui_render_vertical (cross_structure * cross, const ui_structure * ui, ui_subtype index, int x, int y, uint height) {
+ const int entire = (height / ui->height [index]) * ui->height [index];
+
+ for (uint margin = 0; margin < height / ui->height [index]; ++margin) {
+ ui_render (cross, ui, index, x, y + margin * ui->height [index]);
+ }
+
+ if (height % ui->height [index] > 0) {
+ ui_subrender (cross, ui, index, x, y + entire, 0, 0, ui->width [index], height % ui->height [index]);
+ }
+}
+
+static void ui_render_background (cross_structure * cross, const ui_structure * ui, ui_subtype index, int x, int y, uint width, uint height) {
+ const uint offset_x = (width / ui->width [index]) * ui->width [index];
+ const uint offset_y = (height / ui->height [index]) * ui->height [index];
+
+ const uint cutoff_x = width % ui->width [index];
+ const uint cutoff_y = height % ui->height [index];
+
+ for (uint vertical = 0; vertical < height / ui->height [index]; ++vertical) {
+ for (uint horizontal = 0; horizontal < width / ui->width [index]; ++horizontal) {
+ ui_render (cross, ui, index, x + horizontal * ui->width [index], y + vertical * ui->height [index]);
+ }
+
+ if (width % ui->width [index] > 0) {
+ ui_subrender (cross, ui, index, x + offset_x, y + vertical * ui->height [index], 0, 0, cutoff_x, ui->height [index]);
+ }
+ }
+
+ for (uint horizontal = 0; horizontal < width / ui->width [index]; ++horizontal) {
+ ui_subrender (cross, ui, index, x + horizontal * ui->width [index], y + offset_y, 0, 0, ui->width [index], cutoff_y);
+ }
+
+ if (width % ui->width [index] > 0) {
+ ui_subrender (cross, ui, index, x + offset_x, y + offset_y, 0, 0, cutoff_x, cutoff_y);
+ }
+}
+
+static void ui_screen_overlay (cross_structure * cross) {
+ cross_render_rectangle_vertical_gradient (cross, 0, 0, cross->window_width, cross->window_height / 2, 0xcc, 0x00);
+ cross_render_rectangle_vertical_gradient (cross, 0, cross->window_height / 2, cross->window_width, cross->window_height / 2, 0x00, 0xcc);
+}
+
+static void ui_render_grid (cross_structure * cross, const ui_structure * ui, ui_type element, int x, int y, uint width, uint height, uint margin, bool background) {
+ const uint upper_length = width - ui->width [element + 4] - ui->width [element + 5];
+ const uint lower_length = width - ui->width [element + 6] - ui->width [element + 7];
+ const uint left_length = height - ui->height [element + 4] - ui->height [element + 6];
+ const uint right_length = height - ui->height [element + 5] - ui->height [element + 7];
+
+ const int upper_offset_x = ui->width [element + 4];
+ const int lower_offset_x = ui->width [element + 6];
+ const int lower_offset_y = height - ui->height [element + 3];
+
+ const int right_offset_x = width - ui->width [element + 1];
+ const int left_offset_y = ui->height [element + 4];
+ const int right_offset_y = ui->height [element + 5];
+
+ const int upper_right_offset_x = width - ui->width [element + 5];
+ const int lower_right_offset_x = width - ui->width [element + 7];
+ const int lower_left_offset_y = height - ui->height [element + 6];
+ const int lower_right_offset_y = height - ui->height [element + 7];
+
+ if ((background == true) && (width > 2 * margin) && (height > 2 * margin)) {
+ ui_render_background (cross, ui, element + 8, x + margin, y + margin, width - 2 * margin, height - 2 * margin);
+ }
+
+ ui_render_vertical (cross, ui, element + 0, x, y + left_offset_y, left_length);
+ ui_render_vertical (cross, ui, element + 1, x + right_offset_x, y + right_offset_y, right_length);
+
+ ui_render_horizontal (cross, ui, element + 2, x + upper_offset_x, y, upper_length);
+ ui_render_horizontal (cross, ui, element + 3, x + lower_offset_x, y + lower_offset_y, lower_length);
+
+ ui_render (cross, ui, element + 4, x, y);
+ ui_render (cross, ui, element + 5, x + upper_right_offset_x, y);
+ ui_render (cross, ui, element + 6, x, y + lower_left_offset_y);
+ ui_render (cross, ui, element + 7, x + lower_right_offset_x, y + lower_right_offset_y);
+}
+
+static void ui_render_window (cross_structure * cross, const ui_structure * ui, int x, int y, uint width, uint height) {
+ ui_render_grid (cross, ui, ui_window, x, y, width, height, 0, false);
+}
+
+static void ui_render_frame (cross_structure * cross, const ui_structure * ui, int x, int y, uint width, uint height) {
+ ui_render_grid (cross, ui, ui_frame, x, y, width, height, 0, false);
+}
+
+static void ui_render_status (cross_structure * cross, const ui_structure * ui, int x, int y, uint width, uint height) {
+ ui_render_grid (cross, ui, ui_status, x, y, width, height, 16, true);
+}
+
+static void ui_render_menu (cross_structure * cross, const ui_structure * ui, int x, int y, uint width, uint height) {
+ ui_render_grid (cross, ui, ui_menu, x, y, width, height, 24, true);
+}
+
+static void ui_render_button (cross_structure * cross, const ui_structure * ui, int x, int y, uint width, uint height) {
+ ui_render_grid (cross, ui, ui_button, x, y, width, height, 16, true);
+}
+
+static void ui_render_separator (cross_structure * cross, const ui_structure * ui, int x, int y, uint width) {
+ const uint margin = ui->width [ui_separator_left];
+ const uint length = width - margin - ui->width [ui_separator_right];
+
+ ui_render (cross, ui, ui_separator_left, x, y);
+
+ ui_render_horizontal (cross, ui, ui_separator_middle, x + margin, y, length);
+
+ ui_render (cross, ui, ui_separator_right, x + margin + length, y);
+
+ ui_render (cross, ui, ui_separator_center, x + (width - ui->width [ui_separator_center]) / 2, y);
+}
+
+static void ui_render_title_bar (cross_structure * cross, const ui_structure * ui, const char * title, int x, int y, uint width) {
+ const uint margin = ui->width [ui_title_bar_left];
+ const uint length = width - margin - ui->width [ui_title_bar_right];
+
+ ui_render (cross, ui, ui_title_bar_left, x, y);
+
+ ui_render_horizontal (cross, ui, ui_title_bar_middle, x + margin, y, length);
+
+ ui_render (cross, ui, ui_title_bar_right, x + margin + length, y);
+
+ cross_render_string (cross, title, ui->font, x + margin + 8, y + 8, 1, 0x112233ff);
+}
+
+static void ui_render_icon_and_text (cross_structure * cross, const ui_structure * ui, const char * title, uint icon, int x, int y) {
+ cross_render_sprite (cross, icon, x, y);
+
+ cross_render_string (cross, title, ui->font, x - 2 + ui->icon_size, y + 2, 1, 0x112233ffu);
+}
+
+static void ui_render_scroll_bar (cross_structure * cross, const ui_structure * ui, float slider, int x, int y, uint height) {
+ const uint margin = ui->height [ui_scroll_bar_upper];
+ const uint length = height - margin - ui->height [ui_scroll_bar_lower];
+
+ ui_render (cross, ui, ui_scroll_bar_upper, x, y);
+
+ ui_render_vertical (cross, ui, ui_scroll_bar_middle, x, y + margin, length);
+
+ ui_render (cross, ui, ui_scroll_bar_lower, x, y + margin + length);
+
+ ui_render (cross, ui, ui_scroll_bar_slider, x, y + margin + (uint) (slider * (float) (length - ui->height [ui_scroll_bar_slider])));
+}
+
+static void ui_render_fill_bar (cross_structure * cross, const ui_structure * ui, float fill, uint colour, int x, int y, uint width) {
+ const uint margin = ui->width [ui_fill_bar_left];
+ const uint length = width - margin - ui->width [ui_fill_bar_right];
+
+ ui_render (cross, ui, ui_fill_bar_left, x, y);
+
+ ui_render_horizontal (cross, ui, ui_fill_bar_middle, x + margin, y, length);
+
+ ui_render (cross, ui, ui_fill_bar_right, x + margin + length, y);
+
+ ui_render_horizontal_colour (cross, ui, ui_fill_bar_base, colour, x + margin, y, (uint) (fill * (float) length));
+}
+
+static void ui_render_icon (cross_structure * cross, const ui_structure * ui, uint icon, int x, int y) {
+ cross_render_sprite (cross, ui->sprite [ui_icon_frame], x, y);
+
+ if (icon != ui->ignore) {
+ cross_render_sprite (cross, icon, x, y);
+ }
+}
+
+static void ui_render_overicon (cross_structure * cross, const ui_structure * ui, uint icon, int x, int y) {
+ if (icon != ui->ignore) {
+ cross_render_sprite (cross, icon, x, y);
+ }
+
+ cross_render_sprite (cross, ui->sprite [ui_overicon_frame], x, y);
+}
+
+static void ui_render_ubericon (cross_structure * cross, const ui_structure * ui, uint icon, int x, int y) {
+ cross_render_sprite (cross, ui->sprite [ui_ubericon_frame], x, y);
+
+ if (icon != ui->ignore) {
+ cross_render_sprite (cross, icon, x + 16, y + 16);
+ }
+}
+
+static void ui_render_menu_full (cross_structure * cross, const ui_structure * ui, const char * title, int x, int y, uint width, uint height) {
+ const uint margin = 24;
+
+ ui_screen_overlay (cross);
+
+ ui_render_menu (cross, ui, x, y, width, height);
+
+ if (title != null) {
+ ui_render_title_bar (cross, ui, format ("<%s>", title), x + margin, y + margin / 2 - ui->title_bar_size, width - 2 * margin);
+ }
+}
--- /dev/null
+/// _ _
+/// __ ___ _| | | ____ _ _ __
+/// \ \/ / | | | | |/ / _` | '_ \
+/// > <| |_| | | < (_| | | | |
+/// /_/\_\\__,_|_|_|\_\__,_|_| |_|
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xulkan - Tiny and elegant Vulkan wrapper library so I don't have to write 40k lines of code for a triangle...
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+/// DO NOT USE THIS CRAP...
+
+#define VK_USE_PLATFORM_XCB_KHR
+
+#include <vulkan/vulkan.h>
+
+typedef struct {
+ bool active;
+ bool reconfigure_active;
+ bool validation_layers;
+ bool hide_cursor_full;
+ bool hide_cursor;
+ uint time;
+
+ uint cursor; /// TODO: PROPER INPUT
+ int cursor_x;
+ int cursor_y;
+
+ bool signal [signal_count];
+
+ float pixel_width;
+ float pixel_height;
+ uint frame;
+ uint width;
+ uint height;
+ uint sprite_count;
+ uint * * sprite_data;
+ uint * sprite_width;
+ uint * sprite_height;
+ float * sprite_u;
+ float * sprite_v;
+ uint font_count;
+ uint * * font_index;
+ uint * * font_width;
+ uint * * font_height;
+ char * font_begin;
+ char * font_end;
+
+ xcb_connection_t * connection;
+ xcb_screen_t * screen;
+ xcb_window_t window;
+
+ uint global_time;
+ uint gameplay_time;
+ uint animation_time;
+ uint framerate;
+ uint gameplay_framerate;
+ uint animation_framerate;
+ ulong frame_time_in_ns;
+
+ VkInstance instance;
+ VkSurfaceKHR surface;
+ VkPhysicalDevice physical_device;
+ VkQueue queue;
+ uint queue_index;
+ VkDevice logical_device;
+ uint image_count;
+ VkExtent2D extent;
+ VkFormat format;
+ VkPresentModeKHR present_mode;
+ VkSurfaceTransformFlagBitsKHR transform;
+ VkCompositeAlphaFlagBitsKHR composite_alpha;
+ VkSwapchainKHR swapchain;
+ VkImage * images;
+ VkImageView * image_views;
+ VkSemaphore * semaphore_set_1;
+ VkSemaphore * semaphore_set_2;
+ VkFence * fence_set_1;
+ VkDescriptorSetLayout descriptor_set_layout;
+ VkDescriptorSetLayout * descriptor_set_layouts;
+ VkDescriptorPool descriptor_pool;
+ VkDescriptorSet * descriptor_sets;
+ VkRenderPass render_pass;
+ VkShaderModule vertex_shader;
+ VkShaderModule fragment_shader;
+ VkPipelineLayout pipeline_layout;
+ VkPipeline pipeline;
+ VkFramebuffer * framebuffers;
+ VkCommandPool command_pool;
+ VkCommandBuffer * command_buffers;
+ VkCommandBuffer transfer_buffer;
+ VkBuffer vertex_buffer;
+ VkDeviceMemory vertex_memory;
+ float * vertex_data;
+ VkDeviceSize vertex_size;
+ uint vertex_count;
+ uint vertex_limit;
+ VkBuffer index_buffer;
+ VkDeviceMemory index_memory;
+ uint * index_data;
+ VkDeviceSize index_size;
+ uint index_count;
+ uint index_limit;
+ VkSampler sampler;
+ VkImage layout_image;
+ VkDeviceMemory layout_memory;
+ VkImageView layout_image_view;
+ uint * layout_data;
+ uint layout_size;
+ uint layout_width;
+ uint layout_height;
+} vulkan_structure;
+
+static const char * vulkan_continue_execution [] = {
+ "/s Commands successfully completed.\n",
+ "/w Fence or query hasn't yet completed.\n",
+ "/w Wait operation hasn't completed in the specified time.\n",
+ "/w Event is signaled.\n",
+ "/w Event isn't signaled.\n",
+ "/w Return array was too small for the result.\n"
+};
+
+static const char * vulkan_break_execution [] = {
+ "/f Host memory allocation has failed.\n",
+ "/f Device memory allocation has failed.\n",
+ "/f Initialization of an object couldn't be completed.\n",
+ "/f Logical or physical device has been lost.\n",
+ "/f Mapping of a memory object has failed.\n",
+ "/f Requested layer isn't present or couln't be loaded.\n",
+ "/f Requested extension isn't supported.\n",
+ "/f Requested feature isn't supported.\n",
+ "/f Requested version of Vulkan isn't suported.\n",
+ "/f Too many objects of the type have alrady been created.\n",
+ "/f Requested format isn't supported.\n",
+ "/f Pool allocation has failed due to framentation.\n",
+ "/f Unknown error has occurred.\n",
+ "/f Undefined error has occured.\n"
+};
+
+static void vulkan_result (VkResult result) {
+ if (result == 0) {
+ return;
+ } else if (result > 0) {
+ print (vulkan_continue_execution [result]);
+ } else {
+ print (vulkan_break_execution [- result - 1]);
+ //~exit (log_failure);
+ }
+}
+
+static vulkan_structure * vulkan_initialize (ulong quad_memory, ulong layout_side, uint gameplay_framerate, uint animation_framerate) {
+ vulkan_structure * vulkan = allocate (sizeof (* vulkan));
+
+ vulkan->vertex_limit = quad_memory * 32;
+ vulkan->index_limit = quad_memory * 6;
+ vulkan->gameplay_framerate = gameplay_framerate;
+ vulkan->animation_framerate = animation_framerate;
+ vulkan->layout_width = layout_side;
+ vulkan->layout_height = layout_side;
+
+ return (vulkan);
+}
+
+static vulkan_structure * vulkan_deinitialize (vulkan_structure * vulkan) {
+ print ("/c Destroying and deallocating all the bullshit used so far...\n");
+
+ vulkan_result (vkQueueWaitIdle (vulkan->queue));
+ vulkan_result (vkDeviceWaitIdle (vulkan->logical_device));
+
+ vulkan->sprite_width = deallocate (vulkan->sprite_width);
+ vulkan->sprite_height = deallocate (vulkan->sprite_height);
+ vulkan->sprite_u = deallocate (vulkan->sprite_u);
+ vulkan->sprite_v = deallocate (vulkan->sprite_v);
+
+ if (vulkan->font_count > 0) {
+ for (uint index = 0; index < vulkan->font_count; ++index) {
+ vulkan->font_index [index] = deallocate (vulkan->font_index [index]);
+ vulkan->font_width [index] = deallocate (vulkan->font_width [index]);
+ vulkan->font_height [index] = deallocate (vulkan->font_height [index]);
+ }
+
+ vulkan->font_index = deallocate (vulkan->font_index);
+ vulkan->font_width = deallocate (vulkan->font_width);
+ vulkan->font_height = deallocate (vulkan->font_height);
+ vulkan->font_begin = deallocate (vulkan->font_begin);
+ vulkan->font_end = deallocate (vulkan->font_end);
+ }
+
+ vkFreeDescriptorSets (vulkan->logical_device, vulkan->descriptor_pool, vulkan->image_count, vulkan->descriptor_sets);
+
+ vulkan->descriptor_set_layouts = deallocate (vulkan->descriptor_set_layouts);
+ vulkan->descriptor_sets = deallocate (vulkan->descriptor_sets);
+
+ vkDestroyDescriptorPool (vulkan->logical_device, vulkan->descriptor_pool, null);
+ vkDestroySampler (vulkan->logical_device, vulkan->sampler, null);
+ vkDestroyImageView (vulkan->logical_device, vulkan->layout_image_view, null);
+ vkDestroyImage (vulkan->logical_device, vulkan->layout_image, null);
+ vkFreeMemory (vulkan->logical_device, vulkan->layout_memory, null);
+
+ vulkan->layout_data = deallocate (vulkan->layout_data);
+
+ vulkan->index_data = deallocate (vulkan->index_data);
+ vulkan->vertex_data = deallocate (vulkan->vertex_data);
+/*
+ vkFreeCommandBuffers (vulkan->logical_device, vulkan->command_pool, vulkan->image_count, vulkan->command_buffers);
+*/
+ vulkan->command_buffers = deallocate (vulkan->command_buffers);
+
+ vkDestroyCommandPool (vulkan->logical_device, vulkan->command_pool, null);
+
+ for (uint index = 0; index < vulkan->image_count; ++index) {
+ vkDestroyFramebuffer (vulkan->logical_device, vulkan->framebuffers [index], null);
+ }
+
+ vulkan->framebuffers = deallocate (vulkan->framebuffers);
+
+ vkDestroyPipeline (vulkan->logical_device, vulkan->pipeline, null);
+ vkDestroyPipelineLayout (vulkan->logical_device, vulkan->pipeline_layout, null);
+ vkDestroyShaderModule (vulkan->logical_device, vulkan->fragment_shader, null);
+ vkDestroyShaderModule (vulkan->logical_device, vulkan->vertex_shader, null);
+ vkDestroyDescriptorSetLayout (vulkan->logical_device, vulkan->descriptor_set_layout, null);
+ vkDestroyRenderPass (vulkan->logical_device, vulkan->render_pass, null);
+
+ for (uint index = 0; index < vulkan->image_count; ++index) {
+ vkDestroySemaphore (vulkan->logical_device, vulkan->semaphore_set_1 [index], null);
+ vkDestroySemaphore (vulkan->logical_device, vulkan->semaphore_set_2 [index], null);
+ vkDestroyFence (vulkan->logical_device, vulkan->fence_set_1 [index], null);
+ }
+
+ vulkan->semaphore_set_1 = deallocate (vulkan->semaphore_set_1);
+ vulkan->semaphore_set_2 = deallocate (vulkan->semaphore_set_2);
+ vulkan->fence_set_1 = deallocate (vulkan->fence_set_1);
+
+ for (uint index = 0; index < vulkan->image_count; ++index) {
+ vkDestroyImageView (vulkan->logical_device, vulkan->image_views [index], null);
+ }
+
+ vulkan->image_views = deallocate (vulkan->image_views);
+
+ vkDestroySwapchainKHR (vulkan->logical_device, vulkan->swapchain, null);
+
+ vulkan->images = deallocate (vulkan->images);
+
+ vkDestroySurfaceKHR (vulkan->instance, vulkan->surface, null);
+
+ vkDestroyDevice (vulkan->logical_device, null);
+ vkDestroyInstance (vulkan->instance, null);
+
+ xcb_destroy_window (vulkan->connection, vulkan->window);
+ xcb_disconnect (vulkan->connection);
+
+ print ("/c Destroyed and deallocated all resources.\n");
+
+ return (deallocate (vulkan));
+}
+
+static uint vulkan_choose_memory_property (vulkan_structure * vulkan, uint wanted) {
+ uint index = 0;
+ uint usable = 0;
+
+ VkPhysicalDeviceMemoryProperties memory_properties = { 0 };
+
+ vkGetPhysicalDeviceMemoryProperties (vulkan->physical_device, & memory_properties);
+
+ for (index = 0; index < memory_properties.memoryTypeCount; ++index) {
+ if ((memory_properties.memoryTypes [index].propertyFlags & wanted) == wanted) {
+ usable &= (1 << index);
+ }
+ }
+
+ if (usable != wanted) {
+ print ("/w Can't set this memory property bit: usable = %i, wanted = %i.\n", usable, wanted);
+ }
+
+ return (usable);
+}
+
+static void vulkan_create_buffer (vulkan_structure * vulkan, VkBuffer * buffer, VkDeviceMemory * memory, VkDeviceSize size, VkMemoryPropertyFlags usage) {
+ uint wanted_memory_index = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+
+ VkBufferCreateInfo buffer_information = { 0 };
+ VkMemoryRequirements memory_requirements = { 0 };
+ VkMemoryAllocateInfo memory_allocation_information = { 0 };
+
+ buffer_information.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buffer_information.size = size;
+ buffer_information.usage = usage;
+ buffer_information.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+ vulkan_result (vkCreateBuffer (vulkan->logical_device, & buffer_information, null, buffer));
+
+ vkGetBufferMemoryRequirements (vulkan->logical_device, * buffer, & memory_requirements);
+
+ memory_allocation_information.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ memory_allocation_information.allocationSize = memory_requirements.size;
+ memory_allocation_information.memoryTypeIndex = vulkan_choose_memory_property (vulkan, wanted_memory_index);
+
+ vulkan_result (vkAllocateMemory (vulkan->logical_device, & memory_allocation_information, null, memory));
+
+ vulkan_result (vkBindBufferMemory (vulkan->logical_device, * buffer, * memory, 0));
+}
+
+static void vulkan_begin_command_buffer (vulkan_structure * vulkan) {
+ VkCommandBufferAllocateInfo command_buffer_allocation_information = { 0 };
+ VkCommandBufferBeginInfo command_buffer_begin_information = { 0 };
+
+ command_buffer_allocation_information.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ command_buffer_allocation_information.commandPool = vulkan->command_pool;
+ command_buffer_allocation_information.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ command_buffer_allocation_information.commandBufferCount = 1;
+
+ command_buffer_begin_information.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ command_buffer_begin_information.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+
+ vulkan_result (vkAllocateCommandBuffers (vulkan->logical_device, & command_buffer_allocation_information, & vulkan->transfer_buffer));
+
+ vulkan_result (vkBeginCommandBuffer (vulkan->transfer_buffer, & command_buffer_begin_information));
+}
+
+static void vulkan_end_command_buffer (vulkan_structure * vulkan) {
+ VkSubmitInfo submit_information = { 0 };
+
+ vkEndCommandBuffer (vulkan->transfer_buffer);
+
+ submit_information.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_information.commandBufferCount = 1;
+ submit_information.pCommandBuffers = & vulkan->transfer_buffer;
+
+ vkQueueSubmit (vulkan->queue, 1, & submit_information, VK_NULL_HANDLE);
+
+ vkQueueWaitIdle (vulkan->queue);
+
+ vkFreeCommandBuffers (vulkan->logical_device, vulkan->command_pool, 1, & vulkan->transfer_buffer);
+
+ vulkan->transfer_buffer = VK_NULL_HANDLE;
+}
+
+static void vulkan_create_window (vulkan_structure * vulkan, const char * application) {
+ uint window_flags [2] = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vulkan->connection = xcb_connect (null, null);
+
+ print ("Connected to /3X11 server/-.\n");
+
+ vulkan->screen = xcb_setup_roots_iterator (xcb_get_setup (vulkan->connection)).data;
+
+ vulkan->window = xcb_generate_id (vulkan->connection);
+
+ window_flags [0] = vulkan->screen->black_pixel;
+ window_flags [1] = XCB_EVENT_MASK_NO_EVENT |
+ XCB_EVENT_MASK_EXPOSURE |
+ /*XCB_EVENT_MASK_STRUCTURE_NOTIFY |*/
+ XCB_EVENT_MASK_RESIZE_REDIRECT |
+ XCB_EVENT_MASK_KEY_RELEASE |
+ XCB_EVENT_MASK_KEY_PRESS |
+ /*XCB_EVENT_MASK_POINTER_MOTION |*/
+ XCB_EVENT_MASK_BUTTON_RELEASE |
+ XCB_EVENT_MASK_BUTTON_PRESS;
+
+ xcb_create_window (vulkan->connection, vulkan->screen->root_depth, vulkan->window, vulkan->screen->root, 0, 0,
+ (ushort) vulkan->width, (ushort) vulkan->height, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ vulkan->screen->root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, window_flags);
+
+ print ("/c Created /3XCB window/-.\n");
+
+ xcb_map_window (vulkan->connection, vulkan->window);
+
+ xcb_change_property (vulkan->connection, XCB_PROP_MODE_REPLACE, vulkan->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
+ string_length (application), application);
+
+ xcb_flush (vulkan->connection);
+
+ print ("Mapped /3XCB window/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_instance (vulkan_structure * vulkan, const char * application) {
+ uint current = 0;
+ uint general = 0;
+
+ VkApplicationInfo application_information = { 0 };
+ VkInstanceCreateInfo instance_information = { 0 };
+
+ uint instance_layer_count = 0;
+ uint * instance_layer_index = null;
+ VkLayerProperties * instance_layer_array = null;
+ uint instance_extension_count = 0;
+ uint * instance_extension_index = null;
+ VkExtensionProperties * instance_extension_array = null;
+
+ const uint default_instance_layer_count = (uint) (vulkan->validation_layers == true);
+ const uint default_instance_extension_count = 2;
+
+ const char * default_instance_layer_array [VK_MAX_EXTENSION_NAME_SIZE] = {
+ "VK_LAYER_KHRONOS_validation"
+ //~"VK_LAYER_LUNARG_parameter_validation",
+ //~"VK_LAYER_LUNARG_core_validation",
+ //~"VK_LAYER_LUNARG_standard_validation"
+ };
+
+ const char * default_instance_extension_array [VK_MAX_EXTENSION_NAME_SIZE] = {
+ VK_KHR_SURFACE_EXTENSION_NAME,
+ VK_KHR_XCB_SURFACE_EXTENSION_NAME
+ };
+
+ vulkan->time = tick_tock ();
+
+ vulkan_result (vkEnumerateInstanceLayerProperties (& instance_layer_count, null));
+
+ print ("Instance layer count: /2%i/-\n", instance_layer_count);
+
+ instance_layer_index = allocate (instance_layer_count * sizeof (* instance_layer_index));
+ instance_layer_array = allocate (instance_layer_count * sizeof (* instance_layer_array));
+
+ vulkan_result (vkEnumerateInstanceLayerProperties (& instance_layer_count, instance_layer_array));
+
+ for (current = 0; current < instance_layer_count; ++current) {
+ for (general = 0; general < default_instance_layer_count; ++general) {
+ if (string_compare (instance_layer_array [current].layerName, (char *) default_instance_layer_array [general])) {
+ instance_layer_index [current] = true;
+ }
+ }
+ }
+
+ for (current = 0; current < instance_layer_count; ++current) {
+ print ("\t[%t] %s\n", instance_layer_index [current], instance_layer_array [current].layerName);
+ }
+
+ instance_layer_index = deallocate (instance_layer_index);
+ instance_layer_array = deallocate (instance_layer_array);
+
+ print ("Enumerated /2instance layer properties/-.\n");
+
+ vulkan_result (vkEnumerateInstanceExtensionProperties (null, & instance_extension_count, null));
+
+ print ("Instance extension count: /2%i/-\n", instance_extension_count);
+
+ instance_extension_index = allocate (instance_extension_count * sizeof (* instance_extension_index));
+ instance_extension_array = allocate (instance_extension_count * sizeof (* instance_extension_array));
+
+ vulkan_result (vkEnumerateInstanceExtensionProperties (null, & instance_extension_count, instance_extension_array));
+
+ for (current = 0; current < instance_extension_count; ++current) {
+ for (general = 0; general < default_instance_extension_count; ++general) {
+ if (string_compare (instance_extension_array [current].extensionName, (char *) default_instance_extension_array [general])) {
+ instance_extension_index [current] = true;
+ }
+ }
+ }
+
+ for (current = 0; current < instance_extension_count; ++current) {
+ print ("\t[%t] %s\n", instance_extension_index [current], instance_extension_array [current].extensionName);
+ }
+
+ instance_extension_index = deallocate (instance_extension_index);
+ instance_extension_array = deallocate (instance_extension_array);
+
+ print ("Enumerated /2instance extension properties/-.\n");
+
+ application_information.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ application_information.pApplicationName = application;
+ application_information.applicationVersion = VK_MAKE_VERSION (1, 0, 0);
+ application_information.pEngineName = "xulkan";
+ application_information.engineVersion = VK_MAKE_VERSION (1, 0, 0);
+ application_information.apiVersion = VK_API_VERSION_1_0;
+
+ instance_information.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ instance_information.pApplicationInfo = & application_information;
+ instance_information.enabledLayerCount = default_instance_layer_count;
+ instance_information.ppEnabledLayerNames = default_instance_layer_array;
+ instance_information.enabledExtensionCount = default_instance_extension_count;
+ instance_information.ppEnabledExtensionNames = default_instance_extension_array;
+
+ vulkan_result (vkCreateInstance (& instance_information, null, & vulkan->instance));
+
+ print ("/c Created /2Vulkan instance/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_surface (vulkan_structure * vulkan) {
+ VkXcbSurfaceCreateInfoKHR surface_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ surface_information.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+ surface_information.connection = vulkan->connection;
+ surface_information.window = vulkan->window;
+
+ vulkan_result (vkCreateXcbSurfaceKHR (vulkan->instance, & surface_information, null, & vulkan->surface));
+
+ print ("/c Created /2Vulkan-XCB surface/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_device (vulkan_structure * vulkan) {
+ VkDeviceQueueCreateInfo queues = { 0 };
+ VkDeviceCreateInfo device_information = { 0 };
+ VkPhysicalDeviceMemoryProperties memory_properties = { 0 };
+
+ uint queue_count = 0;
+ uint physical_device_count = 0;
+ VkPhysicalDevice * physical_device_array = null;
+ VkBool32 * support = null;
+
+ const float queue_priorities [1] = { 1 };
+
+ const uint default_device_extension_count = 1;
+
+ const char * default_device_extension_array [VK_MAX_EXTENSION_NAME_SIZE] = {
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME
+ };
+
+ vulkan->time = tick_tock ();
+
+ vulkan_result (vkEnumeratePhysicalDevices (vulkan->instance, & physical_device_count, null));
+
+ print ("Device count: /2%i/-\n", physical_device_count);
+
+ physical_device_array = allocate (physical_device_count * sizeof (VkPhysicalDevice));
+
+ vulkan_result (vkEnumeratePhysicalDevices (vulkan->instance, & physical_device_count, physical_device_array));
+
+ print ("Enumerated available physical devices.\n");
+
+ for (uint index = 0; index < physical_device_count; ++index) {
+ uint general = 0;
+ uint current = 0;
+
+ uint device_extension_count = 0;
+ uint * device_extension_index = null;
+ VkExtensionProperties * device_extension_array = null;
+
+ VkPhysicalDeviceProperties physical_device_properties = { 0 };
+ VkPhysicalDeviceFeatures physical_device_features = { 0 };
+
+ VkQueueFamilyProperties * queue_properties = null;
+
+ vkGetPhysicalDeviceProperties (physical_device_array [index], & physical_device_properties);
+ vkGetPhysicalDeviceFeatures (physical_device_array [index], & physical_device_features);
+
+#define get_fucking_version(i) \
+ VK_VERSION_MAJOR(i), \
+ VK_VERSION_MINOR(i), \
+ VK_VERSION_PATCH(i)
+ print ("Physical device: /2%s/-\n", physical_device_properties.deviceName);
+ print ("Device ID: /2%i/-\n", physical_device_properties.deviceID);
+ print ("API version: /2%i.%i.%i/-\n", get_fucking_version (physical_device_properties.apiVersion));
+ print ("Driver version: /2%i.%i.%i/-\n", get_fucking_version (physical_device_properties.driverVersion));
+#undef get_fucking_version
+
+ switch (physical_device_properties.deviceType) {
+ case (VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU): print ("Device type: /2Integrated GPU/-\n"); break;
+ case (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU): print ("Device type: /2Discrete GPU/-\n"); break;
+ case (VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU): print ("Device type: /2Virtual GPU/-\n"); break;
+ case (VK_PHYSICAL_DEVICE_TYPE_CPU): print ("Device type: /2CPU/-\n"); break;
+ default: print ("Device type: /2Other/-\n"); break;
+ }
+
+ switch (physical_device_properties.vendorID) {
+ case (VK_VENDOR_ID_VIV): print ("Vendor: /2VIV/-\n"); break;
+ case (VK_VENDOR_ID_VSI): print ("Vendor: /2VSI/-\n"); break;
+ case (VK_VENDOR_ID_KAZAN): print ("Vendor: /2Kazan/-\n"); break;
+ case (VK_VENDOR_ID_CODEPLAY): print ("Vendor: /2Codeplay/-\n"); break;
+ case (VK_VENDOR_ID_MESA): print ("Vendor: /2MESA/-\n"); break;
+ case (VK_VENDOR_ID_POCL): print ("Vendor: /2POCL/-\n"); break;
+ default: print ("Vendor: /2Other/-\n"); break;
+ }
+
+ vulkan_result (vkEnumerateDeviceExtensionProperties (physical_device_array [index], null, & device_extension_count, null));
+
+ print ("Device extensions available: %i\n", device_extension_count);
+
+ device_extension_index = allocate (device_extension_count * sizeof (* device_extension_index));
+ device_extension_array = allocate (device_extension_count * sizeof (* device_extension_array));
+
+ vulkan_result (vkEnumerateDeviceExtensionProperties (physical_device_array [index], null, & device_extension_count,
+ device_extension_array));
+
+ for (current = 0; current < device_extension_count; ++current) {
+ for (general = 0; general < default_device_extension_count; ++general) {
+ if (string_compare (device_extension_array [current].extensionName, (char *) default_device_extension_array [general])) {
+ device_extension_index [current] = true;
+ }
+ }
+ }
+
+ for (current = 0; current < device_extension_count; ++current) {
+ print ("\t[%t] %s\n", device_extension_index [current], device_extension_array [current].extensionName);
+ }
+
+ device_extension_index = deallocate (device_extension_index);
+ device_extension_array = deallocate (device_extension_array);
+
+ vkGetPhysicalDeviceQueueFamilyProperties (physical_device_array [index], & queue_count, null);
+
+ queue_properties = allocate (queue_count * sizeof (VkQueueFamilyProperties));
+
+ vkGetPhysicalDeviceQueueFamilyProperties (physical_device_array [index], & queue_count, queue_properties);
+
+ vulkan->queue_index = 0;
+
+ if ((physical_device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
+ || (physical_device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)) {
+ vulkan->physical_device = physical_device_array [index];
+ }
+
+ queue_properties = deallocate (queue_properties);
+
+ print ("Enumerated device layer properties.\n");
+
+ print ("Enumerated device extension properties.\n");
+ }
+
+ vulkan->physical_device = physical_device_array [1]; /// THIS SHIT SUCKS.
+
+ VkPhysicalDeviceProperties selected_physical_device_properties = { 0 };
+
+ vkGetPhysicalDeviceProperties (vulkan->physical_device, & selected_physical_device_properties);
+
+ print ("/c Selecting physical device '/2%s/-'.\n", selected_physical_device_properties.deviceName);
+
+ physical_device_array = deallocate (physical_device_array);
+
+ queues.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queues.queueFamilyIndex = vulkan->queue_index;
+ queues.queueCount = 1;
+ queues.pQueuePriorities = queue_priorities;
+
+ device_information.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ device_information.queueCreateInfoCount = 1;
+ device_information.pQueueCreateInfos = & queues;
+ device_information.enabledExtensionCount = default_device_extension_count;
+ device_information.ppEnabledExtensionNames = default_device_extension_array;
+ device_information.pEnabledFeatures = null;
+
+ vulkan_result (vkCreateDevice (vulkan->physical_device, & device_information, null, & vulkan->logical_device));
+
+ print ("/c Created Vulkan logical device.\n");
+
+ vkGetDeviceQueue (vulkan->logical_device, vulkan->queue_index, 0, & vulkan->queue);
+
+ vkGetPhysicalDeviceQueueFamilyProperties (vulkan->physical_device, & queue_count, null);
+
+ support = allocate (queue_count * sizeof (VkBool32));
+
+ for (uint index = 0; index < queue_count; ++index) {
+ vulkan_result (vkGetPhysicalDeviceSurfaceSupportKHR (vulkan->physical_device, index, vulkan->surface, & support [index]));
+ }
+
+ for (uint index = 0; (index != queue_count) && (! (vulkan->queue_index = support [index] ? (index++) : 0)); );
+
+ support = deallocate (support);
+
+ vkGetPhysicalDeviceMemoryProperties (vulkan->physical_device, & memory_properties);
+
+ print ("Found /2Vulkan physical device/- memory properties.\n");
+
+ for (uint index = 0; index < memory_properties.memoryTypeCount; ++index) {
+ print ("> %i\n", memory_properties.memoryTypes [index].propertyFlags);
+ }
+
+ print ("Found /2Vulkan surface support/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_choose_extent (vulkan_structure * vulkan) {
+ VkSurfaceCapabilitiesKHR capabilities = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vulkan_result (vkGetPhysicalDeviceSurfaceCapabilitiesKHR (vulkan->physical_device, vulkan->surface, & capabilities));
+
+ vulkan->image_count = capabilities.minImageCount + 1;
+
+ vulkan->extent.width = vulkan->width;
+ vulkan->extent.height = vulkan->height;
+
+ vulkan->extent.width = (vulkan->extent.width < capabilities.minImageExtent.width) ? capabilities.minImageExtent.width : vulkan->extent.width;
+ vulkan->extent.height = (vulkan->extent.height < capabilities.minImageExtent.height) ? capabilities.minImageExtent.height : vulkan->extent.height;
+
+ vulkan->extent.width = (vulkan->extent.width > capabilities.maxImageExtent.width) ? capabilities.maxImageExtent.width : vulkan->extent.width;
+ vulkan->extent.height = (vulkan->extent.height > capabilities.maxImageExtent.height) ? capabilities.maxImageExtent.height : vulkan->extent.height;
+
+ vulkan->transform = capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ vulkan->composite_alpha = capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+
+ print ("Found /2Vulkan-XCB surface capabilities/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_choose_format (vulkan_structure * vulkan) {
+ uint format_count = 0;
+ VkSurfaceFormatKHR * format_array = null;
+
+ vulkan->time = tick_tock ();
+
+ vulkan_result (vkGetPhysicalDeviceSurfaceFormatsKHR (vulkan->physical_device, vulkan->surface, & format_count, null));
+
+ format_array = allocate (format_count * sizeof (VkSurfaceFormatKHR));
+
+ vulkan_result (vkGetPhysicalDeviceSurfaceFormatsKHR (vulkan->physical_device, vulkan->surface, & format_count, format_array));
+
+ print ("Available surface format count: /2%i/-\n", format_count);
+
+ vulkan->format = VK_FORMAT_B8G8R8A8_UNORM;
+
+ format_array = deallocate (format_array);
+
+ print ("Choosing default /2Vulkan surface formats/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_choose_present_mode (vulkan_structure * vulkan) {
+ uint present_mode_count = 0;
+ VkPresentModeKHR * present_mode_array = null;
+
+ vulkan->time = tick_tock ();
+
+ vulkan_result (vkGetPhysicalDeviceSurfacePresentModesKHR (vulkan->physical_device, vulkan->surface, & present_mode_count, null));
+
+ present_mode_array = allocate (present_mode_count * sizeof (VkPresentModeKHR));
+
+ vulkan_result (vkGetPhysicalDeviceSurfacePresentModesKHR (vulkan->physical_device, vulkan->surface, & present_mode_count,
+ present_mode_array));
+
+ vulkan->present_mode = VK_PRESENT_MODE_FIFO_KHR;
+
+ present_mode_array = deallocate (present_mode_array);
+
+ print ("Choosing FIFO /2Vulkan surface present mode/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_swapchain (vulkan_structure * vulkan) {
+ VkSwapchainCreateInfoKHR swapchain_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ swapchain_information.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapchain_information.surface = vulkan->surface;
+ swapchain_information.minImageCount = vulkan->image_count;
+ swapchain_information.imageFormat = vulkan->format;
+ swapchain_information.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+ swapchain_information.imageExtent = vulkan->extent;
+ swapchain_information.imageArrayLayers = 1;
+ swapchain_information.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ swapchain_information.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchain_information.queueFamilyIndexCount = 0;
+ swapchain_information.pQueueFamilyIndices = null;
+ swapchain_information.preTransform = vulkan->transform;
+ swapchain_information.compositeAlpha = vulkan->composite_alpha;
+ swapchain_information.presentMode = vulkan->present_mode;
+ swapchain_information.clipped = VK_TRUE;
+ swapchain_information.oldSwapchain = VK_NULL_HANDLE;
+
+ vulkan_result (vkCreateSwapchainKHR (vulkan->logical_device, & swapchain_information, null, & vulkan->swapchain));
+
+ print ("/c Created /2Vulkan swapchain/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_images (vulkan_structure * vulkan) {
+ uint temporary = vulkan->image_count;
+
+ vulkan->time = tick_tock ();
+
+ vulkan_result (vkGetSwapchainImagesKHR (vulkan->logical_device, vulkan->swapchain, & temporary, null));
+
+ vulkan->images = allocate (vulkan->image_count * sizeof (VkImage));
+
+ vulkan_result (vkGetSwapchainImagesKHR (vulkan->logical_device, vulkan->swapchain, & temporary, vulkan->images));
+
+ print ("/c Created /2Vulkan swapchain images/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_image_views (vulkan_structure * vulkan) {
+ VkComponentMapping component_mapping = { 0 };
+ VkImageSubresourceRange image_subresource_range = { 0 };
+ VkImageViewCreateInfo image_view_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vulkan->image_views = allocate (vulkan->image_count * sizeof (VkImageView));
+
+ component_mapping.r = VK_COMPONENT_SWIZZLE_R;
+ component_mapping.g = VK_COMPONENT_SWIZZLE_G;
+ component_mapping.b = VK_COMPONENT_SWIZZLE_B;
+ component_mapping.a = VK_COMPONENT_SWIZZLE_A;
+
+ image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ image_subresource_range.baseMipLevel = 0;
+ image_subresource_range.levelCount = 1;
+ image_subresource_range.baseArrayLayer = 0;
+ image_subresource_range.layerCount = 1;
+
+ image_view_information.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ image_view_information.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ image_view_information.format = vulkan->format;
+ image_view_information.components = component_mapping;
+ image_view_information.subresourceRange = image_subresource_range;
+
+ for (uint index = 0; index < vulkan->image_count; ++index) {
+ image_view_information.image = vulkan->images [index];
+
+ vulkan_result (vkCreateImageView (vulkan->logical_device, & image_view_information, null, & vulkan->image_views [index]));
+ }
+
+ print ("/c Created /2Vulkan swapchain image views/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_semaphores (vulkan_structure * vulkan) {
+ VkSemaphoreCreateInfo semaphore_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vulkan->semaphore_set_1 = allocate (vulkan->image_count * sizeof (VkSemaphore));
+ vulkan->semaphore_set_2 = allocate (vulkan->image_count * sizeof (VkSemaphore));
+
+ semaphore_information.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+ for (uint index = 0; index < vulkan->image_count; ++index) {
+ vulkan_result (vkCreateSemaphore (vulkan->logical_device, & semaphore_information, null, & vulkan->semaphore_set_1 [index]));
+ vulkan_result (vkCreateSemaphore (vulkan->logical_device, & semaphore_information, null, & vulkan->semaphore_set_2 [index]));
+ }
+
+ print ("/c Created /2Vulkan synchronization semaphores/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_fences (vulkan_structure * vulkan) {
+ uint index = 0;
+
+ VkFenceCreateInfo fence_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vulkan->fence_set_1 = allocate (vulkan->image_count * sizeof (VkFence));
+
+ fence_information.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fence_information.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+ for (index = 0; index < vulkan->image_count; ++index) {
+ vulkan_result (vkCreateFence (vulkan->logical_device, & fence_information, null, & vulkan->fence_set_1 [index]));
+ }
+
+ print ("/c Created /2Vulkan synchronization fences/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_render_pass (vulkan_structure * vulkan) {
+ VkAttachmentDescription attachment_description = { 0 };
+ VkAttachmentReference attachment_reference = { 0 };
+ VkSubpassDescription subpass_description = { 0 };
+ VkSubpassDependency subpass_dependencies [2] = { { 0 } };
+ VkRenderPassCreateInfo render_pass_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ attachment_description.flags = 0;
+ attachment_description.format = vulkan->format;
+ attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
+ attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachment_description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attachment_description.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ attachment_reference.attachment = 0;
+ attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ subpass_description.flags = 0;
+ subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass_description.inputAttachmentCount = 0;
+ subpass_description.pInputAttachments = null;
+ subpass_description.colorAttachmentCount = 1;
+ subpass_description.pColorAttachments = & attachment_reference;
+ subpass_description.pResolveAttachments = null;
+ subpass_description.pDepthStencilAttachment = null;
+ subpass_description.preserveAttachmentCount = 0;
+ subpass_description.pPreserveAttachments = null;
+
+ subpass_dependencies [0].srcSubpass = VK_SUBPASS_EXTERNAL;
+ subpass_dependencies [0].dstSubpass = 0;
+ subpass_dependencies [0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ subpass_dependencies [0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ subpass_dependencies [0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ subpass_dependencies [0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ subpass_dependencies [0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
+ subpass_dependencies [1].srcSubpass = 0;
+ subpass_dependencies [1].dstSubpass = VK_SUBPASS_EXTERNAL;
+ subpass_dependencies [1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ subpass_dependencies [1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ subpass_dependencies [1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ subpass_dependencies [1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ subpass_dependencies [1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
+
+ render_pass_information.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ render_pass_information.attachmentCount = 1;
+ render_pass_information.pAttachments = & attachment_description;
+ render_pass_information.subpassCount = 1;
+ render_pass_information.pSubpasses = & subpass_description;
+ render_pass_information.dependencyCount = 2;
+ render_pass_information.pDependencies = subpass_dependencies;
+
+ vulkan_result (vkCreateRenderPass (vulkan->logical_device, & render_pass_information, null, & vulkan->render_pass));
+
+ print ("/c Created /2Vulkan render pass/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_descriptor_set_layout (vulkan_structure * vulkan) {
+ VkDescriptorSetLayoutBinding descriptor_set_layout_bindings [2] = { { 0 } };
+ VkDescriptorSetLayoutCreateInfo descriptor_set_layout_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ descriptor_set_layout_bindings [0].binding = 0;
+ descriptor_set_layout_bindings [0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descriptor_set_layout_bindings [0].descriptorCount = 1;
+ descriptor_set_layout_bindings [0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+ descriptor_set_layout_bindings [0].pImmutableSamplers = null;
+ descriptor_set_layout_bindings [1].binding = 1;
+ descriptor_set_layout_bindings [1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ descriptor_set_layout_bindings [1].descriptorCount = 1;
+ descriptor_set_layout_bindings [1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ descriptor_set_layout_bindings [1].pImmutableSamplers = null;
+
+ descriptor_set_layout_information.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ descriptor_set_layout_information.bindingCount = 2;
+ descriptor_set_layout_information.pBindings = descriptor_set_layout_bindings;
+
+ vulkan_result (vkCreateDescriptorSetLayout (vulkan->logical_device, & descriptor_set_layout_information, null,
+ & vulkan->descriptor_set_layout));
+
+ print ("/c Created /2 Vulkan descriptor layout/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_vertex_shader (vulkan_structure * vulkan) {
+ const uint vertex_shader_code [] = {
+ 0x07230203, 0x00010000, 0x000d000b, 0x00000028, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
+ 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
+ 0x000b000f, 0x00000000, 0x00000004, 0x6e69616d, 0x00000000, 0x0000000d, 0x00000012, 0x00000021,
+ 0x00000022, 0x00000024, 0x00000026, 0x00030003, 0x00000002, 0x000001c2, 0x000a0004, 0x475f4c47,
+ 0x4c474f4f, 0x70635f45, 0x74735f70, 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576,
+ 0x00080004, 0x475f4c47, 0x4c474f4f, 0x6e695f45, 0x64756c63, 0x69645f65, 0x74636572, 0x00657669,
+ 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060005, 0x0000000b, 0x505f6c67, 0x65567265,
+ 0x78657472, 0x00000000, 0x00060006, 0x0000000b, 0x00000000, 0x505f6c67, 0x7469736f, 0x006e6f69,
+ 0x00070006, 0x0000000b, 0x00000001, 0x505f6c67, 0x746e696f, 0x657a6953, 0x00000000, 0x00070006,
+ 0x0000000b, 0x00000002, 0x435f6c67, 0x4470696c, 0x61747369, 0x0065636e, 0x00070006, 0x0000000b,
+ 0x00000003, 0x435f6c67, 0x446c6c75, 0x61747369, 0x0065636e, 0x00030005, 0x0000000d, 0x00000000,
+ 0x00030005, 0x00000012, 0x00797869, 0x00030005, 0x00000021, 0x0076756f, 0x00030005, 0x00000022,
+ 0x00767569, 0x00030005, 0x00000024, 0x0000636f, 0x00030005, 0x00000026, 0x00006369, 0x00050048,
+ 0x0000000b, 0x00000000, 0x0000000b, 0x00000000, 0x00050048, 0x0000000b, 0x00000001, 0x0000000b,
+ 0x00000001, 0x00050048, 0x0000000b, 0x00000002, 0x0000000b, 0x00000003, 0x00050048, 0x0000000b,
+ 0x00000003, 0x0000000b, 0x00000004, 0x00030047, 0x0000000b, 0x00000002, 0x00040047, 0x00000012,
+ 0x0000001e, 0x00000000, 0x00040047, 0x00000021, 0x0000001e, 0x00000000, 0x00040047, 0x00000022,
+ 0x0000001e, 0x00000001, 0x00040047, 0x00000024, 0x0000001e, 0x00000001, 0x00040047, 0x00000026,
+ 0x0000001e, 0x00000002, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016,
+ 0x00000006, 0x00000020, 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040015, 0x00000008,
+ 0x00000020, 0x00000000, 0x0004002b, 0x00000008, 0x00000009, 0x00000001, 0x0004001c, 0x0000000a,
+ 0x00000006, 0x00000009, 0x0006001e, 0x0000000b, 0x00000007, 0x00000006, 0x0000000a, 0x0000000a,
+ 0x00040020, 0x0000000c, 0x00000003, 0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d, 0x00000003,
+ 0x00040015, 0x0000000e, 0x00000020, 0x00000001, 0x0004002b, 0x0000000e, 0x0000000f, 0x00000000,
+ 0x00040017, 0x00000010, 0x00000006, 0x00000002, 0x00040020, 0x00000011, 0x00000001, 0x00000010,
+ 0x0004003b, 0x00000011, 0x00000012, 0x00000001, 0x0004002b, 0x00000008, 0x00000013, 0x00000000,
+ 0x00040020, 0x00000014, 0x00000001, 0x00000006, 0x0004002b, 0x00000006, 0x00000017, 0x3f800000,
+ 0x0004002b, 0x00000006, 0x0000001c, 0x00000000, 0x00040020, 0x0000001e, 0x00000003, 0x00000007,
+ 0x00040020, 0x00000020, 0x00000003, 0x00000010, 0x0004003b, 0x00000020, 0x00000021, 0x00000003,
+ 0x0004003b, 0x00000011, 0x00000022, 0x00000001, 0x0004003b, 0x0000001e, 0x00000024, 0x00000003,
+ 0x00040020, 0x00000025, 0x00000001, 0x00000007, 0x0004003b, 0x00000025, 0x00000026, 0x00000001,
+ 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x00050041,
+ 0x00000014, 0x00000015, 0x00000012, 0x00000013, 0x0004003d, 0x00000006, 0x00000016, 0x00000015,
+ 0x00050083, 0x00000006, 0x00000018, 0x00000016, 0x00000017, 0x00050041, 0x00000014, 0x00000019,
+ 0x00000012, 0x00000009, 0x0004003d, 0x00000006, 0x0000001a, 0x00000019, 0x00050083, 0x00000006,
+ 0x0000001b, 0x0000001a, 0x00000017, 0x00070050, 0x00000007, 0x0000001d, 0x00000018, 0x0000001b,
+ 0x0000001c, 0x00000017, 0x00050041, 0x0000001e, 0x0000001f, 0x0000000d, 0x0000000f, 0x0003003e,
+ 0x0000001f, 0x0000001d, 0x0004003d, 0x00000010, 0x00000023, 0x00000022, 0x0003003e, 0x00000021,
+ 0x00000023, 0x0004003d, 0x00000007, 0x00000027, 0x00000026, 0x0003003e, 0x00000024, 0x00000027,
+ 0x000100fd, 0x00010038
+ };
+
+ VkShaderModuleCreateInfo vertex_shader_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vertex_shader_information.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ vertex_shader_information.codeSize = sizeof (vertex_shader_code);
+ vertex_shader_information.pCode = vertex_shader_code;
+
+ vulkan_result (vkCreateShaderModule (vulkan->logical_device, & vertex_shader_information, null, & vulkan->vertex_shader));
+
+ print ("/c Created /2Vulkan vertex shader module/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_fragment_shader (vulkan_structure * vulkan) {
+ const uint fragment_shader_code [] = {
+ 0x07230203, 0x00010000, 0x000d000b, 0x00000018, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
+ 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
+ 0x0008000f, 0x00000004, 0x00000004, 0x6e69616d, 0x00000000, 0x00000009, 0x00000011, 0x00000015,
+ 0x00030010, 0x00000004, 0x00000007, 0x00030003, 0x00000002, 0x000001c2, 0x000a0004, 0x475f4c47,
+ 0x4c474f4f, 0x70635f45, 0x74735f70, 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576,
+ 0x00080004, 0x475f4c47, 0x4c474f4f, 0x6e695f45, 0x64756c63, 0x69645f65, 0x74636572, 0x00657669,
+ 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00040005, 0x00000009, 0x69727073, 0x00006574,
+ 0x00060005, 0x0000000d, 0x74786574, 0x5f657275, 0x706d6173, 0x0072656c, 0x00030005, 0x00000011,
+ 0x00007675, 0x00030005, 0x00000015, 0x0000636f, 0x00040047, 0x00000009, 0x0000001e, 0x00000000,
+ 0x00040047, 0x0000000d, 0x00000022, 0x00000000, 0x00040047, 0x0000000d, 0x00000021, 0x00000001,
+ 0x00040047, 0x00000011, 0x0000001e, 0x00000000, 0x00040047, 0x00000015, 0x0000001e, 0x00000001,
+ 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016, 0x00000006, 0x00000020,
+ 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040020, 0x00000008, 0x00000003, 0x00000007,
+ 0x0004003b, 0x00000008, 0x00000009, 0x00000003, 0x00090019, 0x0000000a, 0x00000006, 0x00000001,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0003001b, 0x0000000b, 0x0000000a,
+ 0x00040020, 0x0000000c, 0x00000000, 0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d, 0x00000000,
+ 0x00040017, 0x0000000f, 0x00000006, 0x00000002, 0x00040020, 0x00000010, 0x00000001, 0x0000000f,
+ 0x0004003b, 0x00000010, 0x00000011, 0x00000001, 0x00040020, 0x00000014, 0x00000001, 0x00000007,
+ 0x0004003b, 0x00000014, 0x00000015, 0x00000001, 0x00050036, 0x00000002, 0x00000004, 0x00000000,
+ 0x00000003, 0x000200f8, 0x00000005, 0x0004003d, 0x0000000b, 0x0000000e, 0x0000000d, 0x0004003d,
+ 0x0000000f, 0x00000012, 0x00000011, 0x00050057, 0x00000007, 0x00000013, 0x0000000e, 0x00000012,
+ 0x0004003d, 0x00000007, 0x00000016, 0x00000015, 0x00050085, 0x00000007, 0x00000017, 0x00000013,
+ 0x00000016, 0x0003003e, 0x00000009, 0x00000017, 0x000100fd, 0x00010038
+ };
+
+ VkShaderModuleCreateInfo fragment_shader_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ fragment_shader_information.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ fragment_shader_information.codeSize = sizeof (fragment_shader_code);
+ fragment_shader_information.pCode = fragment_shader_code;
+
+ vulkan_result (vkCreateShaderModule (vulkan->logical_device, & fragment_shader_information, null, & vulkan->fragment_shader));
+
+ print ("/c Created /2Vulkan fragment shader module/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_pipeline_layout (vulkan_structure * vulkan) {
+ VkPipelineLayoutCreateInfo pipeline_layout_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ pipeline_layout_information.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipeline_layout_information.setLayoutCount = 1;
+ pipeline_layout_information.pSetLayouts = & vulkan->descriptor_set_layout;
+
+ vulkan_result (vkCreatePipelineLayout (vulkan->logical_device, & pipeline_layout_information, VK_NULL_HANDLE, & vulkan->pipeline_layout));
+
+ print ("/c Created /2Vulkan graphics pipeline layout/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_pipeline (vulkan_structure * vulkan) {
+ VkPipelineShaderStageCreateInfo pipeline_shader_stage_information [2] = { { 0 } };
+ VkPipelineInputAssemblyStateCreateInfo pipeline_input_assembly_state_information = { 0 };
+ VkVertexInputBindingDescription vertex_input_binding_description [1] = { { 0 } };
+ VkVertexInputAttributeDescription vertex_input_attribute_description [4] = { { 0 } };
+ VkPipelineVertexInputStateCreateInfo pipeline_vertex_input_state_information = { 0 };
+ VkViewport viewport = { 0 };
+ VkOffset2D scissor_offset = { 0 };
+ VkExtent2D scissor_extent = { 0 };
+ VkRect2D scissor = { 0 };
+ VkPipelineViewportStateCreateInfo pipeline_viewport_state_information = { 0 };
+ VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_information = { 0 };
+ VkPipelineMultisampleStateCreateInfo pipeline_multisample_state_information = { 0 };
+ VkPipelineColorBlendAttachmentState pipeline_colour_blend_attachment_state = { 0 };
+ VkPipelineColorBlendStateCreateInfo pipeline_colour_blend_state_information = { 0 };
+ VkGraphicsPipelineCreateInfo pipeline_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ pipeline_shader_stage_information [0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ pipeline_shader_stage_information [0].stage = VK_SHADER_STAGE_VERTEX_BIT;
+ pipeline_shader_stage_information [0].module = vulkan->vertex_shader;
+ pipeline_shader_stage_information [0].pName = "main";
+ pipeline_shader_stage_information [0].pSpecializationInfo = null;
+ pipeline_shader_stage_information [1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ pipeline_shader_stage_information [1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
+ pipeline_shader_stage_information [1].module = vulkan->fragment_shader;
+ pipeline_shader_stage_information [1].pName = "main";
+ pipeline_shader_stage_information [1].pSpecializationInfo = null;
+
+ pipeline_input_assembly_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ pipeline_input_assembly_state_information.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ pipeline_input_assembly_state_information.primitiveRestartEnable = VK_FALSE;
+
+ vertex_input_binding_description [0].binding = 0;
+ vertex_input_binding_description [0].stride = 32;
+ vertex_input_binding_description [0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+
+ vertex_input_attribute_description [0].binding = vertex_input_binding_description [0].binding;
+ vertex_input_attribute_description [0].location = 0;
+ vertex_input_attribute_description [0].format = VK_FORMAT_R32G32_SFLOAT;
+ vertex_input_attribute_description [0].offset = 0;
+ vertex_input_attribute_description [1].binding = vertex_input_binding_description [0].binding;
+ vertex_input_attribute_description [1].location = 1;
+ vertex_input_attribute_description [1].format = VK_FORMAT_R32G32_SFLOAT;
+ vertex_input_attribute_description [1].offset = 8;
+ vertex_input_attribute_description [2].binding = vertex_input_binding_description [0].binding;
+ vertex_input_attribute_description [2].location = 2;
+ vertex_input_attribute_description [2].format = VK_FORMAT_R32G32B32A32_SFLOAT;
+ vertex_input_attribute_description [2].offset = 16;
+
+ pipeline_vertex_input_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ pipeline_vertex_input_state_information.vertexBindingDescriptionCount = 1;
+ pipeline_vertex_input_state_information.pVertexBindingDescriptions = vertex_input_binding_description;
+ pipeline_vertex_input_state_information.vertexAttributeDescriptionCount = 3;
+ pipeline_vertex_input_state_information.pVertexAttributeDescriptions = vertex_input_attribute_description;
+
+ viewport.x = 0;
+ viewport.y = 0;
+ viewport.width = vulkan->width;
+ viewport.height = vulkan->height;
+ viewport.minDepth = 0;
+ viewport.maxDepth = 1;
+
+ scissor_offset.x = 0;
+ scissor_offset.y = 0;
+
+ scissor_extent.width = vulkan->width;
+ scissor_extent.height = vulkan->height;
+
+ scissor.offset = scissor_offset;
+ scissor.extent = scissor_extent;
+
+ pipeline_viewport_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ pipeline_viewport_state_information.viewportCount = 1;
+ pipeline_viewport_state_information.pViewports = & viewport;
+ pipeline_viewport_state_information.scissorCount = 1;
+ pipeline_viewport_state_information.pScissors = & scissor;
+
+ pipeline_rasterization_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ pipeline_rasterization_state_information.depthClampEnable = VK_FALSE;
+ pipeline_rasterization_state_information.rasterizerDiscardEnable = VK_FALSE;
+ pipeline_rasterization_state_information.polygonMode = VK_POLYGON_MODE_FILL;
+ pipeline_rasterization_state_information.cullMode = VK_CULL_MODE_BACK_BIT;
+ pipeline_rasterization_state_information.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ pipeline_rasterization_state_information.depthBiasEnable = VK_FALSE;
+ pipeline_rasterization_state_information.depthBiasConstantFactor = 0;
+ pipeline_rasterization_state_information.depthBiasClamp = 0;
+ pipeline_rasterization_state_information.depthBiasSlopeFactor = 0;
+ pipeline_rasterization_state_information.lineWidth = 1;
+
+ pipeline_multisample_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ pipeline_multisample_state_information.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ pipeline_multisample_state_information.sampleShadingEnable = VK_FALSE;
+ pipeline_multisample_state_information.minSampleShading = 1;
+ pipeline_multisample_state_information.pSampleMask = null;
+ pipeline_multisample_state_information.alphaToCoverageEnable = VK_FALSE;
+ pipeline_multisample_state_information.alphaToOneEnable = VK_FALSE;
+
+ pipeline_colour_blend_attachment_state.blendEnable = VK_TRUE;
+ pipeline_colour_blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
+ pipeline_colour_blend_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ pipeline_colour_blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD;
+ pipeline_colour_blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+ pipeline_colour_blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
+ pipeline_colour_blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD;
+ pipeline_colour_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT
+ | VK_COLOR_COMPONENT_G_BIT
+ | VK_COLOR_COMPONENT_B_BIT
+ | VK_COLOR_COMPONENT_A_BIT;
+
+ pipeline_colour_blend_state_information.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ pipeline_colour_blend_state_information.logicOpEnable = VK_FALSE;
+ pipeline_colour_blend_state_information.logicOp = VK_LOGIC_OP_COPY;
+ pipeline_colour_blend_state_information.attachmentCount = 1;
+ pipeline_colour_blend_state_information.pAttachments = & pipeline_colour_blend_attachment_state;
+
+ pipeline_information.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+ pipeline_information.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
+ pipeline_information.stageCount = 2;
+ pipeline_information.pStages = pipeline_shader_stage_information;
+ pipeline_information.pVertexInputState = & pipeline_vertex_input_state_information;
+ pipeline_information.pInputAssemblyState = & pipeline_input_assembly_state_information;
+ pipeline_information.pTessellationState = null;
+ pipeline_information.pViewportState = & pipeline_viewport_state_information;
+ pipeline_information.pRasterizationState = & pipeline_rasterization_state_information;
+ pipeline_information.pMultisampleState = & pipeline_multisample_state_information;
+ pipeline_information.pDepthStencilState = null;
+ pipeline_information.pColorBlendState = & pipeline_colour_blend_state_information;
+ pipeline_information.pDynamicState = null;
+ pipeline_information.layout = vulkan->pipeline_layout;
+ pipeline_information.renderPass = vulkan->render_pass;
+ pipeline_information.subpass = 0;
+ pipeline_information.basePipelineHandle = VK_NULL_HANDLE;
+ pipeline_information.basePipelineIndex = -1;
+
+ vulkan_result (vkCreateGraphicsPipelines (vulkan->logical_device, VK_NULL_HANDLE, 1, & pipeline_information, null, & vulkan->pipeline));
+
+ print ("/c Created /2Vulkan graphics pipeline/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_framebuffers (vulkan_structure * vulkan) {
+ VkFramebufferCreateInfo framebuffer_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vulkan->framebuffers = allocate (vulkan->image_count * sizeof (VkFramebuffer));
+
+ framebuffer_information.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ framebuffer_information.renderPass = vulkan->render_pass;
+ framebuffer_information.attachmentCount = 1;
+ framebuffer_information.width = vulkan->extent.width;
+ framebuffer_information.height = vulkan->extent.height;
+ framebuffer_information.layers = 1;
+
+ for (uint index = 0; index < vulkan->image_count; ++index) {
+ framebuffer_information.pAttachments = & vulkan->image_views [index];
+
+ vulkan_result (vkCreateFramebuffer (vulkan->logical_device, & framebuffer_information, null, & vulkan->framebuffers [index]));
+ }
+
+ print ("/c Created /2Vulkan framebuffers/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_command_pool (vulkan_structure * vulkan) {
+ VkCommandPoolCreateInfo command_pool_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ command_pool_information.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ command_pool_information.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ command_pool_information.queueFamilyIndex = vulkan->queue_index;
+
+ vulkan_result (vkCreateCommandPool (vulkan->logical_device, & command_pool_information, null, & vulkan->command_pool));
+
+ print ("/c Created /2Vulkan command pool/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_command_buffers (vulkan_structure * vulkan) {
+ VkCommandBufferAllocateInfo command_buffer_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vulkan->command_buffers = allocate (vulkan->image_count * sizeof (VkCommandBuffer));
+
+ command_buffer_information.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ command_buffer_information.commandPool = vulkan->command_pool;
+ command_buffer_information.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ command_buffer_information.commandBufferCount = vulkan->image_count;
+
+ vulkan_result (vkAllocateCommandBuffers (vulkan->logical_device, & command_buffer_information, vulkan->command_buffers));
+
+ print ("/c Allocated /2Vulkan command buffers/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_vertex_buffer (vulkan_structure * vulkan) {
+ VkBuffer transfer_buffer = VK_NULL_HANDLE;
+ VkDeviceMemory transfer_memory = VK_NULL_HANDLE;
+ void * transfer_void = null;
+
+ VkBufferCopy copy_information = { 0 };
+/*
+ vulkan->time = tick_tock ();
+*/
+ vulkan->vertex_size = vulkan->vertex_count * sizeof (* vulkan->vertex_data);
+
+ vulkan_create_buffer (vulkan, & transfer_buffer, & transfer_memory, vulkan->vertex_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
+
+ vulkan_result (vkMapMemory (vulkan->logical_device, transfer_memory, 0, vulkan->vertex_size, 0, & transfer_void));
+
+ memory_copy (transfer_void, vulkan->vertex_data, vulkan->vertex_size);
+
+ vulkan_create_buffer (vulkan, & vulkan->vertex_buffer, & vulkan->vertex_memory, vulkan->vertex_size,
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+
+ vulkan_begin_command_buffer (vulkan);
+
+ copy_information.srcOffset = 0;
+ copy_information.dstOffset = 0;
+ copy_information.size = vulkan->vertex_size;
+
+ vkCmdCopyBuffer (vulkan->transfer_buffer, transfer_buffer, vulkan->vertex_buffer, 1, & copy_information);
+
+ vulkan_end_command_buffer (vulkan);
+
+ vkDestroyBuffer (vulkan->logical_device, transfer_buffer, null);
+ vkFreeMemory (vulkan->logical_device, transfer_memory, null);
+
+ /*print ("/c Created /2Vulkan vertex buffer/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);*/
+}
+
+static void vulkan_create_index_buffer (vulkan_structure * vulkan) {
+ VkBuffer transfer_buffer = VK_NULL_HANDLE;
+ VkDeviceMemory transfer_memory = VK_NULL_HANDLE;
+ void * transfer_void = null;
+
+ VkBufferCopy copy_information = { 0 };
+/*
+ vulkan->time = tick_tock ();
+*/
+ vulkan->index_size = vulkan->index_count * sizeof (* vulkan->index_data);
+
+ vulkan_create_buffer (vulkan, & transfer_buffer, & transfer_memory, vulkan->index_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
+
+ vulkan_result (vkMapMemory (vulkan->logical_device, transfer_memory, 0, vulkan->index_size, 0, & transfer_void));
+
+ memory_copy (transfer_void, vulkan->index_data, vulkan->index_size);
+
+ vulkan_create_buffer (vulkan, & vulkan->index_buffer, & vulkan->index_memory, vulkan->index_size,
+ VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+
+ vulkan_begin_command_buffer (vulkan);
+
+ copy_information.srcOffset = 0;
+ copy_information.dstOffset = 0;
+ copy_information.size = vulkan->index_size;
+
+ vkCmdCopyBuffer (vulkan->transfer_buffer, transfer_buffer, vulkan->index_buffer, 1, & copy_information);
+
+ vulkan_end_command_buffer (vulkan);
+
+ vkDestroyBuffer (vulkan->logical_device, transfer_buffer, null);
+ vkFreeMemory (vulkan->logical_device, transfer_memory, null);
+/*
+ print ("/c Created /2Vulkan index buffer/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);*/
+}
+
+static void vulkan_create_image_buffer (vulkan_structure * vulkan) {
+ VkBuffer transfer_buffer = VK_NULL_HANDLE;
+ VkDeviceMemory transfer_memory = VK_NULL_HANDLE;
+ void * transfer_void = null;
+
+ VkExtent3D image_extent = { 0 };
+ VkImageCreateInfo image_information = { 0 };
+ VkMemoryRequirements memory_requirements = { 0 };
+ VkMemoryAllocateInfo memory_allocation_information = { 0 };
+ VkImageSubresourceLayers region_subresource_layers = { 0 };
+ VkOffset3D region_offset = { 0 };
+ VkExtent3D region_extent = { 0 };
+ VkBufferImageCopy region_copying_information = { 0 };
+ VkComponentMapping component_mapping = { 0 };
+ VkImageSubresourceRange image_subresource_range = { 0 };
+ VkImageViewCreateInfo image_view_information = { 0 };
+ VkImageMemoryBarrier image_memory_barrier = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vulkan_create_buffer (vulkan, & transfer_buffer, & transfer_memory, vulkan->layout_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
+
+ vulkan_result (vkMapMemory (vulkan->logical_device, transfer_memory, 0, vulkan->layout_size, 0, & transfer_void));
+
+ memory_copy (transfer_void, vulkan->layout_data, vulkan->layout_size);
+
+ image_extent.width = vulkan->layout_width;
+ image_extent.height = vulkan->layout_height;
+ image_extent.depth = 1;
+
+ image_information.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ image_information.imageType = VK_IMAGE_TYPE_2D;
+ image_information.format = vulkan->format;
+ image_information.extent = image_extent;
+ image_information.mipLevels = 1;
+ image_information.arrayLayers = 1;
+ image_information.samples = VK_SAMPLE_COUNT_1_BIT;
+ image_information.tiling = VK_IMAGE_TILING_OPTIMAL;
+ image_information.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+ image_information.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ image_information.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ image_subresource_range.baseMipLevel = 0;
+ image_subresource_range.levelCount = 1;
+ image_subresource_range.baseArrayLayer = 0;
+ image_subresource_range.layerCount = 1;
+
+ vulkan_result (vkCreateImage (vulkan->logical_device, & image_information, null, & vulkan->layout_image));
+
+ vkGetImageMemoryRequirements (vulkan->logical_device, vulkan->layout_image, & memory_requirements);
+
+ memory_allocation_information.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ memory_allocation_information.allocationSize = memory_requirements.size;
+ memory_allocation_information.memoryTypeIndex = vulkan_choose_memory_property (vulkan, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+
+ vulkan_result (vkAllocateMemory (vulkan->logical_device, & memory_allocation_information, null, & vulkan->layout_memory));
+
+ vulkan_result (vkBindImageMemory (vulkan->logical_device, vulkan->layout_image, vulkan->layout_memory, 0));
+
+ vulkan_begin_command_buffer (vulkan);
+
+ image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ image_memory_barrier.pNext = null;
+ image_memory_barrier.srcAccessMask = 0;
+ image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_memory_barrier.image = vulkan->layout_image;
+ image_memory_barrier.subresourceRange = image_subresource_range;
+
+ vkCmdPipelineBarrier (vulkan->transfer_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, null, 0, null,
+ 1, & image_memory_barrier);
+
+ vulkan_end_command_buffer (vulkan);
+
+ vulkan_begin_command_buffer (vulkan);
+
+ region_subresource_layers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ region_subresource_layers.mipLevel = 0;
+ region_subresource_layers.baseArrayLayer = 0;
+ region_subresource_layers.layerCount = 1;
+
+ region_offset.x = 0;
+ region_offset.y = 0;
+ region_offset.z = 0;
+
+ region_extent.width = vulkan->layout_width;
+ region_extent.height = vulkan->layout_height;
+ region_extent.depth = 1;
+
+ region_copying_information.bufferOffset = 0;
+ region_copying_information.bufferRowLength = 0;
+ region_copying_information.bufferImageHeight = 0;
+ region_copying_information.imageSubresource = region_subresource_layers;
+ region_copying_information.imageOffset = region_offset;
+ region_copying_information.imageExtent = region_extent;
+
+ vkCmdCopyBufferToImage (vulkan->transfer_buffer, transfer_buffer, vulkan->layout_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
+ & region_copying_information);
+
+ vulkan_end_command_buffer (vulkan);
+
+ vulkan_begin_command_buffer (vulkan);
+
+ image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ image_memory_barrier.pNext = null;
+ image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_memory_barrier.image = vulkan->layout_image;
+ image_memory_barrier.subresourceRange = image_subresource_range;
+
+ vkCmdPipelineBarrier (vulkan->transfer_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, null, 0,
+ null, 1, & image_memory_barrier);
+
+ vulkan_end_command_buffer (vulkan);
+
+ component_mapping.r = VK_COMPONENT_SWIZZLE_R;
+ component_mapping.g = VK_COMPONENT_SWIZZLE_G;
+ component_mapping.b = VK_COMPONENT_SWIZZLE_B;
+ component_mapping.a = VK_COMPONENT_SWIZZLE_A;
+
+ image_view_information.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ image_view_information.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ image_view_information.format = vulkan->format;
+ image_view_information.components = component_mapping;
+ image_view_information.subresourceRange = image_subresource_range;
+ image_view_information.image = vulkan->layout_image;
+
+ vulkan_result (vkCreateImageView (vulkan->logical_device, & image_view_information, null, & vulkan->layout_image_view));
+
+ vkDestroyBuffer (vulkan->logical_device, transfer_buffer, null);
+ vkFreeMemory (vulkan->logical_device, transfer_memory, null);
+
+ print ("/c Created /2Vulkan image layout buffer/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_sampler (vulkan_structure * vulkan) {
+ VkSamplerCreateInfo sampler_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ sampler_information.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ sampler_information.magFilter = VK_FILTER_NEAREST;
+ sampler_information.minFilter = VK_FILTER_NEAREST;
+ sampler_information.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ sampler_information.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ sampler_information.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ sampler_information.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ sampler_information.mipLodBias = 0;
+ sampler_information.anisotropyEnable = VK_FALSE;
+ sampler_information.maxAnisotropy = 1;
+ sampler_information.compareEnable = VK_FALSE;
+ sampler_information.compareOp = VK_COMPARE_OP_ALWAYS;
+ sampler_information.minLod = 0;
+ sampler_information.maxLod = 0;
+ sampler_information.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
+ sampler_information.unnormalizedCoordinates = VK_FALSE;
+
+ vulkan_result (vkCreateSampler (vulkan->logical_device, & sampler_information, null, & vulkan->sampler));
+
+ print ("/c Created /2Vulkan sampler/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_descriptor_pool (vulkan_structure * vulkan) {
+ VkDescriptorPoolSize descriptor_pool_sizes [2] = { { 0 } };
+ VkDescriptorPoolCreateInfo descriptor_pool_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descriptor_pool_sizes[0].descriptorCount = vulkan->image_count;
+ descriptor_pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ descriptor_pool_sizes[1].descriptorCount = vulkan->image_count;
+
+ descriptor_pool_information.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descriptor_pool_information.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
+ descriptor_pool_information.maxSets = vulkan->image_count;
+ descriptor_pool_information.poolSizeCount = 2;
+ descriptor_pool_information.pPoolSizes = descriptor_pool_sizes;
+
+ vulkan_result (vkCreateDescriptorPool (vulkan->logical_device, & descriptor_pool_information, null, & vulkan->descriptor_pool));
+
+ print ("/c Created /2Vulkan descriptor pool/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_create_descriptor_sets (vulkan_structure * vulkan) {
+ VkDescriptorSetAllocateInfo descriptor_set_allocation_information = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ vulkan->descriptor_set_layouts = allocate (vulkan->image_count * sizeof (VkDescriptorSetLayout));
+
+ for (uint index = 0; index < vulkan->image_count; ++index) {
+ vulkan->descriptor_set_layouts [index] = vulkan->descriptor_set_layout;
+ }
+
+ descriptor_set_allocation_information.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ descriptor_set_allocation_information.descriptorPool = vulkan->descriptor_pool;
+ descriptor_set_allocation_information.descriptorSetCount = vulkan->image_count;
+ descriptor_set_allocation_information.pSetLayouts = vulkan->descriptor_set_layouts;
+
+ vulkan->descriptor_sets = allocate (vulkan->image_count * sizeof (VkDescriptorSet));
+
+ vulkan_result (vkAllocateDescriptorSets (vulkan->logical_device, & descriptor_set_allocation_information, vulkan->descriptor_sets));
+
+ print ("/c Allocated /2Vulkan descriptor sets/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_record_descriptor_sets (vulkan_structure * vulkan) {
+ VkDescriptorBufferInfo descriptor_buffer_information = { 0 };
+ VkDescriptorImageInfo descriptor_image_information = { 0 };
+ VkWriteDescriptorSet write_descriptor_set = { 0 };
+
+ vulkan->time = tick_tock ();
+
+ descriptor_image_information.sampler = vulkan->sampler;
+ descriptor_image_information.imageView = vulkan->layout_image_view;
+ descriptor_image_information.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ write_descriptor_set.dstBinding = 1;
+ write_descriptor_set.dstArrayElement = 0;
+ write_descriptor_set.descriptorCount = 1;
+ write_descriptor_set.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ write_descriptor_set.pImageInfo = & descriptor_image_information;
+ write_descriptor_set.pBufferInfo = null;
+
+ for (uint index = 0; index < vulkan->image_count; ++index) {
+ write_descriptor_set.dstSet = vulkan->descriptor_sets [index];
+
+ vkUpdateDescriptorSets (vulkan->logical_device, 1, & write_descriptor_set, 0, null);
+ }
+
+ print ("/c Recorded /2Vulkan descriptor sets/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);
+}
+
+static void vulkan_record_command_buffers (vulkan_structure * vulkan, int clear_colour, int frame) {
+ uint index = 0;
+
+ VkCommandBufferBeginInfo command_buffer_begin_information = { 0 };
+ //~VkImageSubresourceRange image_subresource_range = { 0 };
+ VkClearValue clear_value = { 0 };
+ VkOffset2D render_area_offset = { 0 };
+ VkExtent2D render_area_extent = { 0 };
+ VkRect2D render_area = { 0 };
+ VkRenderPassBeginInfo render_pass_begin_information = { 0 };
+ VkDeviceSize vertex_offset = 0;
+
+ VkClearColorValue clear_colour_value = { {
+ (float) ((clear_colour & 0xff000000) >> 24) / 255,
+ (float) ((clear_colour & 0x00ff0000) >> 16) / 255,
+ (float) ((clear_colour & 0x0000ff00) >> 8) / 255,
+ (float) ((clear_colour & 0x000000ff) >> 0) / 255
+ } };
+
+ (void) frame;
+/*
+ vulkan->time = tick_tock ();
+*/
+ command_buffer_begin_information.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ command_buffer_begin_information.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
+
+ //~image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ //~image_subresource_range.baseMipLevel = 0;
+ //~image_subresource_range.levelCount = 1;
+ //~image_subresource_range.baseArrayLayer = 0;
+ //~image_subresource_range.layerCount = 1;
+
+ clear_value.color = clear_colour_value;
+
+ render_area_offset.x = 0;
+ render_area_offset.y = 0;
+
+ render_area_extent.width = vulkan->extent.width;
+ render_area_extent.height = vulkan->extent.height;
+
+ render_area.offset = render_area_offset;
+ render_area.extent = render_area_extent;
+
+ render_pass_begin_information.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ render_pass_begin_information.pNext = null;
+ render_pass_begin_information.renderPass = vulkan->render_pass;
+ render_pass_begin_information.renderArea = render_area;
+ render_pass_begin_information.clearValueCount = 1;
+ render_pass_begin_information.pClearValues = & clear_value;
+
+ for (index = 0; index < vulkan->image_count; ++index) {
+ render_pass_begin_information.framebuffer = vulkan->framebuffers [index];
+
+ vulkan_result (vkBeginCommandBuffer (vulkan->command_buffers [index], & command_buffer_begin_information));
+
+ vkCmdBeginRenderPass (vulkan->command_buffers [index], & render_pass_begin_information, VK_SUBPASS_CONTENTS_INLINE);
+
+ vkCmdBindPipeline (vulkan->command_buffers [index], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan->pipeline);
+
+ vkCmdBindVertexBuffers (vulkan->command_buffers [index], 0, 1, & vulkan->vertex_buffer, & vertex_offset);
+
+ vkCmdBindIndexBuffer (vulkan->command_buffers [index], vulkan->index_buffer, 0, VK_INDEX_TYPE_UINT32);
+
+ vkCmdBindDescriptorSets (vulkan->command_buffers [index], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan->pipeline_layout, 0, 1,
+ vulkan->descriptor_sets, 0, null);
+
+ vkCmdDrawIndexed (vulkan->command_buffers [index], vulkan->index_count, 1, 0, 0, 0);
+
+ vkCmdEndRenderPass (vulkan->command_buffers [index]);
+
+ vulkan_result (vkEndCommandBuffer (vulkan->command_buffers [index]));
+ }
+/*
+ render_pass_begin_information.framebuffer = vulkan_framebuffers [frame];
+
+ vulkan_result (vkBeginCommandBuffer (vulkan_command_buffers [frame], & command_buffer_begin_information));
+
+ vkCmdBeginRenderPass (vulkan_command_buffers [frame], & render_pass_begin_information, VK_SUBPASS_CONTENTS_INLINE);
+
+ vkCmdBindPipeline (vulkan_command_buffers [frame], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_pipeline);
+
+ vkCmdBindVertexBuffers (vulkan_command_buffers [frame], 0, 1, & vulkan_vertex_buffer, & vertex_offset);
+
+ vkCmdBindIndexBuffer (vulkan_command_buffers [frame], vulkan_index_buffer, 0, VK_INDEX_TYPE_UINT32);
+
+ vkCmdBindDescriptorSets (vulkan_command_buffers [frame], VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_pipeline_layout, 0, 1,
+ vulkan_descriptor_sets, 0, null);
+
+ vkCmdDrawIndexed (vulkan_command_buffers [frame], vulkan_index_count, 1, 0, 0, 0);
+
+ vkCmdEndRenderPass (vulkan_command_buffers [frame]);
+
+ vulkan_result (vkEndCommandBuffer (vulkan_command_buffers [frame]));
+*/
+ vulkan_result (vkQueueWaitIdle (vulkan->queue));
+ vulkan_result (vkDeviceWaitIdle (vulkan->logical_device));
+
+ /*print ("/c Recorded /2Vulkan command buffers/-.\n");
+ print ("/c Time approximation: /6%i/-\n", tick_tock () - vulkan->time);*/
+}
+
+static uint vulkan_import_sprite (vulkan_structure * vulkan, uint * data, uint width, uint height) {
+ fatal_failure (vulkan->active == true, "vulkan_import_sprite: Failed to import sprite, engine was already configured.");
+ fatal_failure (data == null, "vulkan_import_sprite: Failed to import sprite, data is null pointer.");
+ fatal_failure (width <= 0, "vulkan_import_sprite: Failed to import sprite, width is equal or below zero.");
+ fatal_failure (height <= 0, "vulkan_import_sprite: Failed to import sprite, height is equal or below zero.");
+
+ ++vulkan->sprite_count;
+
+ vulkan->sprite_data = reallocate (vulkan->sprite_data, vulkan->sprite_count * sizeof (* vulkan->sprite_data));
+ vulkan->sprite_width = reallocate (vulkan->sprite_width, vulkan->sprite_count * sizeof (* vulkan->sprite_width));
+ vulkan->sprite_height = reallocate (vulkan->sprite_height, vulkan->sprite_count * sizeof (* vulkan->sprite_height));
+ vulkan->sprite_u = reallocate (vulkan->sprite_u, vulkan->sprite_count * sizeof (* vulkan->sprite_u));
+ vulkan->sprite_v = reallocate (vulkan->sprite_v, vulkan->sprite_count * sizeof (* vulkan->sprite_v));
+
+ vulkan->sprite_data [vulkan->sprite_count - 1] = data;
+ vulkan->sprite_width [vulkan->sprite_count - 1] = width;
+ vulkan->sprite_height [vulkan->sprite_count - 1] = height;
+ vulkan->sprite_u [vulkan->sprite_count - 1] = 0;
+ vulkan->sprite_v [vulkan->sprite_count - 1] = 0;
+
+ return (vulkan->sprite_count - 1);
+}
+
+static uint vulkan_import_font (vulkan_structure * vulkan, uint * data, uint image_width, uint image_height, char begin, char end, uint empty) {
+ uint pointer = 0;
+ char index = 0;
+ uint width = 0;
+ uint height = 0;
+ uint x = 0;
+ uint y = 0;
+
+ uint * buffer = null;
+
+ ++vulkan->font_count;
+
+ vulkan->font_index = reallocate (vulkan->font_index, vulkan->font_count * sizeof (* vulkan->font_index));
+ vulkan->font_width = reallocate (vulkan->font_width, vulkan->font_count * sizeof (* vulkan->font_width));
+ vulkan->font_height = reallocate (vulkan->font_height, vulkan->font_count * sizeof (* vulkan->font_height));
+ vulkan->font_begin = reallocate (vulkan->font_begin, vulkan->font_count * sizeof (* vulkan->font_begin));
+ vulkan->font_end = reallocate (vulkan->font_end, vulkan->font_count * sizeof (* vulkan->font_end));
+
+ vulkan->font_begin [vulkan->font_count - 1] = begin;
+ vulkan->font_end [vulkan->font_count - 1] = end;
+
+ vulkan->font_index [vulkan->font_count - 1] = allocate ((end - begin + 1) * sizeof (* * vulkan->font_index));
+ vulkan->font_width [vulkan->font_count - 1] = allocate ((end - begin + 1) * sizeof (* * vulkan->font_width));
+ vulkan->font_height [vulkan->font_count - 1] = allocate ((end - begin + 1) * sizeof (* * vulkan->font_height));
+
+ for (index = begin; index <= end; ++index) {
+ for ( ; data [pointer] == empty; ++pointer);
+ for (width = 0; data [pointer + width] != empty; ++width);
+ for (height = 0; data [pointer + height * image_width] != empty; ++height);
+
+ buffer = allocate (width * height * sizeof (* buffer));
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ buffer [y * width + x] = data [pointer + (y * image_width) + x];
+ }
+ }
+
+ vulkan->font_index [vulkan->font_count - 1] [index - begin] = vulkan_import_sprite (vulkan, buffer, width, height);
+ vulkan->font_width [vulkan->font_count - 1] [index - begin] = width;
+ vulkan->font_height [vulkan->font_count - 1] [index - begin] = height;
+
+ pointer += width;
+
+ for (; data [pointer] == empty; ++pointer);
+
+ if (pointer % image_width == 2) {
+ pointer += height * image_width;
+ }
+ }
+
+ return (vulkan->font_count - 1);
+}
+
+static void vulkan_bundle_layout (vulkan_structure * vulkan) {
+ uint * order = null;
+
+ vulkan->layout_size = vulkan->layout_width * vulkan->layout_height * (uint) sizeof (* vulkan->layout_data);
+
+ vulkan->layout_data = allocate (vulkan->layout_size);
+
+ order = allocate (vulkan->sprite_count * sizeof (* order));
+
+ for (uint index = 0; index < vulkan->sprite_count; ++index) {
+ order [index] = index;
+ }
+
+ for (uint index = 0; index < vulkan->sprite_count; ++index) {
+ for (uint subindex = 0; subindex < vulkan->sprite_count; ++subindex) {
+ if (vulkan->sprite_height [order [index]] < vulkan->sprite_height [order [subindex]]) {
+ int temporary = order [index];
+
+ order [index] = order [subindex];
+ order [subindex] = temporary;
+ }
+ }
+ }
+
+ for (uint index = 0; index < vulkan->sprite_count; ++index) {
+ uint x = 0;
+ uint y = 0;
+ uint u = 0;
+ uint v = 0;
+
+
+ if (u + vulkan->sprite_width [order [index]] >= vulkan->layout_width) {
+ u *= 0;
+ v += vulkan->sprite_height [order [index]];
+ }
+
+ vulkan->sprite_u [order [index]] = (float) u / (float) vulkan->layout_width;
+ vulkan->sprite_v [order [index]] = (float) v / (float) vulkan->layout_height;
+
+ for (uint y = 0; y < vulkan->sprite_height [order [index]]; ++y) {
+ for (uint x = 0; x < vulkan->sprite_width [order [index]]; ++x) {
+ uint destination = (v + y) * vulkan->layout_width + (u + x);
+ uint source = y * vulkan->sprite_width [order [index]] + x;
+
+ vulkan->layout_data [destination] = vulkan->sprite_data [order [index]] [source];
+ }
+ }
+
+ u += vulkan->sprite_width [order [index]];
+
+ vulkan->sprite_data [order [index]] = deallocate (vulkan->sprite_data [order [index]]);
+ }
+
+ vulkan->sprite_data = deallocate (vulkan->sprite_data);
+ order = deallocate (order);
+}
+
+static void vulkan_configure (vulkan_structure * vulkan, int width, int height, const char * application) {
+ int index = 0;
+
+ uint * dumb_buffer = null;
+
+ if (vulkan->active == true) {
+ return;
+ }
+
+ vulkan->width = width;
+ vulkan->height = height;
+
+ vulkan->pixel_width = (float) 2 / (float) width;
+ vulkan->pixel_height = (float) 2 / (float) height;
+
+ dumb_buffer = allocate (256 * sizeof (* dumb_buffer));
+
+ for (index = 0; index < 256; ++index) {
+ dumb_buffer [index] = ~0;
+ }
+
+ vulkan_import_sprite (vulkan, dumb_buffer, 16, 16);
+
+ vulkan_bundle_layout (vulkan);
+
+ vulkan->vertex_data = allocate (vulkan->vertex_limit * sizeof (* vulkan->vertex_data));
+ vulkan->index_data = allocate (vulkan->index_limit * sizeof (* vulkan->index_data));
+
+ vulkan_create_window (vulkan, application);
+ vulkan_create_instance (vulkan, application);
+ print ("/c Variable : width = %i\n", vulkan->width);
+ print ("/c Variable : height = %i\n", vulkan->height);
+ print ("/c Variable : sprite_count = %i\n", vulkan->sprite_count);
+ print ("/c Variable : font_count = %i\n", vulkan->font_count);
+ print ("/c Variable : gameplay_framerate = %i\n", vulkan->gameplay_framerate);
+ print ("/c Variable : animation_framerate = %i\n", vulkan->animation_framerate);
+ print ("/c Variable : vertex_limit = %i\n", vulkan->vertex_limit);
+ print ("/c Variable : index_limit = %i\n", vulkan->index_limit);
+ print ("/c Variable : layout_size = %i\n", vulkan->layout_size);
+ print ("/c Variable : layout_width = %i\n", vulkan->layout_width);
+ print ("/c Variable : layout_height = %i\n", vulkan->layout_height);
+
+ vulkan_create_surface (vulkan);
+ vulkan_create_device (vulkan);
+ vulkan_choose_extent (vulkan);
+ vulkan_choose_format (vulkan);
+ vulkan_choose_present_mode (vulkan);
+ vulkan_create_swapchain (vulkan);
+ vulkan_create_images (vulkan);
+ vulkan_create_image_views (vulkan);
+ vulkan_create_semaphores (vulkan);
+ vulkan_create_fences (vulkan);
+ vulkan_create_render_pass (vulkan);
+ vulkan_create_descriptor_set_layout (vulkan);
+ vulkan_create_vertex_shader (vulkan);
+ vulkan_create_fragment_shader (vulkan);
+ vulkan_create_pipeline_layout (vulkan);
+ vulkan_create_pipeline (vulkan);
+ vulkan_create_framebuffers (vulkan);
+ vulkan_create_command_pool (vulkan);
+ vulkan_create_command_buffers (vulkan);
+ vulkan_create_image_buffer (vulkan);
+ vulkan_create_sampler (vulkan);
+ vulkan_create_descriptor_pool (vulkan);
+ vulkan_create_descriptor_sets (vulkan);
+ vulkan_record_descriptor_sets (vulkan);
+
+ vulkan->active = true;
+}
+/*
+static void vulkan_reconfigure (void) {
+ int index;
+
+ vulkan_result (vkQueueWaitIdle (vulkan_queue));
+ vulkan_result (vkDeviceWaitIdle (vulkan_logical_device));
+
+ for (index = 0; index < vulkan_image_count; ++index) {
+ vkDestroyFramebuffer (vulkan_logical_device, vulkan_framebuffers [index], null);
+ }
+
+ vulkan_framebuffers = deallocate (vulkan_framebuffers);
+
+ for (index = 0; index < vulkan_image_count; ++index) {
+ vkDestroyImageView (vulkan_logical_device, vulkan_image_views [index], null);
+ }
+
+ vulkan_image_views = deallocate (vulkan_image_views);
+
+ vkDestroySwapchainKHR (vulkan_logical_device, vulkan_swapchain, null);
+
+ vulkan_images = deallocate (vulkan_images);
+
+ vulkan_choose_extent ();
+ vulkan_choose_format ();
+ vulkan_choose_present_mode ();
+ vulkan_create_swapchain ();
+ vulkan_create_images ();
+ vulkan_create_image_views ();
+ vulkan_create_framebuffers ();
+
+ vulkan_result (vkQueueWaitIdle (vulkan_queue));
+ vulkan_result (vkDeviceWaitIdle (vulkan_logical_device));
+
+ vulkan_reconfigure_active = false;
+}
+*/
+static void vulkan_render_core (vulkan_structure * vulkan, int sprite, int x, int y, int u, int v, int width, int height,
+ float scale_x, float scale_y, int flip_x, int flip_y,
+ int colour_0, uint colour_1, uint colour_2, uint colour_3) {
+ float screen_x = x * vulkan->pixel_width;
+ float screen_y = y * vulkan->pixel_height;
+
+ float unwrap_x = vulkan->sprite_u [sprite] + (float) u / vulkan->layout_width;
+ float unwrap_y = vulkan->sprite_v [sprite] + (float) v / vulkan->layout_height;
+
+ float screen_width = (float) width * vulkan->pixel_width * scale_x;
+ float screen_height = (float) height * vulkan->pixel_height * scale_y;
+
+ float unwrap_width = (float) width / vulkan->layout_width;
+ float unwrap_height = (float) height / vulkan->layout_height;
+
+ fatal_failure (vulkan->vertex_count + 32 >= vulkan->vertex_limit, "Reached vertex limit.");
+ fatal_failure (vulkan->index_count + 6 >= vulkan->index_limit, "Reached index limit.");
+
+ vulkan->vertex_data [vulkan->vertex_count + 0] = screen_x;
+ vulkan->vertex_data [vulkan->vertex_count + 1] = screen_y;
+ vulkan->vertex_data [vulkan->vertex_count + 2] = unwrap_x + unwrap_width * (flip_y != 0);
+ vulkan->vertex_data [vulkan->vertex_count + 3] = unwrap_y + unwrap_height * (flip_x != 0);
+ vulkan->vertex_data [vulkan->vertex_count + 4] = (float) ((colour_0 >> 24) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 5] = (float) ((colour_0 >> 16) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 6] = (float) ((colour_0 >> 8) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 7] = (float) ((colour_0 >> 0) & 0xff) / 255;
+
+ vulkan->vertex_data [vulkan->vertex_count + 8] = screen_x + screen_width;
+ vulkan->vertex_data [vulkan->vertex_count + 9] = screen_y;
+ vulkan->vertex_data [vulkan->vertex_count + 10] = unwrap_x + unwrap_width * (flip_y == 0);
+ vulkan->vertex_data [vulkan->vertex_count + 11] = unwrap_y + unwrap_height * (flip_x != 0);
+ vulkan->vertex_data [vulkan->vertex_count + 12] = (float) ((colour_1 >> 24) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 13] = (float) ((colour_1 >> 16) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 14] = (float) ((colour_1 >> 8) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 15] = (float) ((colour_1 >> 0) & 0xff) / 255;
+
+ vulkan->vertex_data [vulkan->vertex_count + 16] = screen_x;
+ vulkan->vertex_data [vulkan->vertex_count + 17] = screen_y + screen_height;
+ vulkan->vertex_data [vulkan->vertex_count + 18] = unwrap_x + unwrap_width * (flip_y != 0);
+ vulkan->vertex_data [vulkan->vertex_count + 19] = unwrap_y + unwrap_height * (flip_x == 0);
+ vulkan->vertex_data [vulkan->vertex_count + 20] = (float) ((colour_2 >> 24) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 21] = (float) ((colour_2 >> 16) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 22] = (float) ((colour_2 >> 8) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 23] = (float) ((colour_2 >> 0) & 0xff) / 255;
+
+ vulkan->vertex_data [vulkan->vertex_count + 24] = screen_x + screen_width;
+ vulkan->vertex_data [vulkan->vertex_count + 25] = screen_y + screen_height;
+ vulkan->vertex_data [vulkan->vertex_count + 26] = unwrap_x + unwrap_width * (flip_y == 0);
+ vulkan->vertex_data [vulkan->vertex_count + 27] = unwrap_y + unwrap_height * (flip_x == 0);
+ vulkan->vertex_data [vulkan->vertex_count + 28] = (float) ((colour_3 >> 24) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 29] = (float) ((colour_3 >> 16) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 30] = (float) ((colour_3 >> 8) & 0xff) / 255;
+ vulkan->vertex_data [vulkan->vertex_count + 31] = (float) ((colour_3 >> 0) & 0xff) / 255;
+
+ vulkan->index_data [vulkan->index_count + 0] = (vulkan->vertex_count >> 3) + 0;
+ vulkan->index_data [vulkan->index_count + 1] = (vulkan->vertex_count >> 3) + 1;
+ vulkan->index_data [vulkan->index_count + 2] = (vulkan->vertex_count >> 3) + 2;
+ vulkan->index_data [vulkan->index_count + 3] = (vulkan->vertex_count >> 3) + 1;
+ vulkan->index_data [vulkan->index_count + 4] = (vulkan->vertex_count >> 3) + 3;
+ vulkan->index_data [vulkan->index_count + 5] = (vulkan->vertex_count >> 3) + 2;
+
+ vulkan->vertex_count += 32;
+ vulkan->index_count += 6;
+}
+
+static void vulkan_render_sprite (vulkan_structure * vulkan, int sprite, int x, int y, uint colour) {
+ vulkan_render_core (vulkan, sprite, x, y, 0, 0, vulkan->sprite_width [sprite], vulkan->sprite_height [sprite], 1.0, 1.0, 0, 0, colour, colour, colour,colour);
+}
+
+static void vulkan_render_sprite_scale (vulkan_structure * vulkan, int sprite, int x, int y, float scale, uint colour) {
+ vulkan_render_core (vulkan, sprite, x, y, 0, 0, vulkan->sprite_width [sprite], vulkan->sprite_height [sprite], scale, scale, 0, 0, colour, colour, colour,colour);
+}
+
+static void vulkan_render_sprite_crop (vulkan_structure * vulkan, int sprite, int x, int y, int u, int v, int width, int height, uint colour) {
+ vulkan_render_core (vulkan, sprite, x, y, u, v, width, height, 1.0, 1.0, 0, 0, colour, colour, colour, colour);
+}
+
+static void vulkan_render_rectangle (vulkan_structure * vulkan, int x, int y, int width, int height, uint colour) {
+ vulkan_render_core (vulkan, vulkan->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16, (float) height / 16, 0, 0, colour, colour, colour, colour);
+}
+
+static void vulkan_render_rectangle_gradient_v (vulkan_structure * vulkan, int x, int y, int width, int height, uint colour_up, uint colour_down) {
+ vulkan_render_core (vulkan, vulkan->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16, (float) height / 16, 0, 0, colour_up, colour_up, colour_down, colour_down);
+}
+
+static void vulkan_render_rectangle_gradient_h (vulkan_structure * vulkan, int x, int y, int width, int height, uint colour_left, uint colour_right) {
+ vulkan_render_core (vulkan, vulkan->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16, (float) height / 16, 0, 0, colour_left, colour_right, colour_left, colour_right);
+}
+
+static int vulkan_string_width (vulkan_structure * vulkan, const char * string, int font, float scale) {
+ int length = 0;
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ int character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
+/*
+ if (string [index] == '\t') {
+ length += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
+ continue;
+ }
+
+ if (string [index] == '\n') {
+ continue;
+ }
+*/
+ length += vulkan->sprite_width [character] * scale;
+ }
+
+ return (length);
+}
+
+static void vulkan_render_string (vulkan_structure * vulkan, const char * string, int font, int x, int y, uint colour) {
+ int offset = x;
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ int character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
+
+ if (string [index] == '\t') {
+ x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
+ continue;
+ }
+
+ if (string [index] == '\n') {
+ x = offset;
+ y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
+ continue;
+ }
+
+ vulkan_render_sprite (vulkan, character, x, y, colour);
+
+ x += vulkan->sprite_width [character];
+ }
+}
+
+static void vulkan_render_string_scale (vulkan_structure * vulkan, const char * string, int font, int x, int y, float scale, uint colour) {
+ int offset = x;
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ int character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
+
+ if (string [index] == '\t') {
+ x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
+ continue;
+ }
+
+ if (string [index] == '\n') {
+ x = offset;
+ y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
+ continue;
+ }
+
+ vulkan_render_core (vulkan, character, x, y, 0, 0, vulkan->sprite_width [character], vulkan->sprite_height [character], scale, scale,
+ 0, 0, colour, colour, colour, colour);
+
+ x += vulkan->sprite_width [character];
+ }
+}
+
+static void vulkan_render_string_offset (vulkan_structure * vulkan, const char * string, uint length, uint font, uint offset, int * x, int * y, uint colour) {
+ for (uint index = 0; (string [index] != '\0') && (index < length); ++index) {
+ uint character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
+
+ if (string [index] == '\t') {
+ * x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
+ continue;
+ }
+
+ if (string [index] == '\n') {
+ * x = offset;
+ * y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]];
+ continue;
+ }
+
+ vulkan_render_sprite (vulkan, character, * x, * y, colour);
+
+ * x += vulkan->sprite_width [character];
+ }
+}
+
+static void vulkan_render_string_gradient_v (vulkan_structure * vulkan, const char * string, int font, int x, int y, float scale, uint colour_up, uint colour_down) {
+ int offset = x;
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ uint character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
+
+ if (string [index] == '\t') {
+ x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]] * scale;
+ continue;
+ }
+
+ if (string [index] == '\n') {
+ x = offset;
+ y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]] * scale;
+ continue;
+ }
+
+ vulkan_render_core (vulkan, character, x, y, 0, 0, vulkan->sprite_width [character], vulkan->sprite_height [character], scale, scale,
+ 0, 0, colour_up, colour_up, colour_down, colour_down);
+
+ x += vulkan->sprite_width [character] * scale;
+ }
+}
+
+static void vulkan_render_string_gradient_h (vulkan_structure * vulkan, const char * string, int font, int x, int y, float scale, uint colour_left, uint colour_right) {
+ int offset = x;
+
+ for (uint index = 0; string [index] != '\0'; ++index) {
+ uint character = vulkan->font_index [font] [string [index] - vulkan->font_begin [font]];
+
+ if (string [index] == '\t') {
+ x += 8 * vulkan->sprite_width [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]] * scale;
+ continue;
+ }
+
+ if (string [index] == '\n') {
+ x = offset;
+ y += vulkan->sprite_height [vulkan->font_index [font] [' ' - vulkan->font_begin [font]]] * scale;
+ continue;
+ }
+
+ vulkan_render_core (vulkan, character, x, y, 0, 0, vulkan->sprite_width [character], vulkan->sprite_height [character], scale, scale,
+ 0, 0, colour_left, colour_right, colour_left, colour_right);
+
+ x += vulkan->sprite_width [character] * scale;
+ }
+}
+
+static void vulkan_handle_events (vulkan_structure * vulkan) {
+ static const int signal_code [signal_count] = {
+ 0,
+ 38, 56, 54, 40, 26, 41, 42, 43, 31, 44, 45, 46, 58, 57, 32, 33,
+ 24, 27, 39, 28, 30, 55, 25, 53, 29, 52, 19, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 9, 23, 36, 36, 61, 51, 47, 49, 65, 22, 60, 59,
+ 48, 66, 20, 21, 34, 35, 37, 105, 50, 62, 64, 108, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 95, 96, 111, 116, 113, 114, 77, 127, 118, 110,
+ 112, 119, 115, 117, 86, 82, 63, 106, 104, 91, 90, 87, 88, 89, 83, 84,
+ 85, 79, 80, 81
+ };
+
+ int index, key_code;
+
+ xcb_generic_event_t * generic_event;
+
+ /*generic_event = xcb_wait_for_event (vulkan_connection);*/
+ generic_event = xcb_poll_for_event (vulkan->connection);
+
+ if (generic_event == null) {
+ return;
+ }
+
+ switch (generic_event->response_type & 127) {
+ case (XCB_EXPOSE): {
+ xcb_flush (vulkan->connection);
+ } break;
+ /*case (XCB_CONFIGURE_NOTIFY): {
+ const xcb_configure_notify_event_t * reconfigure = (const xcb_configure_notify_event_t *) generic_event;
+ if ((reconfigure->width != vulkan->width) || (reconfigure->height != vulkan->height)) {
+ vulkan->width = reconfigure->width;
+ vulkan->height = reconfigure->height;
+ if ((vulkan->width > 0) && (vulkan->height > 0)) {
+ vulkan->reconfigure_active = true;
+ vulkan->reconfigure ();
+ }
+ }
+ } break;*/
+ case (XCB_BUTTON_PRESS): {
+ vulkan->cursor = (int) ((xcb_button_press_event_t *) generic_event)->detail;
+ vulkan->cursor_x = (int) ((xcb_button_press_event_t *) generic_event)->event_x;
+ vulkan->cursor_y = (int) ((xcb_button_press_event_t *) generic_event)->event_y;
+ } break;
+ case (XCB_BUTTON_RELEASE): {
+ vulkan->cursor = cursor_none;
+ vulkan->cursor_x = (int) ((xcb_button_release_event_t *) generic_event)->event_x;
+ vulkan->cursor_y = (int) ((xcb_button_release_event_t *) generic_event)->event_y;
+ } break;
+ case (XCB_KEY_PRESS): {
+ key_code = (int) ((xcb_key_press_event_t *) generic_event)->detail;
+ for (index = 0; index < signal_count; ++index) {
+ if (key_code == signal_code [index]) {
+ vulkan->signal [index] = true;
+ break;
+ }
+ }
+ } break;
+ case (XCB_KEY_RELEASE): {
+ key_code = (int) ((xcb_key_release_event_t *) generic_event)->detail;
+ for (index = 0; index < signal_count; ++index) {
+ if (key_code == signal_code [index]) {
+ vulkan->signal [index] = false;
+ break;
+ }
+ }
+ } break;
+ /*case (XCB_MOTION_NOTIFY): {
+ vulkan->cursor_x = (int) ((xcb_motion_notify_event_t *) generic_event)->event_x;
+ vulkan->cursor_y = (int) ((xcb_motion_notify_event_t *) generic_event)->event_y;
+ } break;*/
+ default: {
+ } break;
+ }
+
+ generic_event = deallocate (generic_event);
+}
+
+static void vulkan_synchronize (vulkan_structure * vulkan, uint clear_colour) {
+ uint index = 0;
+ uint frame = 0;
+
+ VkResult result = VK_SUCCESS;
+
+ void * ubo_void = null;
+
+ const VkPipelineStageFlags wait_stages [1] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT} ;
+
+ VkSubmitInfo submit_information = { 0 };
+ VkPresentInfoKHR present_information = { 0 };
+
+ VkSwapchainKHR * swapchain_pointer = & vulkan->swapchain;
+
+ struct timespec frame_begin = { 0 };
+ struct timespec frame_end = { 0 };
+
+ clock_gettime (CLOCK_REALTIME, & frame_begin);
+
+ vulkan_handle_events (vulkan);
+
+ if ((vulkan->active == false) || (vulkan->reconfigure_active == true)) {
+ return;
+ }
+
+ if (vulkan->signal [signal_q] == true) {
+ vulkan->active = false;
+ }
+
+ vulkan_render_core (vulkan, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ vulkan_create_vertex_buffer (vulkan);
+ vulkan_create_index_buffer (vulkan);
+
+ vulkan_record_command_buffers (vulkan, clear_colour, frame);
+
+ vulkan_result (vkWaitForFences (vulkan->logical_device, 1, & vulkan->fence_set_1 [vulkan->frame], VK_TRUE, ~0));
+
+ vulkan_result (vkAcquireNextImageKHR (vulkan->logical_device, vulkan->swapchain, ~0, vulkan->semaphore_set_1 [vulkan->frame],
+ VK_NULL_HANDLE, & frame));
+/*
+ result = vkAcquireNextImageKHR (vulkan->logical_device, vulkan->swapchain, ~0, vulkan->semaphore_set_1 [vulkan->frame],
+ VK_NULL_HANDLE, & frame);
+
+ print ("vkAcquireNextImageKHR : /5%i/-\n", result);
+
+ if (result == VK_ERROR_OUT_OF_DATE_KHR) {
+ vulkan->reconfigure_active = true;
+ return;
+ }
+*/
+ vulkan_result (vkResetFences (vulkan->logical_device, 1, & vulkan->fence_set_1 [vulkan->frame]));
+
+ submit_information.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_information.waitSemaphoreCount = 1;
+ submit_information.pWaitSemaphores = & vulkan->semaphore_set_1 [vulkan->frame];
+ submit_information.pWaitDstStageMask = wait_stages;
+ submit_information.commandBufferCount = 1;
+ submit_information.pCommandBuffers = & vulkan->command_buffers [vulkan->frame];
+ //~submit_information.pCommandBuffers = & vulkan->command_buffers [frame];
+ submit_information.signalSemaphoreCount = 1;
+ submit_information.pSignalSemaphores = & vulkan->semaphore_set_2 [vulkan->frame];
+
+ vulkan_result (vkQueueSubmit (vulkan->queue, 1, & submit_information, vulkan->fence_set_1 [vulkan->frame]));
+
+ present_information.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ present_information.waitSemaphoreCount = 1;
+ present_information.pWaitSemaphores = & vulkan->semaphore_set_2 [vulkan->frame];
+ present_information.swapchainCount = 1;
+ present_information.pSwapchains = swapchain_pointer;
+ present_information.pImageIndices = & frame;
+
+ vulkan_result (vkQueuePresentKHR (vulkan->queue, & present_information));
+/*
+ result = vkQueuePresentKHR (vulkan->queue, & present_information);
+
+ print ("vkQueuePresentKHR : /5%i/-\n", result);
+
+ if ((result == VK_ERROR_OUT_OF_DATE_KHR) || (result == VK_SUBOPTIMAL_KHR)) {
+ vulkan->reconfigure_active = true;
+ return;
+ }
+*/
+ vulkan->frame = (vulkan->frame + 1) % vulkan->image_count;
+
+ vulkan_result (vkQueueWaitIdle (vulkan->queue));
+ vulkan_result (vkDeviceWaitIdle (vulkan->logical_device));
+
+ vkDestroyBuffer (vulkan->logical_device, vulkan->index_buffer, null);
+ vkFreeMemory (vulkan->logical_device, vulkan->index_memory, null);
+ vkDestroyBuffer (vulkan->logical_device, vulkan->vertex_buffer, null);
+ vkFreeMemory (vulkan->logical_device, vulkan->vertex_memory, null);
+
+ vulkan->vertex_count = 0;
+ vulkan->index_count = 0;
+
+ vulkan_result (vkQueueWaitIdle (vulkan->queue));
+ vulkan_result (vkDeviceWaitIdle (vulkan->logical_device));
+
+ clock_gettime (CLOCK_REALTIME, & frame_end);
+
+ if (vulkan->gameplay_time % (vulkan->gameplay_framerate / 10) == 0) {
+ vulkan->frame_time_in_ns = (frame_end.tv_sec - frame_begin.tv_sec) * 1000000000 + frame_end.tv_nsec - frame_begin.tv_nsec;
+
+ vulkan->framerate = (int) (1000000000 / vulkan->frame_time_in_ns);
+ }
+
+ if (vulkan->framerate > vulkan->gameplay_framerate) {
+ struct timespec wait = { 0, 0 };
+
+ wait.tv_nsec = 1000000000 / vulkan->gameplay_framerate - vulkan->frame_time_in_ns;
+
+ while (nanosleep (& wait, null) == -1) continue;
+ }
+
+ ++vulkan->global_time;
+
+ vulkan->global_time = vulkan->global_time % (vulkan->gameplay_framerate * vulkan->animation_framerate);
+ vulkan->gameplay_time = vulkan->global_time % (vulkan->gameplay_framerate);
+ vulkan->animation_time = vulkan->global_time / (vulkan->gameplay_framerate / vulkan->animation_framerate);
+}
--- /dev/null
+// __ ___ _ _ __ __ _ ___ ___ _ __
+// \ \/ / | | | '_ \ / _` |/ _ \/ _ \| '_ \
+// > <| |_| | | | | (_| | __/ (_) | | | |
+// /_/\_\\__,_|_| |_|\__, |\___|\___/|_| |_|
+// |___/
+//
+// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+//
+// xolatile@chud.cyou - xungeon - Small library for defining dungeon crawler gameplay information.
+//
+// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+//
+// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+//~typedef struct {
+ //~char * name;
+//~} * _definition;
+
+typedef struct {
+ char * name; // Name string copy.
+ uint temperature; // ;
+ uint humidity; // ;
+} * dungeon_biome_definition;
+
+typedef struct {
+ char * name; // Name string copy.
+ uint biome; // Index in biome array.
+ bool clip; // Can entities move through?
+} * dungeon_landmark_definition;
+
+typedef struct {
+ char * name; // Name string copy.
+} * dungeon_expertise_definition;
+
+typedef struct {
+ char * name; // Name string copy.
+ uint base; // Default amount of points per entity.
+ uint limit; // After this point, points won't increase.
+} * dungeon_attribute_definition;
+
+typedef struct {
+ char * name; // Name string copy.
+ uint base; // Default amount of points per entity.
+ uint limit; // After this point, points won't increase.
+} * dungeon_skill_definition;
+
+typedef struct {
+ char * name; // Name string copy.
+ uint base; // Default amount of points per entity.
+ uint limit; // After this point, points won't increase.
+ uint value; // Constant trade value per index 0.
+ uint trade; // Trade rate for acquiring the resource.
+} * dungeon_resource_definition;
+
+typedef struct {
+ char * name; // Name string copy.
+} * dungeon_item_slot_definition;
+
+typedef struct {
+ char * name; // Name string copy.
+ uint slot; // Index in item slot array.
+ uint effect; // Index in effect array.
+} * dungeon_item_definition;
+
+typedef struct {
+ uint biome_count;
+ uint landmark_count;
+ uint expertise_count;
+ uint attribute_count;
+ uint skill_count;
+ uint resource_count;
+ uint item_slot_count;
+ uint item_count;
+ dungeon_biome_definition * biome_array;
+ dungeon_landmark_definition * landmark_array;
+ dungeon_expertise_definition * expertise_array;
+ dungeon_attribute_definition * attribute_array;
+ dungeon_skill_definition * skill_array;
+ dungeon_resource_definition * resource_array;
+ dungeon_item_slot_definition * item_slot_array;
+ dungeon_item_definition * item_array;
+} * dungeon_structure;
+
+static uint dungeon_biome_define (dungeon_structure dungeon, const char * name, uint temperature, uint humidity) {
+ dungeon_biome_definition biome = arena_add (sizeof (* biome));
+
+ fatal_failure (dungeon == null, "biome_define: Dungeon is not configured.");
+ fatal_failure (name == null, "biome_define: Name is null pointer.");
+
+ string_copy ((biome->name = arena_add ((string_length (name) + 1) * sizeof (* biome->name))), name);
+
+ biome->temperature = temperature;
+ biome->humidity = humidity;
+
+ dungeon->biome_count += 1;
+
+ dungeon->biome_array [dungeon->biome_count - 1] = biome;
+
+ return (dungeon->biome_count - 1);
+}
+
+static char * dungeon_biome_name (dungeon_structure dungeon, uint index) { return (dungeon->biome_array [index]->name); }
+static uint dungeon_biome_temperature (dungeon_structure dungeon, uint index) { return (dungeon->biome_array [index]->temperature); }
+static uint dungeon_biome_humidity (dungeon_structure dungeon, uint index) { return (dungeon->biome_array [index]->humidity); }
+
+static uint dungeon_landmark_define (dungeon_structure dungeon, const char * name, uint biome, bool clip) {
+ dungeon_landmark_definition landmark = arena_add (sizeof (* landmark));
+
+ fatal_failure (dungeon == null, "landmark_define: Dungeon is not configured.");
+ fatal_failure (name == null, "landmark_define: Name is null pointer.");
+
+ string_copy ((landmark->name = arena_add ((string_length (name) + 1) * sizeof (* landmark->name))), name);
+
+ landmark->biome = biome;
+ landmark->clip = clip;
+
+ dungeon->landmark_count += 1;
+
+ dungeon->landmark_array [dungeon->landmark_count - 1] = landmark;
+
+ return (dungeon->landmark_count - 1);
+}
+
+static char * dungeon_landmark_name (dungeon_structure dungeon, uint index) { return (dungeon->landmark_array [index]->name); }
+static uint dungeon_landmark_biome (dungeon_structure dungeon, uint index) { return (dungeon->landmark_array [index]->biome); }
+static bool dungeon_landmark_clip (dungeon_structure dungeon, uint index) { return (dungeon->landmark_array [index]->clip); }
+
+static uint dungeon_expertise_define (dungeon_structure dungeon, const char * name) {
+ dungeon_expertise_definition expertise = arena_add (sizeof (* expertise));
+
+ fatal_failure (dungeon == null, "expertise_define: Dungeon is not configured.");
+ fatal_failure (name == null, "expertise_define: Name is null pointer.");
+
+ string_copy ((expertise->name = arena_add ((string_length (name) + 1) * sizeof (* expertise->name))), name);
+
+ dungeon->expertise_count += 1;
+
+ dungeon->expertise_array [dungeon->expertise_count - 1] = expertise;
+
+ return (dungeon->expertise_count - 1);
+}
+
+static char * dungeon_expertise_name (dungeon_structure dungeon, uint index) { return (dungeon->expertise_array [index]->name); }
+
+static uint dungeon_attribute_define (dungeon_structure dungeon, const char * name, uint base, uint limit) {
+ dungeon_attribute_definition attribute = arena_add (sizeof (* attribute));
+
+ fatal_failure (dungeon == null, "attribute_define: Dungeon is not configured.");
+ fatal_failure (name == null, "attribute_define: Name is null pointer.");
+
+ string_copy ((attribute->name = arena_add ((string_length (name) + 1) * sizeof (* attribute->name))), name);
+
+ attribute->base = base;
+ attribute->limit = limit;
+
+ dungeon->attribute_count += 1;
+
+ dungeon->attribute_array [dungeon->attribute_count - 1] = attribute;
+
+ return (dungeon->attribute_count - 1);
+}
+
+static char * dungeon_attribute_name (dungeon_structure dungeon, uint index) { return (dungeon->attribute_array [index]->name); }
+static uint dungeon_attribute_base (dungeon_structure dungeon, uint index) { return (dungeon->attribute_array [index]->base); }
+static uint dungeon_attribute_limit (dungeon_structure dungeon, uint index) { return (dungeon->attribute_array [index]->limit); }
+
+static uint dungeon_skill_define (dungeon_structure dungeon, const char * name, uint base, uint limit) {
+ dungeon_skill_definition skill = arena_add (sizeof (* skill));
+
+ fatal_failure (dungeon == null, "skill_define: Dungeon is not configured.");
+ fatal_failure (name == null, "skill_define: Name is null pointer.");
+
+ string_copy ((skill->name = arena_add ((string_length (name) + 1) * sizeof (* skill->name))), name);
+
+ skill->base = base;
+ skill->limit = limit;
+
+ dungeon->skill_count += 1;
+
+ dungeon->skill_array [dungeon->skill_count - 1] = skill;
+
+ return (dungeon->skill_count - 1);
+}
+
+static char * dungeon_skill_name (dungeon_structure dungeon, uint index) { return (dungeon->skill_array [index]->name); }
+static uint dungeon_skill_base (dungeon_structure dungeon, uint index) { return (dungeon->skill_array [index]->base); }
+static uint dungeon_skill_limit (dungeon_structure dungeon, uint index) { return (dungeon->skill_array [index]->limit); }
+
+static uint dungeon_resource_define (dungeon_structure dungeon, const char * name, uint base, uint limit, uint value, uint trade) {
+ dungeon_resource_definition resource = arena_add (sizeof (* resource));
+
+ fatal_failure (dungeon == null, "resource_define: Dungeon is not configured.");
+ fatal_failure (name == null, "resource_define: Name is null pointer.");
+
+ string_copy ((resource->name = arena_add ((string_length (name) + 1) * sizeof (* resource->name))), name);
+
+ resource->base = base;
+ resource->limit = limit;
+ resource->value = value;
+ resource->trade = trade;
+
+ dungeon->resource_count += 1;
+
+ dungeon->resource_array [dungeon->resource_count - 1] = resource;
+
+ return (dungeon->resource_count - 1);
+}
+
+static char * dungeon_resource_name (dungeon_structure dungeon, uint index) { return (dungeon->resource_array [index]->name); }
+static uint dungeon_resource_base (dungeon_structure dungeon, uint index) { return (dungeon->resource_array [index]->base); }
+static uint dungeon_resource_limit (dungeon_structure dungeon, uint index) { return (dungeon->resource_array [index]->limit); }
+static uint dungeon_resource_value (dungeon_structure dungeon, uint index) { return (dungeon->resource_array [index]->value); }
+static uint dungeon_resource_trade (dungeon_structure dungeon, uint index) { return (dungeon->resource_array [index]->trade); }
+
+static uint dungeon_item_slot_define (dungeon_structure dungeon, const char * name) {
+ dungeon_item_slot_definition item_slot = arena_add (sizeof (* item_slot));
+
+ fatal_failure (dungeon == null, "item_slot_define: Dungeon is not configured.");
+ fatal_failure (name == null, "item_slot_define: Name is null pointer.");
+
+ string_copy ((item_slot->name = arena_add ((string_length (name) + 1) * sizeof (* item_slot->name))), name);
+
+ dungeon->item_slot_count += 1;
+
+ dungeon->item_slot_array [dungeon->item_slot_count - 1] = item_slot;
+
+ return (dungeon->item_slot_count - 1);
+}
+
+static char * dungeon_item_slot_name (dungeon_structure dungeon, uint index) { return (dungeon->item_slot_array [index]->name); }
+
+static uint dungeon_item_define (dungeon_structure dungeon, const char * name, uint slot, uint effect) {
+ dungeon_item_definition item = arena_add (sizeof (* item));
+
+ fatal_failure (dungeon == null, "item_define: Dungeon is not configured.");
+ fatal_failure (name == null, "item_define: Name is null pointer.");
+
+ string_copy ((item->name = arena_add ((string_length (name) + 1) * sizeof (* item->name))), name);
+
+ item->slot = slot;
+ item->effect = effect;
+
+ dungeon->item_count += 1;
+
+ dungeon->item_array [dungeon->item_count - 1] = item;
+
+ return (dungeon->item_count - 1);
+}
+
+static char * dungeon_item_name (dungeon_structure dungeon, uint index) { return (dungeon->item_array [index]->name); }
+static uint dungeon_item_slot (dungeon_structure dungeon, uint index) { return (dungeon->item_array [index]->slot); }
+static uint dungeon_item_effect (dungeon_structure dungeon, uint index) { return (dungeon->item_array [index]->effect); }
+
+static dungeon_structure dungeon_configure (uint biome_limit, uint landmark_limit, uint expertise_limit, uint attribute_limit, uint skill_limit,
+ uint resource_limit, uint item_slot_limit, uint item_limit) {
+ dungeon_structure dungeon = arena_add (sizeof (* dungeon));
+
+ dungeon->biome_array = arena_add (biome_limit * sizeof (* dungeon->biome_array));
+ dungeon->landmark_array = arena_add (landmark_limit * sizeof (* dungeon->landmark_array));
+ dungeon->expertise_array = arena_add (expertise_limit * sizeof (* dungeon->expertise_array));
+ dungeon->attribute_array = arena_add (attribute_limit * sizeof (* dungeon->attribute_array));
+ dungeon->skill_array = arena_add (skill_limit * sizeof (* dungeon->skill_array));
+ dungeon->resource_array = arena_add (resource_limit * sizeof (* dungeon->resource_array));
+ dungeon->item_slot_array = arena_add (item_slot_limit * sizeof (* dungeon->item_slot_array));
+ dungeon->item_array = arena_add (item_limit * sizeof (* dungeon->item_array));
+
+ return (dungeon);
+}
--- /dev/null
+#include <xolatile/xtandard.h>
+#include <xolatile/xyntax.h>
+#include <xolatile/xormat/png.h>
+
+#define foreground (0xffccccccu)
+#define background (0xff181818u)
+
+#define font_indent ( 8)
+#define font_width ( 8)
+#define font_height ( 8)
+#define font_count (96)
+
+static uint * render = null;
+static uint colour = foreground;
+
+static uint width = 0;
+static uint height = 0;
+static uint x = 0;
+static uint y = 0;
+
+static void render_character (char character) {
+ const ulong font_code [font_count] = {
+ 0x0000000000000000, 0x00180018183c3c18, 0x0000000000363636, 0x006c6cfe6cfe6c6c,
+ 0x00187ed07c16fc30, 0x0060660c18306606, 0x00dc66b61c36361c, 0x0000000000181818,
+ 0x0030180c0c0c1830, 0x000c18303030180c, 0x0000187e3c7e1800, 0x000018187e181800,
+ 0x0c18180000000000, 0x000000007e000000, 0x0018180000000000, 0x0000060c18306000,
+ 0x003c666e7e76663c, 0x007e181818181c18, 0x007e0c183060663c, 0x003c66603860663c,
+ 0x0030307e363c3830, 0x003c6660603e067e, 0x003c66663e060c38, 0x000c0c0c1830607e,
+ 0x003c66663c66663c, 0x001c30607c66663c, 0x0018180018180000, 0x0c18180018180000,
+ 0x0030180c060c1830, 0x0000007e007e0000, 0x000c18306030180c, 0x001800181830663c,
+ 0x003c06765676663c, 0x006666667e66663c, 0x003e66663e66663e, 0x003c66060606663c,
+ 0x001e36666666361e, 0x007e06063e06067e, 0x000606063e06067e, 0x003c66667606663c,
+ 0x006666667e666666, 0x007e18181818187e, 0x001c36303030307c, 0x0066361e0e1e3666,
+ 0x007e060606060606, 0x00c6c6d6d6feeec6, 0x006666767e6e6666, 0x003c66666666663c,
+ 0x000606063e66663e, 0x006c36566666663c, 0x006666363e66663e, 0x003c66603c06663c,
+ 0x001818181818187e, 0x003c666666666666, 0x00183c6666666666, 0x00c6eefed6d6c6c6,
+ 0x0066663c183c6666, 0x001818183c666666, 0x007e060c1830607e, 0x003e06060606063e,
+ 0x00006030180c0600, 0x007c60606060607c, 0x000000000000663c, 0xffff000000000000,
+ 0x000000000030180c, 0x007c667c603c0000, 0x003e6666663e0606, 0x003c6606663c0000,
+ 0x007c6666667c6060, 0x003c067e663c0000, 0x000c0c0c3e0c0c38, 0x3c607c66667c0000,
+ 0x00666666663e0606, 0x003c1818181c0018, 0x0e181818181c0018, 0x0066361e36660606,
+ 0x003c18181818181c, 0x00c6d6d6fe6c0000, 0x00666666663e0000, 0x003c6666663c0000,
+ 0x06063e66663e0000, 0xe0607c66667c0000, 0x000606066e360000, 0x003e603c067c0000,
+ 0x00380c0c0c3e0c0c, 0x007c666666660000, 0x00183c6666660000, 0x006cfed6d6c60000,
+ 0x00663c183c660000, 0x3c607c6666660000, 0x007e0c18307e0000, 0x003018180e181830,
+ 0x0018181818181818, 0x000c18187018180c, 0x000000000062d68c, 0x0000000000000000
+ };
+
+ for (uint offset = 0; offset < font_width * font_height; ++offset) {
+ uint u = offset / font_width + y;
+ uint v = offset % font_width + x;
+
+ render [u * width + v] = ((font_code [(uint) (character - ' ')] >> offset) % 2) ? colour : background;
+ }
+
+ x += font_width + 1;
+}
+
+static void render_string (const char * string, uint length) {
+ for (uint offset = 0; offset < length; ++offset) {
+ if (string [offset] == '\t') {
+ x += font_width * font_indent;
+ } else if (string [offset] == '\n') {
+ y += font_height + 1;
+ x = 1;
+ } else {
+ render_character (string [offset]);
+ }
+ }
+}
+
+int main (void) {
+ uint index = 0;
+ uint length = 0;
+ char * buffer = null;
+
+ const char separator [] = ".,:;<=>+-*/%!&~^()[]{}'\" \t\r\n";
+
+ const char * keywords [] = {
+ "register", "volatile", "auto", "const", "static", "extern", "if", "else",
+ "do", "while", "for", "continue", "switch", "case", "default", "break",
+ "enum", "union", "struct", "typedef", "goto", "void", "return", "sizeof",
+ "char", "short", "int", "long", "signed", "unsigned", "float", "double"
+ };
+
+ syntax_structure * syntax = syntax_initialize (0);
+
+ syntax_define (syntax, false, false, "#", "\n", '\\', 0xff3377aa, 0);
+ syntax_define (syntax, false, false, "//", "\n", '\0', 0xff777777, 0);
+ syntax_define (syntax, false, false, "/*", "*/", '\0', 0xff777777, 0);
+ syntax_define (syntax, false, false, "'", "'", '\\', 0xff9933cc, 0);
+ syntax_define (syntax, false, false, "\"", "\"", '\\', 0xffcc3399, 0);
+ syntax_define (syntax, true, false, ".,:;<=>+-*/%!&~^?|", "", '\0', 0xffccaa33, 0);
+ syntax_define (syntax, true, false, "(){}[]", "", '\0', 0xffcc3333, 0);
+
+ for (ulong word = 0; word < array_length (keywords); ++word) {
+ syntax_define (syntax, false, true, keywords [word], separator, '\0', 0xff33aacc, 0);
+ }
+
+ syntax_define (syntax, true, true, "0123456789", separator, '\0', 0xffcc77cc, 0);
+ syntax_define (syntax, true, true, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_", separator, '\0', 0xffcccccc, 0);
+
+ buffer = record ();
+
+ width = string_full_width (buffer, font_indent) * (font_width + 1) + 1;
+ height = string_full_height (buffer) * (font_height + 1) + 1;
+
+ render = allocate (4 * width * height);
+
+ for (uint offset = 0; offset < width * height; ++offset) {
+ render [offset] = background;
+ }
+
+ for (uint offset = 0; buffer [offset] != '\0'; offset += length) {
+ index = syntax_select (syntax, & buffer [offset], & length);
+
+ colour = syntax->colour [index];
+
+ render_string (& buffer [offset], length);
+ }
+
+ png_image_export ("xuxuxu.png", render, width, height);
+
+ syntax = syntax_deinitialize (syntax);
+
+ buffer = deallocate (buffer);
+ render = deallocate (render);
+
+ return (log_success);
+}
--- /dev/null
+/// _
+/// __ ___ _ _ __ | |_ __ ___ __
+/// \ \/ / | | | '_ \| __/ _` \ \/ /
+/// > <| |_| | | | | || (_| |> <
+/// /_/\_\\__, |_| |_|\__\__,_/_/\_\
+/// |___/
+///
+/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
+///
+/// xolatile@chud.cyou - xyntax - Tiny, unsafe and somewhat insane unity header for generic syntax definition.
+///
+/// This program is free software, free as in freedom and as in free beer, 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 any later version if you wish...
+///
+/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
+/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
+/// for more details, if you dare, it is a lot of text that nobody wants to read...
+
+typedef struct {
+ uint count;
+ uint limit;
+ bool * enrange;
+ bool * derange;
+ char * * begin;
+ char * * end;
+ char * escape;
+ uint * colour;
+ uint * effect;
+} syntax_structure;
+
+static syntax_structure * syntax_initialize (uint limit) {
+ syntax_structure * syntax = allocate (sizeof (* syntax));
+
+ syntax->limit = limit;
+
+ if (limit != 0) {
+ syntax->enrange = allocate (syntax->limit * sizeof (* syntax->enrange));
+ syntax->derange = allocate (syntax->limit * sizeof (* syntax->derange));
+ syntax->begin = allocate (syntax->limit * sizeof (* syntax->begin));
+ syntax->end = allocate (syntax->limit * sizeof (* syntax->end));
+ syntax->escape = allocate (syntax->limit * sizeof (* syntax->escape));
+ syntax->colour = allocate (syntax->limit * sizeof (* syntax->colour));
+ syntax->effect = allocate (syntax->limit * sizeof (* syntax->effect));
+ }
+
+ return (syntax);
+}
+
+static syntax_structure * syntax_deinitialize (syntax_structure * syntax) {
+ for (uint index = 0; index < syntax->count; ++index) {
+ syntax->begin [index] = deallocate (syntax->begin [index]);
+ syntax->end [index] = deallocate (syntax->end [index]);
+ }
+
+ syntax->enrange = deallocate (syntax->enrange);
+ syntax->derange = deallocate (syntax->derange);
+ syntax->begin = deallocate (syntax->begin);
+ syntax->end = deallocate (syntax->end);
+ syntax->escape = deallocate (syntax->escape);
+ syntax->colour = deallocate (syntax->colour);
+ syntax->effect = deallocate (syntax->effect);
+
+ return (deallocate (syntax));
+}
+
+static uint syntax_define (syntax_structure * syntax, bool enrange, bool derange, const char * begin, const char * end, char escape,
+ uint colour, uint effect) {
+ ++syntax->count;
+
+ uint current = syntax->count - 1;
+
+ fatal_failure (begin == null, "syntax_define: Begin string is null pointer.");
+ fatal_failure (end == null, "syntax_define: End string is null pointer.");
+
+ fatal_failure (syntax->count >= syntax->limit, "syntax_define: Reached the hardcoded limit.");
+
+ if (syntax->limit == 0) {
+ syntax->enrange = reallocate (syntax->enrange, syntax->count * sizeof (* syntax->enrange));
+ syntax->derange = reallocate (syntax->derange, syntax->count * sizeof (* syntax->derange));
+ syntax->begin = reallocate (syntax->begin, syntax->count * sizeof (* syntax->begin));
+ syntax->end = reallocate (syntax->end, syntax->count * sizeof (* syntax->end));
+ syntax->escape = reallocate (syntax->escape, syntax->count * sizeof (* syntax->escape));
+ syntax->colour = reallocate (syntax->colour, syntax->count * sizeof (* syntax->colour));
+ syntax->effect = reallocate (syntax->effect, syntax->count * sizeof (* syntax->effect));
+ }
+
+ syntax->begin [current] = allocate ((string_length (begin) + 1) * sizeof (* * syntax->begin));
+ syntax->end [current] = allocate ((string_length (end) + 1) * sizeof (* * syntax->end));
+
+ syntax->enrange [current] = enrange;
+ syntax->derange [current] = derange;
+ syntax->escape [current] = escape;
+ syntax->colour [current] = colour;
+ syntax->effect [current] = effect;
+
+ string_copy (syntax->begin [current], begin);
+ string_copy (syntax->end [current], end);
+
+ return (current);
+}
+
+static uint syntax_select (syntax_structure * syntax, const char * string, uint * length) {
+ uint offset = 0;
+ uint subset = 0;
+ uint select = 0;
+
+ ulong begin_length = 0;
+ ulong end_length = 0;
+
+ for (; select != syntax->count; ++select) {
+ begin_length = string_length (syntax->begin [select]);
+
+ if (! syntax->enrange [select]) {
+ if (! syntax->derange [select]) {
+ if (string_compare_limit (string, syntax->begin [select], begin_length)) {
+ break;
+ }
+ } else {
+ if ((string_compare_limit (string, syntax->begin [select], begin_length))
+ && (character_compare_array (string [offset + begin_length], syntax->end [select]))) {
+ break;
+ }
+ }
+ } else {
+ for (subset = 0; subset != begin_length; ++subset) {
+ if (string [offset] == syntax->begin [select] [subset]) {
+ goto selected;
+ }
+ }
+ }
+ }
+
+ selected:
+
+ if (select >= syntax->count) {
+ * length = 1;
+
+ return (syntax->count);
+ }
+
+ end_length = string_length (syntax->end [select]);
+
+ for (offset = 1; string [offset - 1] != character_null; ++offset) {
+ if (string [offset] == syntax->escape [select]) {
+ ++offset;
+ continue;
+ }
+
+ if (syntax->derange [select]) {
+ subset = 0;
+ if (end_length == 0) {
+ break;
+ } do {
+ if (string [offset] == syntax->end [select] [subset]) {
+ * length = offset;
+ goto finished;
+ }
+ } while (++subset != end_length);
+ } else {
+ if (end_length != 0) {
+ if (string_compare_limit (& string [offset], syntax->end [select], end_length)) {
+ * length = offset + end_length;
+ return (select);
+ }
+ } else {
+ * length = 1;
+ return (select);
+ }
+ }
+ }
+
+ finished:
+
+ return (select);
+}