From: xolatile Date: Sun, 6 Apr 2025 14:01:15 +0000 (+0200) Subject: Just dumped everything because... X-Git-Url: https://git.xolatile.top/?a=commitdiff_plain;h=6e21f5457cf1aa57d45cd86031aa237d73cac69d;p=emil-xolatilization.git Just dumped everything because... --- diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..906d731 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +xop +xscii +xtatus +xighlight +xhallenge +xuxuxu +xarbon +xource diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..e142a52 --- /dev/null +++ b/LICENSE @@ -0,0 +1,625 @@ +GNU GENERAL PUBLIC LICENSE + +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble + +The GNU General Public License is a free, copyleft license for software and +other kinds of works. + +The licenses for most software and other practical works are designed to take +away your freedom to share and change the works. By contrast, the GNU General +Public License is intended to guarantee your freedom to share and change all +versions of a program--to make sure it remains free software for all its users. +We, the Free Software Foundation, use the GNU General Public License for most +of our software; it applies also to any other work released this way by its +authors. You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom +to distribute copies of free software (and charge for them if you wish), that +you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs, and that you know you +can do these things. + +To protect your rights, we need to prevent others from denying you these rights +or asking you to surrender the rights. Therefore, you have certain responsibilities +if you distribute copies of the software, or if you modify it: responsibilities +to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or +for a fee, you must pass on to the recipients the same freedoms that you received. +You must make sure that they, too, receive or can get the source code. And +you must show them these terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert +copyright on the software, and (2) offer you this License giving you legal +permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that +there is no warranty for this free software. For both users' and authors' +sake, the GPL requires that modified versions be marked as changed, so that +their problems will not be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified +versions of the software inside them, although the manufacturer can do so. +This is fundamentally incompatible with the aim of protecting users' freedom +to change the software. The systematic pattern of such abuse occurs in the +area of products for individuals to use, which is precisely where it is most +unacceptable. Therefore, we have designed this version of the GPL to prohibit +the practice for those products. If such problems arise substantially in other +domains, we stand ready to extend this provision to those domains in future +versions of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. States +should not allow patents to restrict development and use of software on general-purpose +computers, but in those that do, we wish to avoid the special danger that +patents applied to a free program could make it effectively proprietary. To +prevent this, the GPL assures that patents cannot be used to render the program +non-free. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds of works, +such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this License. +Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals +or organizations. + +To "modify" a work means to copy from or adapt all or part of the work in +a fashion requiring copyright permission, other than the making of an exact +copy. The resulting work is called a "modified version" of the earlier work +or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based on the +Program. + +To "propagate" a work means to do anything with it that, without permission, +would make you directly or secondarily liable for infringement under applicable +copyright law, except executing it on a computer or modifying a private copy. +Propagation includes copying, distribution (with or without modification), +making available to the public, and in some countries other activities as +well. + +To "convey" a work means any kind of propagation that enables other parties +to make or receive copies. Mere interaction with a user through a computer +network, with no transfer of a copy, is not conveying. + +An interactive user interface displays "Appropriate Legal Notices" to the +extent that it includes a convenient and prominently visible feature that +(1) displays an appropriate copyright notice, and (2) tells the user that +there is no warranty for the work (except to the extent that warranties are +provided), that licensees may convey the work under this License, and how +to view a copy of this License. If the interface presents a list of user commands +or options, such as a menu, a prominent item in the list meets this criterion. + + 1. Source Code. + +The "source code" for a work means the preferred form of the work for making +modifications to it. "Object code" means any non-source form of a work. + +A "Standard Interface" means an interface that either is an official standard +defined by a recognized standards body, or, in the case of interfaces specified +for a particular programming language, one that is widely used among developers +working in that language. + +The "System Libraries" of an executable work include anything, other than +the work as a whole, that (a) is included in the normal form of packaging +a Major Component, but which is not part of that Major Component, and (b) +serves only to enable use of the work with that Major Component, or to implement +a Standard Interface for which an implementation is available to the public +in source code form. A "Major Component", in this context, means a major essential +component (kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to produce +the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all the source +code needed to generate, install, and (for an executable work) run the object +code and to modify the work, including scripts to control those activities. +However, it does not include the work's System Libraries, or general-purpose +tools or generally available free programs which are used unmodified in performing +those activities but which are not part of the work. For example, Corresponding +Source includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically linked +subprograms that the work is specifically designed to require, such as by +intimate data communication or control flow between those subprograms and +other parts of the work. + +The Corresponding Source need not include anything that users can regenerate +automatically from other parts of the Corresponding Source. + + The Corresponding Source for a work in source code form is that same work. + + 2. Basic Permissions. + +All rights granted under this License are granted for the term of copyright +on the Program, and are irrevocable provided the stated conditions are met. +This License explicitly affirms your unlimited permission to run the unmodified +Program. The output from running a covered work is covered by this License +only if the output, given its content, constitutes a covered work. This License +acknowledges your rights of fair use or other equivalent, as provided by copyright +law. + +You may make, run and propagate covered works that you do not convey, without +conditions so long as your license otherwise remains in force. You may convey +covered works to others for the sole purpose of having them make modifications +exclusively for you, or provide you with facilities for running those works, +provided that you comply with the terms of this License in conveying all material +for which you do not control copyright. Those thus making or running the covered +works for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of your copyrighted +material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the conditions +stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological measure +under any applicable law fulfilling obligations under article 11 of the WIPO +copyright treaty adopted on 20 December 1996, or similar laws prohibiting +or restricting circumvention of such measures. + +When you convey a covered work, you waive any legal power to forbid circumvention +of technological measures to the extent such circumvention is effected by +exercising rights under this License with respect to the covered work, and +you disclaim any intention to limit operation or modification of the work +as a means of enforcing, against the work's users, your or third parties' +legal rights to forbid circumvention of technological measures. + + 4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you receive +it, in any medium, provided that you conspicuously and appropriately publish +on each copy an appropriate copyright notice; keep intact all notices stating +that this License and any non-permissive terms added in accord with section +7 apply to the code; keep intact all notices of the absence of any warranty; +and give all recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you +may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to produce +it from the Program, in the form of source code under the terms of section +4, provided that you also meet all of these conditions: + +a) The work must carry prominent notices stating that you modified it, and +giving a relevant date. + +b) The work must carry prominent notices stating that it is released under +this License and any conditions added under section 7. This requirement modifies +the requirement in section 4 to "keep intact all notices". + +c) You must license the entire work, as a whole, under this License to anyone +who comes into possession of a copy. This License will therefore apply, along +with any applicable section 7 additional terms, to the whole of the work, +and all its parts, regardless of how they are packaged. This License gives +no permission to license the work in any other way, but it does not invalidate +such permission if you have separately received it. + +d) If the work has interactive user interfaces, each must display Appropriate +Legal Notices; however, if the Program has interactive interfaces that do +not display Appropriate Legal Notices, your work need not make them do so. + +A compilation of a covered work with other separate and independent works, +which are not by their nature extensions of the covered work, and which are +not combined with it such as to form a larger program, in or on a volume of +a storage or distribution medium, is called an "aggregate" if the compilation +and its resulting copyright are not used to limit the access or legal rights +of the compilation's users beyond what the individual works permit. Inclusion +of a covered work in an aggregate does not cause this License to apply to +the other parts of the aggregate. + + 6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of sections +4 and 5, provided that you also convey the machine-readable Corresponding +Source under the terms of this License, in one of these ways: + +a) Convey the object code in, or embodied in, a physical product (including +a physical distribution medium), accompanied by the Corresponding Source fixed +on a durable physical medium customarily used for software interchange. + +b) Convey the object code in, or embodied in, a physical product (including +a physical distribution medium), accompanied by a written offer, valid for +at least three years and valid for as long as you offer spare parts or customer +support for that product model, to give anyone who possesses the object code +either (1) a copy of the Corresponding Source for all the software in the +product that is covered by this License, on a durable physical medium customarily +used for software interchange, for a price no more than your reasonable cost +of physically performing this conveying of source, or (2) access to copy the +Corresponding Source from a network server at no charge. + +c) Convey individual copies of the object code with a copy of the written +offer to provide the Corresponding Source. This alternative is allowed only +occasionally and noncommercially, and only if you received the object code +with such an offer, in accord with subsection 6b. + +d) Convey the object code by offering access from a designated place (gratis +or for a charge), and offer equivalent access to the Corresponding Source +in the same way through the same place at no further charge. You need not +require recipients to copy the Corresponding Source along with the object +code. If the place to copy the object code is a network server, the Corresponding +Source may be on a different server (operated by you or a third party) that +supports equivalent copying facilities, provided you maintain clear directions +next to the object code saying where to find the Corresponding Source. Regardless +of what server hosts the Corresponding Source, you remain obligated to ensure +that it is available for as long as needed to satisfy these requirements. + +e) Convey the object code using peer-to-peer transmission, provided you inform +other peers where the object code and Corresponding Source of the work are +being offered to the general public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded from +the Corresponding Source as a System Library, need not be included in conveying +the object code work. + +A "User Product" is either (1) a "consumer product", which means any tangible +personal property which is normally used for personal, family, or household +purposes, or (2) anything designed or sold for incorporation into a dwelling. +In determining whether a product is a consumer product, doubtful cases shall +be resolved in favor of coverage. For a particular product received by a particular +user, "normally used" refers to a typical or common use of that class of product, +regardless of the status of the particular user or of the way in which the +particular user actually uses, or expects or is expected to use, the product. +A product is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent the +only significant mode of use of the product. + +"Installation Information" for a User Product means any methods, procedures, +authorization keys, or other information required to install and execute modified +versions of a covered work in that User Product from a modified version of +its Corresponding Source. The information must suffice to ensure that the +continued functioning of the modified object code is in no case prevented +or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically +for use in, a User Product, and the conveying occurs as part of a transaction +in which the right of possession and use of the User Product is transferred +to the recipient in perpetuity or for a fixed term (regardless of how the +transaction is characterized), the Corresponding Source conveyed under this +section must be accompanied by the Installation Information. But this requirement +does not apply if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has been installed +in ROM). + +The requirement to provide Installation Information does not include a requirement +to continue to provide support service, warranty, or updates for a work that +has been modified or installed by the recipient, or for the User Product in +which it has been modified or installed. Access to a network may be denied +when the modification itself materially and adversely affects the operation +of the network or violates the rules and protocols for communication across +the network. + +Corresponding Source conveyed, and Installation Information provided, in accord +with this section must be in a format that is publicly documented (and with +an implementation available to the public in source code form), and must require +no special password or key for unpacking, reading or copying. + + 7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this License +by making exceptions from one or more of its conditions. Additional permissions +that are applicable to the entire Program shall be treated as though they +were included in this License, to the extent that they are valid under applicable +law. If additional permissions apply only to part of the Program, that part +may be used separately under those permissions, but the entire Program remains +governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any +additional permissions from that copy, or from any part of it. (Additional +permissions may be written to require their own removal in certain cases when +you modify the work.) You may place additional permissions on material, added +by you to a covered work, for which you have or can give appropriate copyright +permission. + +Notwithstanding any other provision of this License, for material you add +to a covered work, you may (if authorized by the copyright holders of that +material) supplement the terms of this License with terms: + +a) Disclaiming warranty or limiting liability differently from the terms of +sections 15 and 16 of this License; or + +b) Requiring preservation of specified reasonable legal notices or author +attributions in that material or in the Appropriate Legal Notices displayed +by works containing it; or + +c) Prohibiting misrepresentation of the origin of that material, or requiring +that modified versions of such material be marked in reasonable ways as different +from the original version; or + +d) Limiting the use for publicity purposes of names of licensors or authors +of the material; or + +e) Declining to grant rights under trademark law for use of some trade names, +trademarks, or service marks; or + +f) Requiring indemnification of licensors and authors of that material by +anyone who conveys the material (or modified versions of it) with contractual +assumptions of liability to the recipient, for any liability that these contractual +assumptions directly impose on those licensors and authors. + +All other non-permissive additional terms are considered "further restrictions" +within the meaning of section 10. If the Program as you received it, or any +part of it, contains a notice stating that it is governed by this License +along with a term that is a further restriction, you may remove that term. +If a license document contains a further restriction but permits relicensing +or conveying under this License, you may add to a covered work material governed +by the terms of that license document, provided that the further restriction +does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, +in the relevant source files, a statement of the additional terms that apply +to those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form +of a separately written license, or stated as exceptions; the above requirements +apply either way. + + 8. Termination. + +You may not propagate or modify a covered work except as expressly provided +under this License. Any attempt otherwise to propagate or modify it is void, +and will automatically terminate your rights under this License (including +any patent licenses granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from +a particular copyright holder is reinstated (a) provisionally, unless and +until the copyright holder explicitly and finally terminates your license, +and (b) permanently, if the copyright holder fails to notify you of the violation +by some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently +if the copyright holder notifies you of the violation by some reasonable means, +this is the first time you have received notice of violation of this License +(for any work) from that copyright holder, and you cure the violation prior +to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses +of parties who have received copies or rights from you under this License. +If your rights have been terminated and not permanently reinstated, you do +not qualify to receive new licenses for the same material under section 10. + + 9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run a copy +of the Program. Ancillary propagation of a covered work occurring solely as +a consequence of using peer-to-peer transmission to receive a copy likewise +does not require acceptance. However, nothing other than this License grants +you permission to propagate or modify any covered work. These actions infringe +copyright if you do not accept this License. Therefore, by modifying or propagating +a covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically receives +a license from the original licensors, to run, modify and propagate that work, +subject to this License. You are not responsible for enforcing compliance +by third parties with this License. + +An "entity transaction" is a transaction transferring control of an organization, +or substantially all assets of one, or subdividing an organization, or merging +organizations. If propagation of a covered work results from an entity transaction, +each party to that transaction who receives a copy of the work also receives +whatever licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the Corresponding +Source of the work from the predecessor in interest, if the predecessor has +it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights +granted or affirmed under this License. For example, you may not impose a +license fee, royalty, or other charge for exercise of rights granted under +this License, and you may not initiate litigation (including a cross-claim +or counterclaim in a lawsuit) alleging that any patent claim is infringed +by making, using, selling, offering for sale, or importing the Program or +any portion of it. + + 11. Patents. + +A "contributor" is a copyright holder who authorizes use under this License +of the Program or a work on which the Program is based. The work thus licensed +is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims owned or controlled +by the contributor, whether already acquired or hereafter acquired, that would +be infringed by some manner, permitted by this License, of making, using, +or selling its contributor version, but do not include claims that would be +infringed only as a consequence of further modification of the contributor +version. For purposes of this definition, "control" includes the right to +grant patent sublicenses in a manner consistent with the requirements of this +License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent +license under the contributor's essential patent claims, to make, use, sell, +offer for sale, import and otherwise run, modify and propagate the contents +of its contributor version. + +In the following three paragraphs, a "patent license" is any express agreement +or commitment, however denominated, not to enforce a patent (such as an express +permission to practice a patent or covenant not to sue for patent infringement). +To "grant" such a patent license to a party means to make such an agreement +or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the +Corresponding Source of the work is not available for anyone to copy, free +of charge and under the terms of this License, through a publicly available +network server or other readily accessible means, then you must either (1) +cause the Corresponding Source to be so available, or (2) arrange to deprive +yourself of the benefit of the patent license for this particular work, or +(3) arrange, in a manner consistent with the requirements of this License, +to extend the patent license to downstream recipients. "Knowingly relying" +means you have actual knowledge that, but for the patent license, your conveying +the covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that country +that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, +you convey, or propagate by procuring conveyance of, a covered work, and grant +a patent license to some of the parties receiving the covered work authorizing +them to use, propagate, modify or convey a specific copy of the covered work, +then the patent license you grant is automatically extended to all recipients +of the covered work and works based on it. + +A patent license is "discriminatory" if it does not include within the scope +of its coverage, prohibits the exercise of, or is conditioned on the non-exercise +of one or more of the rights that are specifically granted under this License. +You may not convey a covered work if you are a party to an arrangement with +a third party that is in the business of distributing software, under which +you make payment to the third party based on the extent of your activity of +conveying the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by you +(or copies made from those copies), or (b) primarily for and in connection +with specific products or compilations that contain the covered work, unless +you entered into that arrangement, or that patent license was granted, prior +to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied +license or other defenses to infringement that may otherwise be available +to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or otherwise) +that contradict the conditions of this License, they do not excuse you from +the conditions of this License. If you cannot convey a covered work so as +to satisfy simultaneously your obligations under this License and any other +pertinent obligations, then as a consequence you may not convey it at all. +For example, if you agree to terms that obligate you to collect a royalty +for further conveying from those to whom you convey the Program, the only +way you could satisfy both those terms and this License would be to refrain +entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have permission to +link or combine any covered work with a work licensed under version 3 of the +GNU Affero General Public License into a single combined work, and to convey +the resulting work. The terms of this License will continue to apply to the +part which is the covered work, but the special requirements of the GNU Affero +General Public License, section 13, concerning interaction through a network +will apply to the combination as such. + + 14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions of the +GNU General Public License from time to time. Such new versions will be similar +in spirit to the present version, but may differ in detail to address new +problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies +that a certain numbered version of the GNU General Public License "or any +later version" applies to it, you have the option of following the terms and +conditions either of that numbered version or of any later version published +by the Free Software Foundation. If the Program does not specify a version +number of the GNU General Public License, you may choose any version ever +published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions of +the GNU General Public License can be used, that proxy's public statement +of acceptance of a version permanently authorizes you to choose that version +for the Program. + +Later license versions may give you additional or different permissions. However, +no additional obligations are imposed on any author or copyright holder as +a result of your choosing to follow a later version. + + 15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE +LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM +PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + + 16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM +AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO +USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED +INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE +PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided above cannot +be given local legal effect according to their terms, reviewing courts shall +apply local law that most closely approximates an absolute waiver of all civil +liability in connection with the Program, unless a warranty or assumption +of liability accompanies a copy of the Program in return for a fee. END OF +TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively state the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + + +Copyright (C) + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like +this when it starts in an interactive mode: + + Copyright (C) + +This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + +This is free software, and you are welcome to redistribute it under certain +conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands might +be different; for a GUI interface, you would use an "about box". + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU GPL, see . + +The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General Public +License instead of this License. But first, please read . diff --git a/README.md b/README.md new file mode 100755 index 0000000..79789c2 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# 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. diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000..c2e2135 --- /dev/null +++ b/compile.sh @@ -0,0 +1,19 @@ +#!/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 diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..5ec3b17 --- /dev/null +++ b/install.sh @@ -0,0 +1,53 @@ +#!/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 diff --git a/test b/test new file mode 100755 index 0000000..7eae4d2 Binary files /dev/null and b/test differ diff --git a/test.c b/test.c new file mode 100644 index 0000000..8b241cb --- /dev/null +++ b/test.c @@ -0,0 +1,79 @@ +#define use_mathematics + +#include "xtandard.h" +#include "xector.h" +#include "xarticle.h" + +#include + +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); +} diff --git a/xachine.h b/xachine.h new file mode 100755 index 0000000..aaed02a --- /dev/null +++ b/xachine.h @@ -0,0 +1,456 @@ +/// _ _ +/// __ ____ _ ___| |__ (_)_ __ ___ +/// \ \/ / _` |/ __| '_ \| | '_ \ / _ \ +/// > < (_| | (__| | | | | | | | __/ +/// /_/\_\__,_|\___|_| |_|_|_| |_|\___| +/// +/// 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)); +} diff --git a/xanguage.h b/xanguage.h new file mode 100755 index 0000000..3efd312 --- /dev/null +++ b/xanguage.h @@ -0,0 +1,201 @@ +/// __ ____ _ _ __ __ _ _ _ __ _ __ _ ___ +/// \ \/ / _` | '_ \ / _` | | | |/ _` |/ _` |/ _ \ +/// > < (_| | | | | (_| | |_| | (_| | (_| | __/ +/// /_/\_\__,_|_| |_|\__, |\__,_|\__,_|\__, |\___| +/// |___/ |___/ +/// +/// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); + } + } +} diff --git a/xanguage/ada.h b/xanguage/ada.h new file mode 100755 index 0000000..0e453b1 --- /dev/null +++ b/xanguage/ada.h @@ -0,0 +1,31 @@ +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); +} diff --git a/xanguage/bash.h b/xanguage/bash.h new file mode 100755 index 0000000..351c2f3 --- /dev/null +++ b/xanguage/bash.h @@ -0,0 +1,24 @@ +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); +} diff --git a/xanguage/c++.h b/xanguage/c++.h new file mode 100755 index 0000000..131176d --- /dev/null +++ b/xanguage/c++.h @@ -0,0 +1,53 @@ +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); +} diff --git a/xanguage/c.h b/xanguage/c.h new file mode 100755 index 0000000..8005724 --- /dev/null +++ b/xanguage/c.h @@ -0,0 +1,49 @@ +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); +} diff --git a/xanguage/common.h b/xanguage/common.h new file mode 100755 index 0000000..652b10b --- /dev/null +++ b/xanguage/common.h @@ -0,0 +1,9 @@ +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); +} diff --git a/xanguage/d.h b/xanguage/d.h new file mode 100755 index 0000000..d5a043a --- /dev/null +++ b/xanguage/d.h @@ -0,0 +1,49 @@ +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); +} diff --git a/xanguage/eaxhla.h b/xanguage/eaxhla.h new file mode 100755 index 0000000..ca99f20 --- /dev/null +++ b/xanguage/eaxhla.h @@ -0,0 +1,79 @@ +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); +} diff --git a/xanguage/flat.h b/xanguage/flat.h new file mode 100755 index 0000000..eabf301 --- /dev/null +++ b/xanguage/flat.h @@ -0,0 +1,66 @@ +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); +} diff --git a/xanguage/fortran.h b/xanguage/fortran.h new file mode 100755 index 0000000..e24923a --- /dev/null +++ b/xanguage/fortran.h @@ -0,0 +1,47 @@ +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); +} diff --git a/xanguage/go.h b/xanguage/go.h new file mode 100755 index 0000000..38919e8 --- /dev/null +++ b/xanguage/go.h @@ -0,0 +1,46 @@ +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); +} diff --git a/xanguage/haskell.h b/xanguage/haskell.h new file mode 100755 index 0000000..5766d29 --- /dev/null +++ b/xanguage/haskell.h @@ -0,0 +1,34 @@ +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); +} diff --git a/xanguage/lua.h b/xanguage/lua.h new file mode 100755 index 0000000..1509e86 --- /dev/null +++ b/xanguage/lua.h @@ -0,0 +1,50 @@ +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); +} diff --git a/xanguage/pascal.h b/xanguage/pascal.h new file mode 100755 index 0000000..21bac25 --- /dev/null +++ b/xanguage/pascal.h @@ -0,0 +1,29 @@ +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); +} diff --git a/xanguage/python.h b/xanguage/python.h new file mode 100755 index 0000000..ccd8dcd --- /dev/null +++ b/xanguage/python.h @@ -0,0 +1,47 @@ +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); +} diff --git a/xanguage/valgrind.h b/xanguage/valgrind.h new file mode 100755 index 0000000..411f580 --- /dev/null +++ b/xanguage/valgrind.h @@ -0,0 +1,25 @@ +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); +} diff --git a/xanual/adc.md b/xanual/adc.md new file mode 100755 index 0000000..c70de61 --- /dev/null +++ b/xanual/adc.md @@ -0,0 +1,52 @@ +# 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. diff --git a/xanual/add.md b/xanual/add.md new file mode 100755 index 0000000..5460984 --- /dev/null +++ b/xanual/add.md @@ -0,0 +1,48 @@ +# 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. diff --git a/xanual/and.md b/xanual/and.md new file mode 100755 index 0000000..ce79ef2 --- /dev/null +++ b/xanual/and.md @@ -0,0 +1,45 @@ +# 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. diff --git a/xanual/call.md b/xanual/call.md new file mode 100755 index 0000000..da34cdd --- /dev/null +++ b/xanual/call.md @@ -0,0 +1,201 @@ +# 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. diff --git a/xanual/cmovcc.md b/xanual/cmovcc.md new file mode 100755 index 0000000..8530e76 --- /dev/null +++ b/xanual/cmovcc.md @@ -0,0 +1,121 @@ +# 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. diff --git a/xanual/cmp.md b/xanual/cmp.md new file mode 100755 index 0000000..88eb3ff --- /dev/null +++ b/xanual/cmp.md @@ -0,0 +1,45 @@ +# 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. diff --git a/xanual/dec.md b/xanual/dec.md new file mode 100755 index 0000000..faa890b --- /dev/null +++ b/xanual/dec.md @@ -0,0 +1,31 @@ +# 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. diff --git a/xanual/div.md b/xanual/div.md new file mode 100755 index 0000000..3407c95 --- /dev/null +++ b/xanual/div.md @@ -0,0 +1,28 @@ +# 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. diff --git a/xanual/enter.md b/xanual/enter.md new file mode 100755 index 0000000..6b7fd8b --- /dev/null +++ b/xanual/enter.md @@ -0,0 +1,46 @@ +# 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. diff --git a/xanual/idiv.md b/xanual/idiv.md new file mode 100755 index 0000000..75ff099 --- /dev/null +++ b/xanual/idiv.md @@ -0,0 +1,28 @@ +# 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. diff --git a/xanual/imul.md b/xanual/imul.md new file mode 100755 index 0000000..1bb5c76 --- /dev/null +++ b/xanual/imul.md @@ -0,0 +1,66 @@ +# 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. diff --git a/xanual/inc.md b/xanual/inc.md new file mode 100755 index 0000000..9207cd5 --- /dev/null +++ b/xanual/inc.md @@ -0,0 +1,31 @@ +# 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. diff --git a/xanual/jcc.md b/xanual/jcc.md new file mode 100755 index 0000000..afc0e47 --- /dev/null +++ b/xanual/jcc.md @@ -0,0 +1,147 @@ +# 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. diff --git a/xanual/jmp.md b/xanual/jmp.md new file mode 100755 index 0000000..65c5967 --- /dev/null +++ b/xanual/jmp.md @@ -0,0 +1,103 @@ +# 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. diff --git a/xanual/leave.md b/xanual/leave.md new file mode 100755 index 0000000..9414082 --- /dev/null +++ b/xanual/leave.md @@ -0,0 +1,20 @@ +# 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. diff --git a/xanual/mov.md b/xanual/mov.md new file mode 100755 index 0000000..2e91c6c --- /dev/null +++ b/xanual/mov.md @@ -0,0 +1,78 @@ +# 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. diff --git a/xanual/mul.md b/xanual/mul.md new file mode 100755 index 0000000..10ae89e --- /dev/null +++ b/xanual/mul.md @@ -0,0 +1,28 @@ + 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. diff --git a/xanual/neg.md b/xanual/neg.md new file mode 100755 index 0000000..e919a4e --- /dev/null +++ b/xanual/neg.md @@ -0,0 +1,26 @@ +# 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. diff --git a/xanual/nop.md b/xanual/nop.md new file mode 100755 index 0000000..aab6665 --- /dev/null +++ b/xanual/nop.md @@ -0,0 +1,40 @@ +# 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` diff --git a/xanual/not.md b/xanual/not.md new file mode 100755 index 0000000..545dccc --- /dev/null +++ b/xanual/not.md @@ -0,0 +1,26 @@ +# 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. diff --git a/xanual/or.md b/xanual/or.md new file mode 100755 index 0000000..cad76ef --- /dev/null +++ b/xanual/or.md @@ -0,0 +1,45 @@ +# 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. diff --git a/xanual/pop.md b/xanual/pop.md new file mode 100755 index 0000000..bdc0664 --- /dev/null +++ b/xanual/pop.md @@ -0,0 +1,66 @@ +# 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. diff --git a/xanual/push.md b/xanual/push.md new file mode 100755 index 0000000..60ad851 --- /dev/null +++ b/xanual/push.md @@ -0,0 +1,55 @@ +# 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. diff --git a/xanual/ret.md b/xanual/ret.md new file mode 100755 index 0000000..65aa948 --- /dev/null +++ b/xanual/ret.md @@ -0,0 +1,52 @@ +# 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. diff --git a/xanual/rot.md b/xanual/rot.md new file mode 100755 index 0000000..9ad236a --- /dev/null +++ b/xanual/rot.md @@ -0,0 +1,94 @@ +# 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. diff --git a/xanual/sbb.md b/xanual/sbb.md new file mode 100755 index 0000000..537839d --- /dev/null +++ b/xanual/sbb.md @@ -0,0 +1,54 @@ +# 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. diff --git a/xanual/setcc.md b/xanual/setcc.md new file mode 100755 index 0000000..79c815e --- /dev/null +++ b/xanual/setcc.md @@ -0,0 +1,89 @@ +# 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. diff --git a/xanual/sft.md b/xanual/sft.md new file mode 100755 index 0000000..a053948 --- /dev/null +++ b/xanual/sft.md @@ -0,0 +1,110 @@ +# 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. diff --git a/xanual/sub.md b/xanual/sub.md new file mode 100755 index 0000000..179b2ec --- /dev/null +++ b/xanual/sub.md @@ -0,0 +1,48 @@ +# 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. diff --git a/xanual/syscall.md b/xanual/syscall.md new file mode 100755 index 0000000..c3020e9 --- /dev/null +++ b/xanual/syscall.md @@ -0,0 +1,27 @@ +# 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. diff --git a/xanual/sysenter.md b/xanual/sysenter.md new file mode 100755 index 0000000..82d8347 --- /dev/null +++ b/xanual/sysenter.md @@ -0,0 +1,61 @@ +# 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. diff --git a/xanual/sysexit.md b/xanual/sysexit.md new file mode 100755 index 0000000..1261727 --- /dev/null +++ b/xanual/sysexit.md @@ -0,0 +1,46 @@ +# 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. diff --git a/xanual/sysret.md b/xanual/sysret.md new file mode 100755 index 0000000..251d7d7 --- /dev/null +++ b/xanual/sysret.md @@ -0,0 +1,42 @@ +# 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. diff --git a/xanual/template.md b/xanual/template.md new file mode 100755 index 0000000..9b7abf8 --- /dev/null +++ b/xanual/template.md @@ -0,0 +1,15 @@ +# + +## Description + + + +## Instruction + +| Opcode | Assembly | Op/En | Modern Mode | Legacy Mode | Description | +|--------|-------------|-------|-------------|-------------|-----------------------------------------------------------------------------------| + + +## Information + + diff --git a/xanual/xor.md b/xanual/xor.md new file mode 100755 index 0000000..81b28b9 --- /dev/null +++ b/xanual/xor.md @@ -0,0 +1,44 @@ +# 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. diff --git a/xaptor b/xaptor new file mode 100755 index 0000000..68c322e Binary files /dev/null and b/xaptor differ diff --git a/xaptor.c b/xaptor.c new file mode 100644 index 0000000..cf59554 --- /dev/null +++ b/xaptor.c @@ -0,0 +1,44 @@ +#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 +#include +#include +#include + +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); +} diff --git a/xaptor.h b/xaptor.h new file mode 100644 index 0000000..8567acf --- /dev/null +++ b/xaptor.h @@ -0,0 +1,679 @@ +/// _ +/// __ ____ _ _ __ | |_ ___ _ __ +/// \ \/ / _` | '_ \| __/ _ \| '__| +/// > < (_| | |_) | || (_) | | +/// /_/\_\__,_| .__/ \__\___/|_| +/// |_| +/// +/// 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 +#include + +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); +} diff --git a/xarbon.c b/xarbon.c new file mode 100755 index 0000000..a1bda6c --- /dev/null +++ b/xarbon.c @@ -0,0 +1,274 @@ +/// _ +/// __ ____ _ _ __| |__ ___ _ __ +/// \ \/ / _` | '__| '_ \ / _ \| '_ | +/// > < (_| | | | |_) | (_) | | | | +/// /_/\_\__,_|_| |_.__/ \___/|_| |_| +/// +/// 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 +#include +#include +#include + +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); +} diff --git a/xarticle.h b/xarticle.h new file mode 100644 index 0000000..6c0f7bd --- /dev/null +++ b/xarticle.h @@ -0,0 +1,170 @@ +/// _ _ _ +/// __ ____ _ _ __| |_(_) ___| | ___ +/// \ \/ / _` | '__| __| |/ __| |/ _ \ +/// > < (_| | | | |_| | (__| | __/ +/// /_/\_\__,_|_| \__|_|\___|_|\___| +/// +/// 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]); + } +} diff --git a/xatrix.h b/xatrix.h new file mode 100644 index 0000000..b0d8c8a --- /dev/null +++ b/xatrix.h @@ -0,0 +1,510 @@ +/// _ _ +/// __ ____ _| |_ _ __(_)_ __ +/// \ \/ / _` | __| '__| \ \/ / +/// > < (_| | |_| | | |> < +/// /_/\_\__,_|\__|_| |_/_/\_\ +/// +/// 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; + } + } +} diff --git a/xcript.h b/xcript.h new file mode 100755 index 0000000..6266e06 --- /dev/null +++ b/xcript.h @@ -0,0 +1,383 @@ +/// _ _ +/// __ _____ _ __(_)_ __ | |_ +/// \ \/ / __| '__| | '_ \| __| +/// > < (__| | | | |_) | |_ +/// /_/\_\___|_| |_| .__/ \__| +/// |_| +/// +/// 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); +} diff --git a/xector.h b/xector.h new file mode 100755 index 0000000..22e49b6 --- /dev/null +++ b/xector.h @@ -0,0 +1,388 @@ +/// _ +/// __ _____ ___| |_ ___ _ __ +/// \ \/ / _ \/ __| __/ _ \| '__| +/// > < __/ (__| || (_) | | +/// /_/\_\___|\___|\__\___/|_| +/// +/// 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); +} diff --git a/xhallenge.c b/xhallenge.c new file mode 100755 index 0000000..2e97aa4 --- /dev/null +++ b/xhallenge.c @@ -0,0 +1,531 @@ +#define use_fatal_failure + +#include +#include +#include + +#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); +} diff --git a/xhallenge_list.cfg b/xhallenge_list.cfg new file mode 100755 index 0000000..2ce3364 --- /dev/null +++ b/xhallenge_list.cfg @@ -0,0 +1,433 @@ +[] 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" diff --git a/xiasma.h b/xiasma.h new file mode 100755 index 0000000..c699e27 --- /dev/null +++ b/xiasma.h @@ -0,0 +1,694 @@ +/// _ +/// __ _(_) __ _ ___ _ __ ___ __ _ +/// \ \/ / |/ _` / __| '_ ` _ \ / _` | +/// > <| | (_| \__ \ | | | | | (_| | +/// /_/\_\_|\__,_|___/_| |_| |_|\__,_| +/// +/// 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); +} diff --git a/xighlight.c b/xighlight.c new file mode 100755 index 0000000..aa792c6 --- /dev/null +++ b/xighlight.c @@ -0,0 +1,127 @@ +/// _ _ _ _ _ _ +/// __ _(_) __ _| |__ | (_) __ _| |__ | |_ +/// \ \/ / |/ _` | '_ \| | |/ _` | '_ \| __| +/// > <| | (_| | | | | | | (_| | | | | |_ +/// /_/\_\_|\__, |_| |_|_|_|\__, |_| |_|\__| +/// |___/ |___/ +/// +/// 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 +#include +#include + +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); +} diff --git a/xogueout b/xogueout new file mode 100755 index 0000000..e19639b Binary files /dev/null and b/xogueout differ diff --git a/xogueout.c b/xogueout.c new file mode 100644 index 0000000..7011063 --- /dev/null +++ b/xogueout.c @@ -0,0 +1,50 @@ +/// _ +/// __ _____ __ _ _ _ ___ ___ _ _| |_ +/// \ \/ / _ \ / _` | | | |/ _ \/ _ \| | | | __| +/// > < (_) | (_| | |_| | __/ (_) | |_| | |_ +/// /_/\_\___/ \__, |\__,_|\___|\___/ \__,_|\__| +/// |___/ +/// +/// 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 +#include +#include + +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); +} diff --git a/xommon.h b/xommon.h new file mode 100755 index 0000000..91ba248 --- /dev/null +++ b/xommon.h @@ -0,0 +1,666 @@ +/// __ _____ _ __ ___ _ __ ___ ___ _ __ +/// \ \/ / _ \| '_ ` _ \| '_ ` _ \ / _ \| '_ \ +/// > < (_) | | | | | | | | | | | (_) | | | | +/// /_/\_\___/|_| |_| |_|_| |_| |_|\___/|_| |_| +/// +/// 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 +#include +#include +//~#include + +#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]); + } +} diff --git a/xop.c b/xop.c new file mode 100755 index 0000000..dc6aeeb --- /dev/null +++ b/xop.c @@ -0,0 +1,43 @@ +#include + +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); +} diff --git a/xormat.h b/xormat.h new file mode 100644 index 0000000..992d710 --- /dev/null +++ b/xormat.h @@ -0,0 +1,122 @@ +/// _ +/// __ _____ _ __ _ __ ___ __ _| |_ +/// \ \/ / _ \| '__| '_ ` _ \ / _` | __| +/// > < (_) | | | | | | | | (_| | |_ +/// /_/\_\___/|_| |_| |_| |_|\__,_|\__| +/// +/// 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 +#endif + +#ifdef use_jxl_library +#include +#endif + +#ifdef use_jpg_library +#include +#endif + +#ifdef use_tga_library +#include +#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); +} diff --git a/xormat/jxl.h b/xormat/jxl.h new file mode 100644 index 0000000..91754ad --- /dev/null +++ b/xormat/jxl.h @@ -0,0 +1,68 @@ +#include + +#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); +} diff --git a/xormat/png.h b/xormat/png.h new file mode 100644 index 0000000..e7b5bdb --- /dev/null +++ b/xormat/png.h @@ -0,0 +1,106 @@ +#include +#include + +#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); +} diff --git a/xpenal.h b/xpenal.h new file mode 100755 index 0000000..736b75b --- /dev/null +++ b/xpenal.h @@ -0,0 +1,19 @@ +/// _ +/// __ ___ __ ___ _ __ __ _| | +/// \ \/ / '_ \ / _ \ '_ \ / _` | | +/// > <| |_) | __/ | | | (_| | | +/// /_/\_\ .__/ \___|_| |_|\__,_|_| +/// |_| +/// +/// 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... diff --git a/xpengl.h b/xpengl.h new file mode 100755 index 0000000..125b6ca --- /dev/null +++ b/xpengl.h @@ -0,0 +1,1209 @@ +/// _ +/// __ ___ __ ___ _ __ __ _| | +/// \ \/ / '_ \ / _ \ '_ \ / _` | | +/// > <| |_) | __/ | | | (_| | | +/// /_/\_\ .__/ \___|_| |_|\__, |_| +/// |_| |___/ +/// +/// 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 + +#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 diff --git a/xphere.h b/xphere.h new file mode 100755 index 0000000..813c8c5 --- /dev/null +++ b/xphere.h @@ -0,0 +1,86 @@ +/// _ +/// __ ___ __ | |__ ___ _ __ ___ +/// \ \/ / '_ \| '_ \ / _ \ '__/ _ \ +/// > <| |_) | | | | __/ | | __/ +/// /_/\_\ .__/|_| |_|\___|_| \___| +/// |_| +/// +/// 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); +} diff --git a/xprite.h b/xprite.h new file mode 100755 index 0000000..8753a9e --- /dev/null +++ b/xprite.h @@ -0,0 +1,131 @@ +/// _ _ +/// __ ___ __ _ __(_) |_ ___ +/// \ \/ / '_ \| '__| | __/ _ \ +/// > <| |_) | | | | || __/ +/// /_/\_\ .__/|_| |_|\__\___| +/// |_| +/// +/// 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); + } +} diff --git a/xrocessor.h b/xrocessor.h new file mode 100755 index 0000000..6b606b1 --- /dev/null +++ b/xrocessor.h @@ -0,0 +1,303 @@ +/// __ ___ __ ___ ___ ___ ___ ___ ___ _ __ +/// \ \/ / '__/ _ \ / __/ _ \/ __/ __|/ _ \| '__| +/// > <| | | (_) | (_| __/\__ \__ \ (_) | | +/// /_/\_\_| \___/ \___\___||___/___/\___/|_| +/// +/// 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 +//~#include + +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); +//~} diff --git a/xross.h b/xross.h new file mode 100755 index 0000000..c23ad6d --- /dev/null +++ b/xross.h @@ -0,0 +1,190 @@ +/// __ ___ __ ___ ___ ___ +/// \ \/ / '__/ _ \/ __/ __| +/// > <| | | (_) \__ \__ \ +/// /_/\_\_| \___/|___/___/ +/// +/// 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 diff --git a/xscii.c b/xscii.c new file mode 100755 index 0000000..ad22a13 --- /dev/null +++ b/xscii.c @@ -0,0 +1,99 @@ +#include + +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); +} diff --git a/xtandard.h b/xtandard.h new file mode 100755 index 0000000..b0be1ab --- /dev/null +++ b/xtandard.h @@ -0,0 +1,1136 @@ +/// _ _ _ +/// | | | | | | +/// __ _| |_ __ _ _ __ __| | __ _ _ __ __| | +/// \ \/ / __/ _` | '_ \ / _` |/ _` | '__/ _` | +/// > <| || (_| | | | | (_| | (_| | | | (_| | +/// /_/\_\\__\__,_|_| |_|\__,_|\__,_|_| \__,_| +/// +/// 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 +#include +#include +#include +#include +#include +#include + +#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 + +#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 diff --git a/xui.h b/xui.h new file mode 100755 index 0000000..4c4ee36 --- /dev/null +++ b/xui.h @@ -0,0 +1,392 @@ +/// _ +/// __ ___ _(_) +/// \ \/ / | | | | +/// > <| |_| | | +/// /_/\_\\__,_|_| +/// +/// 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); + } +} diff --git a/xui/common/fullscreen_off.png b/xui/common/fullscreen_off.png new file mode 100755 index 0000000..eb8c813 Binary files /dev/null and b/xui/common/fullscreen_off.png differ diff --git a/xui/common/fullscreen_on.png b/xui/common/fullscreen_on.png new file mode 100755 index 0000000..5d1c0b3 Binary files /dev/null and b/xui/common/fullscreen_on.png differ diff --git a/xui/common/map_preview_panel_off.png b/xui/common/map_preview_panel_off.png new file mode 100755 index 0000000..d0fb58a Binary files /dev/null and b/xui/common/map_preview_panel_off.png differ diff --git a/xui/common/map_preview_panel_on.png b/xui/common/map_preview_panel_on.png new file mode 100755 index 0000000..08dd569 Binary files /dev/null and b/xui/common/map_preview_panel_on.png differ diff --git a/xui/common/monospace.png b/xui/common/monospace.png new file mode 100755 index 0000000..074f192 Binary files /dev/null and b/xui/common/monospace.png differ diff --git a/xui/common/palette.png b/xui/common/palette.png new file mode 100755 index 0000000..8a8ab27 Binary files /dev/null and b/xui/common/palette.png differ diff --git a/xui/common/regular.png b/xui/common/regular.png new file mode 100755 index 0000000..0e5bfe7 Binary files /dev/null and b/xui/common/regular.png differ diff --git a/xui/common/status_preview_panel_off.png b/xui/common/status_preview_panel_off.png new file mode 100755 index 0000000..fdb5173 Binary files /dev/null and b/xui/common/status_preview_panel_off.png differ diff --git a/xui/common/status_preview_panel_on.png b/xui/common/status_preview_panel_on.png new file mode 100755 index 0000000..530fc12 Binary files /dev/null and b/xui/common/status_preview_panel_on.png differ diff --git a/xui/common/text_box_panel_off.png b/xui/common/text_box_panel_off.png new file mode 100755 index 0000000..06efe6c Binary files /dev/null and b/xui/common/text_box_panel_off.png differ diff --git a/xui/common/text_box_panel_on.png b/xui/common/text_box_panel_on.png new file mode 100755 index 0000000..0576c96 Binary files /dev/null and b/xui/common/text_box_panel_on.png differ diff --git a/xui/dwarf/button_left.png b/xui/dwarf/button_left.png new file mode 100755 index 0000000..0631351 Binary files /dev/null and b/xui/dwarf/button_left.png differ diff --git a/xui/dwarf/button_lower.png b/xui/dwarf/button_lower.png new file mode 100755 index 0000000..01ce842 Binary files /dev/null and b/xui/dwarf/button_lower.png differ diff --git a/xui/dwarf/button_lower_left.png b/xui/dwarf/button_lower_left.png new file mode 100755 index 0000000..f75c4de Binary files /dev/null and b/xui/dwarf/button_lower_left.png differ diff --git a/xui/dwarf/button_lower_right.png b/xui/dwarf/button_lower_right.png new file mode 100755 index 0000000..27ae523 Binary files /dev/null and b/xui/dwarf/button_lower_right.png differ diff --git a/xui/dwarf/button_middle.png b/xui/dwarf/button_middle.png new file mode 100755 index 0000000..f44ef76 Binary files /dev/null and b/xui/dwarf/button_middle.png differ diff --git a/xui/dwarf/button_right.png b/xui/dwarf/button_right.png new file mode 100755 index 0000000..6ccd9af Binary files /dev/null and b/xui/dwarf/button_right.png differ diff --git a/xui/dwarf/button_upper.png b/xui/dwarf/button_upper.png new file mode 100755 index 0000000..4e57d92 Binary files /dev/null and b/xui/dwarf/button_upper.png differ diff --git a/xui/dwarf/button_upper_left.png b/xui/dwarf/button_upper_left.png new file mode 100755 index 0000000..e6bde50 Binary files /dev/null and b/xui/dwarf/button_upper_left.png differ diff --git a/xui/dwarf/button_upper_right.png b/xui/dwarf/button_upper_right.png new file mode 100755 index 0000000..b44cd48 Binary files /dev/null and b/xui/dwarf/button_upper_right.png differ diff --git a/xui/dwarf/check_box_off.png b/xui/dwarf/check_box_off.png new file mode 100755 index 0000000..5a0b5d1 Binary files /dev/null and b/xui/dwarf/check_box_off.png differ diff --git a/xui/dwarf/check_box_on.png b/xui/dwarf/check_box_on.png new file mode 100755 index 0000000..8c1d977 Binary files /dev/null and b/xui/dwarf/check_box_on.png differ diff --git a/xui/dwarf/cursor.png b/xui/dwarf/cursor.png new file mode 100755 index 0000000..918d594 Binary files /dev/null and b/xui/dwarf/cursor.png differ diff --git a/xui/dwarf/end_turn_button.png b/xui/dwarf/end_turn_button.png new file mode 100755 index 0000000..b89b15c Binary files /dev/null and b/xui/dwarf/end_turn_button.png differ diff --git a/xui/dwarf/fill_bar_base.png b/xui/dwarf/fill_bar_base.png new file mode 100755 index 0000000..654b381 Binary files /dev/null and b/xui/dwarf/fill_bar_base.png differ diff --git a/xui/dwarf/fill_bar_left.png b/xui/dwarf/fill_bar_left.png new file mode 100755 index 0000000..8723288 Binary files /dev/null and b/xui/dwarf/fill_bar_left.png differ diff --git a/xui/dwarf/fill_bar_middle.png b/xui/dwarf/fill_bar_middle.png new file mode 100755 index 0000000..76ef017 Binary files /dev/null and b/xui/dwarf/fill_bar_middle.png differ diff --git a/xui/dwarf/fill_bar_right.png b/xui/dwarf/fill_bar_right.png new file mode 100755 index 0000000..8aba62c Binary files /dev/null and b/xui/dwarf/fill_bar_right.png differ diff --git a/xui/dwarf/frame_left.png b/xui/dwarf/frame_left.png new file mode 100755 index 0000000..7bbfc97 Binary files /dev/null and b/xui/dwarf/frame_left.png differ diff --git a/xui/dwarf/frame_lower.png b/xui/dwarf/frame_lower.png new file mode 100755 index 0000000..5816643 Binary files /dev/null and b/xui/dwarf/frame_lower.png differ diff --git a/xui/dwarf/frame_lower_left.png b/xui/dwarf/frame_lower_left.png new file mode 100755 index 0000000..f8ad153 Binary files /dev/null and b/xui/dwarf/frame_lower_left.png differ diff --git a/xui/dwarf/frame_lower_right.png b/xui/dwarf/frame_lower_right.png new file mode 100755 index 0000000..7dabfc1 Binary files /dev/null and b/xui/dwarf/frame_lower_right.png differ diff --git a/xui/dwarf/frame_right.png b/xui/dwarf/frame_right.png new file mode 100755 index 0000000..9085408 Binary files /dev/null and b/xui/dwarf/frame_right.png differ diff --git a/xui/dwarf/frame_upper.png b/xui/dwarf/frame_upper.png new file mode 100755 index 0000000..e159058 Binary files /dev/null and b/xui/dwarf/frame_upper.png differ diff --git a/xui/dwarf/frame_upper_left.png b/xui/dwarf/frame_upper_left.png new file mode 100755 index 0000000..ae13b76 Binary files /dev/null and b/xui/dwarf/frame_upper_left.png differ diff --git a/xui/dwarf/frame_upper_right.png b/xui/dwarf/frame_upper_right.png new file mode 100755 index 0000000..fa0d670 Binary files /dev/null and b/xui/dwarf/frame_upper_right.png differ diff --git a/xui/dwarf/icon_frame.png b/xui/dwarf/icon_frame.png new file mode 100755 index 0000000..c61f9e3 Binary files /dev/null and b/xui/dwarf/icon_frame.png differ diff --git a/xui/dwarf/menu_left.png b/xui/dwarf/menu_left.png new file mode 100755 index 0000000..0631351 Binary files /dev/null and b/xui/dwarf/menu_left.png differ diff --git a/xui/dwarf/menu_lower.png b/xui/dwarf/menu_lower.png new file mode 100755 index 0000000..01ce842 Binary files /dev/null and b/xui/dwarf/menu_lower.png differ diff --git a/xui/dwarf/menu_lower_left.png b/xui/dwarf/menu_lower_left.png new file mode 100755 index 0000000..f75c4de Binary files /dev/null and b/xui/dwarf/menu_lower_left.png differ diff --git a/xui/dwarf/menu_lower_right.png b/xui/dwarf/menu_lower_right.png new file mode 100755 index 0000000..27ae523 Binary files /dev/null and b/xui/dwarf/menu_lower_right.png differ diff --git a/xui/dwarf/menu_middle.png b/xui/dwarf/menu_middle.png new file mode 100755 index 0000000..f44ef76 Binary files /dev/null and b/xui/dwarf/menu_middle.png differ diff --git a/xui/dwarf/menu_right.png b/xui/dwarf/menu_right.png new file mode 100755 index 0000000..6ccd9af Binary files /dev/null and b/xui/dwarf/menu_right.png differ diff --git a/xui/dwarf/menu_upper.png b/xui/dwarf/menu_upper.png new file mode 100755 index 0000000..4e57d92 Binary files /dev/null and b/xui/dwarf/menu_upper.png differ diff --git a/xui/dwarf/menu_upper_left.png b/xui/dwarf/menu_upper_left.png new file mode 100755 index 0000000..e6bde50 Binary files /dev/null and b/xui/dwarf/menu_upper_left.png differ diff --git a/xui/dwarf/menu_upper_right.png b/xui/dwarf/menu_upper_right.png new file mode 100755 index 0000000..b44cd48 Binary files /dev/null and b/xui/dwarf/menu_upper_right.png differ diff --git a/xui/dwarf/overicon_frame.png b/xui/dwarf/overicon_frame.png new file mode 100755 index 0000000..c54c9be Binary files /dev/null and b/xui/dwarf/overicon_frame.png differ diff --git a/xui/dwarf/scroll_bar_lower.png b/xui/dwarf/scroll_bar_lower.png new file mode 100755 index 0000000..16f3ef4 Binary files /dev/null and b/xui/dwarf/scroll_bar_lower.png differ diff --git a/xui/dwarf/scroll_bar_middle.png b/xui/dwarf/scroll_bar_middle.png new file mode 100755 index 0000000..19063a7 Binary files /dev/null and b/xui/dwarf/scroll_bar_middle.png differ diff --git a/xui/dwarf/scroll_bar_slider.png b/xui/dwarf/scroll_bar_slider.png new file mode 100755 index 0000000..c54c9be Binary files /dev/null and b/xui/dwarf/scroll_bar_slider.png differ diff --git a/xui/dwarf/scroll_bar_upper.png b/xui/dwarf/scroll_bar_upper.png new file mode 100755 index 0000000..bd3b9a7 Binary files /dev/null and b/xui/dwarf/scroll_bar_upper.png differ diff --git a/xui/dwarf/separator_center.png b/xui/dwarf/separator_center.png new file mode 100755 index 0000000..c54c9be Binary files /dev/null and b/xui/dwarf/separator_center.png differ diff --git a/xui/dwarf/separator_left.png b/xui/dwarf/separator_left.png new file mode 100755 index 0000000..23b9cfe Binary files /dev/null and b/xui/dwarf/separator_left.png differ diff --git a/xui/dwarf/separator_middle.png b/xui/dwarf/separator_middle.png new file mode 100755 index 0000000..3db79c4 Binary files /dev/null and b/xui/dwarf/separator_middle.png differ diff --git a/xui/dwarf/separator_right.png b/xui/dwarf/separator_right.png new file mode 100755 index 0000000..7f6f4ce Binary files /dev/null and b/xui/dwarf/separator_right.png differ diff --git a/xui/dwarf/status_left.png b/xui/dwarf/status_left.png new file mode 100755 index 0000000..99020ed Binary files /dev/null and b/xui/dwarf/status_left.png differ diff --git a/xui/dwarf/status_lower.png b/xui/dwarf/status_lower.png new file mode 100755 index 0000000..1c0a3e7 Binary files /dev/null and b/xui/dwarf/status_lower.png differ diff --git a/xui/dwarf/status_lower_left.png b/xui/dwarf/status_lower_left.png new file mode 100755 index 0000000..fc161cc Binary files /dev/null and b/xui/dwarf/status_lower_left.png differ diff --git a/xui/dwarf/status_lower_right.png b/xui/dwarf/status_lower_right.png new file mode 100755 index 0000000..3366adb Binary files /dev/null and b/xui/dwarf/status_lower_right.png differ diff --git a/xui/dwarf/status_middle.png b/xui/dwarf/status_middle.png new file mode 100755 index 0000000..76de51a Binary files /dev/null and b/xui/dwarf/status_middle.png differ diff --git a/xui/dwarf/status_right.png b/xui/dwarf/status_right.png new file mode 100755 index 0000000..99020ed Binary files /dev/null and b/xui/dwarf/status_right.png differ diff --git a/xui/dwarf/status_upper.png b/xui/dwarf/status_upper.png new file mode 100755 index 0000000..1c0a3e7 Binary files /dev/null and b/xui/dwarf/status_upper.png differ diff --git a/xui/dwarf/status_upper_left.png b/xui/dwarf/status_upper_left.png new file mode 100755 index 0000000..3d8c271 Binary files /dev/null and b/xui/dwarf/status_upper_left.png differ diff --git a/xui/dwarf/status_upper_right.png b/xui/dwarf/status_upper_right.png new file mode 100755 index 0000000..00c9afb Binary files /dev/null and b/xui/dwarf/status_upper_right.png differ diff --git a/xui/dwarf/tiny_fill_bar_base.png b/xui/dwarf/tiny_fill_bar_base.png new file mode 100755 index 0000000..91f835c Binary files /dev/null and b/xui/dwarf/tiny_fill_bar_base.png differ diff --git a/xui/dwarf/tiny_fill_bar_left.png b/xui/dwarf/tiny_fill_bar_left.png new file mode 100755 index 0000000..bf129c0 Binary files /dev/null and b/xui/dwarf/tiny_fill_bar_left.png differ diff --git a/xui/dwarf/tiny_fill_bar_middle.png b/xui/dwarf/tiny_fill_bar_middle.png new file mode 100755 index 0000000..a872221 Binary files /dev/null and b/xui/dwarf/tiny_fill_bar_middle.png differ diff --git a/xui/dwarf/tiny_fill_bar_right.png b/xui/dwarf/tiny_fill_bar_right.png new file mode 100755 index 0000000..c35665a Binary files /dev/null and b/xui/dwarf/tiny_fill_bar_right.png differ diff --git a/xui/dwarf/title_bar_left.png b/xui/dwarf/title_bar_left.png new file mode 100755 index 0000000..96a3bbb Binary files /dev/null and b/xui/dwarf/title_bar_left.png differ diff --git a/xui/dwarf/title_bar_middle.png b/xui/dwarf/title_bar_middle.png new file mode 100755 index 0000000..1286a7f Binary files /dev/null and b/xui/dwarf/title_bar_middle.png differ diff --git a/xui/dwarf/title_bar_right.png b/xui/dwarf/title_bar_right.png new file mode 100755 index 0000000..d8dadd2 Binary files /dev/null and b/xui/dwarf/title_bar_right.png differ diff --git a/xui/dwarf/ubericon_frame.png b/xui/dwarf/ubericon_frame.png new file mode 100755 index 0000000..053c144 Binary files /dev/null and b/xui/dwarf/ubericon_frame.png differ diff --git a/xui/dwarf/window_left.png b/xui/dwarf/window_left.png new file mode 100755 index 0000000..0c0c404 Binary files /dev/null and b/xui/dwarf/window_left.png differ diff --git a/xui/dwarf/window_lower.png b/xui/dwarf/window_lower.png new file mode 100755 index 0000000..085ce53 Binary files /dev/null and b/xui/dwarf/window_lower.png differ diff --git a/xui/dwarf/window_lower_left.png b/xui/dwarf/window_lower_left.png new file mode 100755 index 0000000..eee8dac Binary files /dev/null and b/xui/dwarf/window_lower_left.png differ diff --git a/xui/dwarf/window_lower_right.png b/xui/dwarf/window_lower_right.png new file mode 100755 index 0000000..cff21bd Binary files /dev/null and b/xui/dwarf/window_lower_right.png differ diff --git a/xui/dwarf/window_right.png b/xui/dwarf/window_right.png new file mode 100755 index 0000000..0c0c404 Binary files /dev/null and b/xui/dwarf/window_right.png differ diff --git a/xui/dwarf/window_upper.png b/xui/dwarf/window_upper.png new file mode 100755 index 0000000..085ce53 Binary files /dev/null and b/xui/dwarf/window_upper.png differ diff --git a/xui/dwarf/window_upper_left.png b/xui/dwarf/window_upper_left.png new file mode 100755 index 0000000..ef1e867 Binary files /dev/null and b/xui/dwarf/window_upper_left.png differ diff --git a/xui/dwarf/window_upper_right.png b/xui/dwarf/window_upper_right.png new file mode 100755 index 0000000..81a118d Binary files /dev/null and b/xui/dwarf/window_upper_right.png differ diff --git a/xui/fairy/button_left.png b/xui/fairy/button_left.png new file mode 100755 index 0000000..c4d0d77 Binary files /dev/null and b/xui/fairy/button_left.png differ diff --git a/xui/fairy/button_lower.png b/xui/fairy/button_lower.png new file mode 100755 index 0000000..f6588bd Binary files /dev/null and b/xui/fairy/button_lower.png differ diff --git a/xui/fairy/button_lower_left.png b/xui/fairy/button_lower_left.png new file mode 100755 index 0000000..9cf9145 Binary files /dev/null and b/xui/fairy/button_lower_left.png differ diff --git a/xui/fairy/button_lower_right.png b/xui/fairy/button_lower_right.png new file mode 100755 index 0000000..f476acb Binary files /dev/null and b/xui/fairy/button_lower_right.png differ diff --git a/xui/fairy/button_middle.png b/xui/fairy/button_middle.png new file mode 100755 index 0000000..4106227 Binary files /dev/null and b/xui/fairy/button_middle.png differ diff --git a/xui/fairy/button_right.png b/xui/fairy/button_right.png new file mode 100755 index 0000000..1a024f4 Binary files /dev/null and b/xui/fairy/button_right.png differ diff --git a/xui/fairy/button_upper.png b/xui/fairy/button_upper.png new file mode 100755 index 0000000..5ce1f04 Binary files /dev/null and b/xui/fairy/button_upper.png differ diff --git a/xui/fairy/button_upper_left.png b/xui/fairy/button_upper_left.png new file mode 100755 index 0000000..0f84a4e Binary files /dev/null and b/xui/fairy/button_upper_left.png differ diff --git a/xui/fairy/button_upper_right.png b/xui/fairy/button_upper_right.png new file mode 100755 index 0000000..5f38191 Binary files /dev/null and b/xui/fairy/button_upper_right.png differ diff --git a/xui/fairy/check_box_off.png b/xui/fairy/check_box_off.png new file mode 100755 index 0000000..5e203c6 Binary files /dev/null and b/xui/fairy/check_box_off.png differ diff --git a/xui/fairy/check_box_on.png b/xui/fairy/check_box_on.png new file mode 100755 index 0000000..85e68e3 Binary files /dev/null and b/xui/fairy/check_box_on.png differ diff --git a/xui/fairy/cursor.png b/xui/fairy/cursor.png new file mode 100755 index 0000000..56748b5 Binary files /dev/null and b/xui/fairy/cursor.png differ diff --git a/xui/fairy/end_turn_button.png b/xui/fairy/end_turn_button.png new file mode 100755 index 0000000..4e25d42 Binary files /dev/null and b/xui/fairy/end_turn_button.png differ diff --git a/xui/fairy/fill_bar_base.png b/xui/fairy/fill_bar_base.png new file mode 100755 index 0000000..cf08f70 Binary files /dev/null and b/xui/fairy/fill_bar_base.png differ diff --git a/xui/fairy/fill_bar_left.png b/xui/fairy/fill_bar_left.png new file mode 100755 index 0000000..09c10c6 Binary files /dev/null and b/xui/fairy/fill_bar_left.png differ diff --git a/xui/fairy/fill_bar_middle.png b/xui/fairy/fill_bar_middle.png new file mode 100755 index 0000000..d7b6b15 Binary files /dev/null and b/xui/fairy/fill_bar_middle.png differ diff --git a/xui/fairy/fill_bar_right.png b/xui/fairy/fill_bar_right.png new file mode 100755 index 0000000..8b0279b Binary files /dev/null and b/xui/fairy/fill_bar_right.png differ diff --git a/xui/fairy/frame_left.png b/xui/fairy/frame_left.png new file mode 100755 index 0000000..315183b Binary files /dev/null and b/xui/fairy/frame_left.png differ diff --git a/xui/fairy/frame_lower.png b/xui/fairy/frame_lower.png new file mode 100755 index 0000000..c7836fb Binary files /dev/null and b/xui/fairy/frame_lower.png differ diff --git a/xui/fairy/frame_lower_left.png b/xui/fairy/frame_lower_left.png new file mode 100755 index 0000000..f3c43c9 Binary files /dev/null and b/xui/fairy/frame_lower_left.png differ diff --git a/xui/fairy/frame_lower_right.png b/xui/fairy/frame_lower_right.png new file mode 100755 index 0000000..39ab611 Binary files /dev/null and b/xui/fairy/frame_lower_right.png differ diff --git a/xui/fairy/frame_right.png b/xui/fairy/frame_right.png new file mode 100755 index 0000000..84cc10c Binary files /dev/null and b/xui/fairy/frame_right.png differ diff --git a/xui/fairy/frame_upper.png b/xui/fairy/frame_upper.png new file mode 100755 index 0000000..9cde493 Binary files /dev/null and b/xui/fairy/frame_upper.png differ diff --git a/xui/fairy/frame_upper_left.png b/xui/fairy/frame_upper_left.png new file mode 100755 index 0000000..a060d82 Binary files /dev/null and b/xui/fairy/frame_upper_left.png differ diff --git a/xui/fairy/frame_upper_right.png b/xui/fairy/frame_upper_right.png new file mode 100755 index 0000000..e0e41ad Binary files /dev/null and b/xui/fairy/frame_upper_right.png differ diff --git a/xui/fairy/icon_frame.png b/xui/fairy/icon_frame.png new file mode 100755 index 0000000..9fa4604 Binary files /dev/null and b/xui/fairy/icon_frame.png differ diff --git a/xui/fairy/menu_left.png b/xui/fairy/menu_left.png new file mode 100755 index 0000000..98adffe Binary files /dev/null and b/xui/fairy/menu_left.png differ diff --git a/xui/fairy/menu_lower.png b/xui/fairy/menu_lower.png new file mode 100755 index 0000000..0a93d4b Binary files /dev/null and b/xui/fairy/menu_lower.png differ diff --git a/xui/fairy/menu_lower_left.png b/xui/fairy/menu_lower_left.png new file mode 100755 index 0000000..848c900 Binary files /dev/null and b/xui/fairy/menu_lower_left.png differ diff --git a/xui/fairy/menu_lower_right.png b/xui/fairy/menu_lower_right.png new file mode 100755 index 0000000..4090caf Binary files /dev/null and b/xui/fairy/menu_lower_right.png differ diff --git a/xui/fairy/menu_middle.png b/xui/fairy/menu_middle.png new file mode 100755 index 0000000..0019c6e Binary files /dev/null and b/xui/fairy/menu_middle.png differ diff --git a/xui/fairy/menu_right.png b/xui/fairy/menu_right.png new file mode 100755 index 0000000..d7f2edb Binary files /dev/null and b/xui/fairy/menu_right.png differ diff --git a/xui/fairy/menu_upper.png b/xui/fairy/menu_upper.png new file mode 100755 index 0000000..3cf8921 Binary files /dev/null and b/xui/fairy/menu_upper.png differ diff --git a/xui/fairy/menu_upper_left.png b/xui/fairy/menu_upper_left.png new file mode 100755 index 0000000..ba4c0a7 Binary files /dev/null and b/xui/fairy/menu_upper_left.png differ diff --git a/xui/fairy/menu_upper_right.png b/xui/fairy/menu_upper_right.png new file mode 100755 index 0000000..a7f9ce2 Binary files /dev/null and b/xui/fairy/menu_upper_right.png differ diff --git a/xui/fairy/overicon_frame.png b/xui/fairy/overicon_frame.png new file mode 100755 index 0000000..23cf7c5 Binary files /dev/null and b/xui/fairy/overicon_frame.png differ diff --git a/xui/fairy/scroll_bar_lower.png b/xui/fairy/scroll_bar_lower.png new file mode 100755 index 0000000..f4c77c1 Binary files /dev/null and b/xui/fairy/scroll_bar_lower.png differ diff --git a/xui/fairy/scroll_bar_middle.png b/xui/fairy/scroll_bar_middle.png new file mode 100755 index 0000000..d627d82 Binary files /dev/null and b/xui/fairy/scroll_bar_middle.png differ diff --git a/xui/fairy/scroll_bar_slider.png b/xui/fairy/scroll_bar_slider.png new file mode 100644 index 0000000..1ae3016 Binary files /dev/null and b/xui/fairy/scroll_bar_slider.png differ diff --git a/xui/fairy/scroll_bar_upper.png b/xui/fairy/scroll_bar_upper.png new file mode 100755 index 0000000..fd83ff9 Binary files /dev/null and b/xui/fairy/scroll_bar_upper.png differ diff --git a/xui/fairy/separator_center.png b/xui/fairy/separator_center.png new file mode 100644 index 0000000..1ae3016 Binary files /dev/null and b/xui/fairy/separator_center.png differ diff --git a/xui/fairy/separator_left.png b/xui/fairy/separator_left.png new file mode 100755 index 0000000..511455c Binary files /dev/null and b/xui/fairy/separator_left.png differ diff --git a/xui/fairy/separator_middle.png b/xui/fairy/separator_middle.png new file mode 100755 index 0000000..4435ade Binary files /dev/null and b/xui/fairy/separator_middle.png differ diff --git a/xui/fairy/separator_right.png b/xui/fairy/separator_right.png new file mode 100755 index 0000000..1f97a93 Binary files /dev/null and b/xui/fairy/separator_right.png differ diff --git a/xui/fairy/status_left.png b/xui/fairy/status_left.png new file mode 100755 index 0000000..6bbb1df Binary files /dev/null and b/xui/fairy/status_left.png differ diff --git a/xui/fairy/status_lower.png b/xui/fairy/status_lower.png new file mode 100755 index 0000000..ac0f64a Binary files /dev/null and b/xui/fairy/status_lower.png differ diff --git a/xui/fairy/status_lower_left.png b/xui/fairy/status_lower_left.png new file mode 100755 index 0000000..5fad49d Binary files /dev/null and b/xui/fairy/status_lower_left.png differ diff --git a/xui/fairy/status_lower_right.png b/xui/fairy/status_lower_right.png new file mode 100755 index 0000000..803609e Binary files /dev/null and b/xui/fairy/status_lower_right.png differ diff --git a/xui/fairy/status_middle.png b/xui/fairy/status_middle.png new file mode 100755 index 0000000..efaddd0 Binary files /dev/null and b/xui/fairy/status_middle.png differ diff --git a/xui/fairy/status_right.png b/xui/fairy/status_right.png new file mode 100755 index 0000000..6bbb1df Binary files /dev/null and b/xui/fairy/status_right.png differ diff --git a/xui/fairy/status_upper.png b/xui/fairy/status_upper.png new file mode 100755 index 0000000..ac0f64a Binary files /dev/null and b/xui/fairy/status_upper.png differ diff --git a/xui/fairy/status_upper_left.png b/xui/fairy/status_upper_left.png new file mode 100755 index 0000000..bc7528d Binary files /dev/null and b/xui/fairy/status_upper_left.png differ diff --git a/xui/fairy/status_upper_right.png b/xui/fairy/status_upper_right.png new file mode 100755 index 0000000..24c00a3 Binary files /dev/null and b/xui/fairy/status_upper_right.png differ diff --git a/xui/fairy/tiny_fill_bar_base.png b/xui/fairy/tiny_fill_bar_base.png new file mode 100755 index 0000000..763dc24 Binary files /dev/null and b/xui/fairy/tiny_fill_bar_base.png differ diff --git a/xui/fairy/tiny_fill_bar_left.png b/xui/fairy/tiny_fill_bar_left.png new file mode 100755 index 0000000..1c94cf9 Binary files /dev/null and b/xui/fairy/tiny_fill_bar_left.png differ diff --git a/xui/fairy/tiny_fill_bar_middle.png b/xui/fairy/tiny_fill_bar_middle.png new file mode 100755 index 0000000..b72cabd Binary files /dev/null and b/xui/fairy/tiny_fill_bar_middle.png differ diff --git a/xui/fairy/tiny_fill_bar_right.png b/xui/fairy/tiny_fill_bar_right.png new file mode 100755 index 0000000..55bbe08 Binary files /dev/null and b/xui/fairy/tiny_fill_bar_right.png differ diff --git a/xui/fairy/title_bar_left.png b/xui/fairy/title_bar_left.png new file mode 100755 index 0000000..daa5ec8 Binary files /dev/null and b/xui/fairy/title_bar_left.png differ diff --git a/xui/fairy/title_bar_middle.png b/xui/fairy/title_bar_middle.png new file mode 100755 index 0000000..be3768c Binary files /dev/null and b/xui/fairy/title_bar_middle.png differ diff --git a/xui/fairy/title_bar_right.png b/xui/fairy/title_bar_right.png new file mode 100755 index 0000000..f2fc8b1 Binary files /dev/null and b/xui/fairy/title_bar_right.png differ diff --git a/xui/fairy/ubericon_frame.png b/xui/fairy/ubericon_frame.png new file mode 100755 index 0000000..9ea054b Binary files /dev/null and b/xui/fairy/ubericon_frame.png differ diff --git a/xui/fairy/window_left.png b/xui/fairy/window_left.png new file mode 100755 index 0000000..490e1f1 Binary files /dev/null and b/xui/fairy/window_left.png differ diff --git a/xui/fairy/window_lower.png b/xui/fairy/window_lower.png new file mode 100755 index 0000000..271096a Binary files /dev/null and b/xui/fairy/window_lower.png differ diff --git a/xui/fairy/window_lower_left.png b/xui/fairy/window_lower_left.png new file mode 100755 index 0000000..599be64 Binary files /dev/null and b/xui/fairy/window_lower_left.png differ diff --git a/xui/fairy/window_lower_right.png b/xui/fairy/window_lower_right.png new file mode 100755 index 0000000..869bbb7 Binary files /dev/null and b/xui/fairy/window_lower_right.png differ diff --git a/xui/fairy/window_right.png b/xui/fairy/window_right.png new file mode 100755 index 0000000..bf8d98c Binary files /dev/null and b/xui/fairy/window_right.png differ diff --git a/xui/fairy/window_upper.png b/xui/fairy/window_upper.png new file mode 100755 index 0000000..271096a Binary files /dev/null and b/xui/fairy/window_upper.png differ diff --git a/xui/fairy/window_upper_left.png b/xui/fairy/window_upper_left.png new file mode 100755 index 0000000..b0d76b2 Binary files /dev/null and b/xui/fairy/window_upper_left.png differ diff --git a/xui/fairy/window_upper_right.png b/xui/fairy/window_upper_right.png new file mode 100755 index 0000000..e6761a4 Binary files /dev/null and b/xui/fairy/window_upper_right.png differ diff --git a/xui/fullscreen_off.png b/xui/fullscreen_off.png new file mode 100755 index 0000000..eb8c813 Binary files /dev/null and b/xui/fullscreen_off.png differ diff --git a/xui/fullscreen_on.png b/xui/fullscreen_on.png new file mode 100755 index 0000000..5d1c0b3 Binary files /dev/null and b/xui/fullscreen_on.png differ diff --git a/xui/gnoll/button_left.png b/xui/gnoll/button_left.png new file mode 100755 index 0000000..9b460c6 Binary files /dev/null and b/xui/gnoll/button_left.png differ diff --git a/xui/gnoll/button_lower.png b/xui/gnoll/button_lower.png new file mode 100755 index 0000000..ac26ead Binary files /dev/null and b/xui/gnoll/button_lower.png differ diff --git a/xui/gnoll/button_lower_left.png b/xui/gnoll/button_lower_left.png new file mode 100755 index 0000000..e4e42f1 Binary files /dev/null and b/xui/gnoll/button_lower_left.png differ diff --git a/xui/gnoll/button_lower_right.png b/xui/gnoll/button_lower_right.png new file mode 100755 index 0000000..67b0986 Binary files /dev/null and b/xui/gnoll/button_lower_right.png differ diff --git a/xui/gnoll/button_middle.png b/xui/gnoll/button_middle.png new file mode 100755 index 0000000..58f49ed Binary files /dev/null and b/xui/gnoll/button_middle.png differ diff --git a/xui/gnoll/button_right.png b/xui/gnoll/button_right.png new file mode 100755 index 0000000..44aafbc Binary files /dev/null and b/xui/gnoll/button_right.png differ diff --git a/xui/gnoll/button_upper.png b/xui/gnoll/button_upper.png new file mode 100755 index 0000000..7a76ea4 Binary files /dev/null and b/xui/gnoll/button_upper.png differ diff --git a/xui/gnoll/button_upper_left.png b/xui/gnoll/button_upper_left.png new file mode 100755 index 0000000..82f4707 Binary files /dev/null and b/xui/gnoll/button_upper_left.png differ diff --git a/xui/gnoll/button_upper_right.png b/xui/gnoll/button_upper_right.png new file mode 100755 index 0000000..dffff05 Binary files /dev/null and b/xui/gnoll/button_upper_right.png differ diff --git a/xui/gnoll/check_box_off.png b/xui/gnoll/check_box_off.png new file mode 100755 index 0000000..db36276 Binary files /dev/null and b/xui/gnoll/check_box_off.png differ diff --git a/xui/gnoll/check_box_on.png b/xui/gnoll/check_box_on.png new file mode 100755 index 0000000..356dd53 Binary files /dev/null and b/xui/gnoll/check_box_on.png differ diff --git a/xui/gnoll/cursor.png b/xui/gnoll/cursor.png new file mode 100755 index 0000000..954f141 Binary files /dev/null and b/xui/gnoll/cursor.png differ diff --git a/xui/gnoll/end_turn_button.png b/xui/gnoll/end_turn_button.png new file mode 100755 index 0000000..34efbcc Binary files /dev/null and b/xui/gnoll/end_turn_button.png differ diff --git a/xui/gnoll/fill_bar_base.png b/xui/gnoll/fill_bar_base.png new file mode 100755 index 0000000..5456dc3 Binary files /dev/null and b/xui/gnoll/fill_bar_base.png differ diff --git a/xui/gnoll/fill_bar_left.png b/xui/gnoll/fill_bar_left.png new file mode 100755 index 0000000..ba693f6 Binary files /dev/null and b/xui/gnoll/fill_bar_left.png differ diff --git a/xui/gnoll/fill_bar_middle.png b/xui/gnoll/fill_bar_middle.png new file mode 100755 index 0000000..d7cbdf5 Binary files /dev/null and b/xui/gnoll/fill_bar_middle.png differ diff --git a/xui/gnoll/fill_bar_right.png b/xui/gnoll/fill_bar_right.png new file mode 100755 index 0000000..d5ea533 Binary files /dev/null and b/xui/gnoll/fill_bar_right.png differ diff --git a/xui/gnoll/frame_left.png b/xui/gnoll/frame_left.png new file mode 100755 index 0000000..007b90c Binary files /dev/null and b/xui/gnoll/frame_left.png differ diff --git a/xui/gnoll/frame_lower.png b/xui/gnoll/frame_lower.png new file mode 100755 index 0000000..41c176e Binary files /dev/null and b/xui/gnoll/frame_lower.png differ diff --git a/xui/gnoll/frame_lower_left.png b/xui/gnoll/frame_lower_left.png new file mode 100755 index 0000000..35e703c Binary files /dev/null and b/xui/gnoll/frame_lower_left.png differ diff --git a/xui/gnoll/frame_lower_right.png b/xui/gnoll/frame_lower_right.png new file mode 100755 index 0000000..ea819a5 Binary files /dev/null and b/xui/gnoll/frame_lower_right.png differ diff --git a/xui/gnoll/frame_right.png b/xui/gnoll/frame_right.png new file mode 100755 index 0000000..6ed8446 Binary files /dev/null and b/xui/gnoll/frame_right.png differ diff --git a/xui/gnoll/frame_upper.png b/xui/gnoll/frame_upper.png new file mode 100755 index 0000000..a885c77 Binary files /dev/null and b/xui/gnoll/frame_upper.png differ diff --git a/xui/gnoll/frame_upper_left.png b/xui/gnoll/frame_upper_left.png new file mode 100755 index 0000000..aee9a04 Binary files /dev/null and b/xui/gnoll/frame_upper_left.png differ diff --git a/xui/gnoll/frame_upper_right.png b/xui/gnoll/frame_upper_right.png new file mode 100755 index 0000000..2bdcf7c Binary files /dev/null and b/xui/gnoll/frame_upper_right.png differ diff --git a/xui/gnoll/icon_frame.png b/xui/gnoll/icon_frame.png new file mode 100755 index 0000000..75b387f Binary files /dev/null and b/xui/gnoll/icon_frame.png differ diff --git a/xui/gnoll/menu_left.png b/xui/gnoll/menu_left.png new file mode 100755 index 0000000..a49003c Binary files /dev/null and b/xui/gnoll/menu_left.png differ diff --git a/xui/gnoll/menu_lower.png b/xui/gnoll/menu_lower.png new file mode 100755 index 0000000..95cd0df Binary files /dev/null and b/xui/gnoll/menu_lower.png differ diff --git a/xui/gnoll/menu_lower_left.png b/xui/gnoll/menu_lower_left.png new file mode 100755 index 0000000..bf7e4fc Binary files /dev/null and b/xui/gnoll/menu_lower_left.png differ diff --git a/xui/gnoll/menu_lower_right.png b/xui/gnoll/menu_lower_right.png new file mode 100755 index 0000000..7aa4bb9 Binary files /dev/null and b/xui/gnoll/menu_lower_right.png differ diff --git a/xui/gnoll/menu_middle.png b/xui/gnoll/menu_middle.png new file mode 100755 index 0000000..a9eddc0 Binary files /dev/null and b/xui/gnoll/menu_middle.png differ diff --git a/xui/gnoll/menu_right.png b/xui/gnoll/menu_right.png new file mode 100755 index 0000000..88de24a Binary files /dev/null and b/xui/gnoll/menu_right.png differ diff --git a/xui/gnoll/menu_upper.png b/xui/gnoll/menu_upper.png new file mode 100755 index 0000000..6b2d146 Binary files /dev/null and b/xui/gnoll/menu_upper.png differ diff --git a/xui/gnoll/menu_upper_left.png b/xui/gnoll/menu_upper_left.png new file mode 100755 index 0000000..0afa4f7 Binary files /dev/null and b/xui/gnoll/menu_upper_left.png differ diff --git a/xui/gnoll/menu_upper_right.png b/xui/gnoll/menu_upper_right.png new file mode 100755 index 0000000..9019c35 Binary files /dev/null and b/xui/gnoll/menu_upper_right.png differ diff --git a/xui/gnoll/overicon_frame.png b/xui/gnoll/overicon_frame.png new file mode 100755 index 0000000..e11efa5 Binary files /dev/null and b/xui/gnoll/overicon_frame.png differ diff --git a/xui/gnoll/scroll_bar_lower.png b/xui/gnoll/scroll_bar_lower.png new file mode 100755 index 0000000..9a2c0ac Binary files /dev/null and b/xui/gnoll/scroll_bar_lower.png differ diff --git a/xui/gnoll/scroll_bar_middle.png b/xui/gnoll/scroll_bar_middle.png new file mode 100755 index 0000000..453539e Binary files /dev/null and b/xui/gnoll/scroll_bar_middle.png differ diff --git a/xui/gnoll/scroll_bar_slider.png b/xui/gnoll/scroll_bar_slider.png new file mode 100755 index 0000000..356dd53 Binary files /dev/null and b/xui/gnoll/scroll_bar_slider.png differ diff --git a/xui/gnoll/scroll_bar_upper.png b/xui/gnoll/scroll_bar_upper.png new file mode 100755 index 0000000..1412b7d Binary files /dev/null and b/xui/gnoll/scroll_bar_upper.png differ diff --git a/xui/gnoll/separator_center.png b/xui/gnoll/separator_center.png new file mode 100755 index 0000000..356dd53 Binary files /dev/null and b/xui/gnoll/separator_center.png differ diff --git a/xui/gnoll/separator_left.png b/xui/gnoll/separator_left.png new file mode 100755 index 0000000..6fdd0eb Binary files /dev/null and b/xui/gnoll/separator_left.png differ diff --git a/xui/gnoll/separator_middle.png b/xui/gnoll/separator_middle.png new file mode 100755 index 0000000..5b4a7b4 Binary files /dev/null and b/xui/gnoll/separator_middle.png differ diff --git a/xui/gnoll/separator_right.png b/xui/gnoll/separator_right.png new file mode 100755 index 0000000..e58569d Binary files /dev/null and b/xui/gnoll/separator_right.png differ diff --git a/xui/gnoll/status_left.png b/xui/gnoll/status_left.png new file mode 100755 index 0000000..6eff431 Binary files /dev/null and b/xui/gnoll/status_left.png differ diff --git a/xui/gnoll/status_lower.png b/xui/gnoll/status_lower.png new file mode 100755 index 0000000..c0c69c9 Binary files /dev/null and b/xui/gnoll/status_lower.png differ diff --git a/xui/gnoll/status_lower_left.png b/xui/gnoll/status_lower_left.png new file mode 100755 index 0000000..8a73b35 Binary files /dev/null and b/xui/gnoll/status_lower_left.png differ diff --git a/xui/gnoll/status_lower_right.png b/xui/gnoll/status_lower_right.png new file mode 100755 index 0000000..e655ef5 Binary files /dev/null and b/xui/gnoll/status_lower_right.png differ diff --git a/xui/gnoll/status_middle.png b/xui/gnoll/status_middle.png new file mode 100755 index 0000000..45b2919 Binary files /dev/null and b/xui/gnoll/status_middle.png differ diff --git a/xui/gnoll/status_right.png b/xui/gnoll/status_right.png new file mode 100755 index 0000000..b4b4343 Binary files /dev/null and b/xui/gnoll/status_right.png differ diff --git a/xui/gnoll/status_upper.png b/xui/gnoll/status_upper.png new file mode 100755 index 0000000..acab93f Binary files /dev/null and b/xui/gnoll/status_upper.png differ diff --git a/xui/gnoll/status_upper_left.png b/xui/gnoll/status_upper_left.png new file mode 100755 index 0000000..bd0e017 Binary files /dev/null and b/xui/gnoll/status_upper_left.png differ diff --git a/xui/gnoll/status_upper_right.png b/xui/gnoll/status_upper_right.png new file mode 100755 index 0000000..ecc87d6 Binary files /dev/null and b/xui/gnoll/status_upper_right.png differ diff --git a/xui/gnoll/tiny_fill_bar_base.png b/xui/gnoll/tiny_fill_bar_base.png new file mode 100755 index 0000000..4d72d7a Binary files /dev/null and b/xui/gnoll/tiny_fill_bar_base.png differ diff --git a/xui/gnoll/tiny_fill_bar_left.png b/xui/gnoll/tiny_fill_bar_left.png new file mode 100755 index 0000000..254499a Binary files /dev/null and b/xui/gnoll/tiny_fill_bar_left.png differ diff --git a/xui/gnoll/tiny_fill_bar_middle.png b/xui/gnoll/tiny_fill_bar_middle.png new file mode 100755 index 0000000..ee6a587 Binary files /dev/null and b/xui/gnoll/tiny_fill_bar_middle.png differ diff --git a/xui/gnoll/tiny_fill_bar_right.png b/xui/gnoll/tiny_fill_bar_right.png new file mode 100755 index 0000000..64634e4 Binary files /dev/null and b/xui/gnoll/tiny_fill_bar_right.png differ diff --git a/xui/gnoll/title_bar_left.png b/xui/gnoll/title_bar_left.png new file mode 100755 index 0000000..a1f300e Binary files /dev/null and b/xui/gnoll/title_bar_left.png differ diff --git a/xui/gnoll/title_bar_middle.png b/xui/gnoll/title_bar_middle.png new file mode 100755 index 0000000..b4c3780 Binary files /dev/null and b/xui/gnoll/title_bar_middle.png differ diff --git a/xui/gnoll/title_bar_right.png b/xui/gnoll/title_bar_right.png new file mode 100755 index 0000000..2b2cec2 Binary files /dev/null and b/xui/gnoll/title_bar_right.png differ diff --git a/xui/gnoll/ubericon_frame.png b/xui/gnoll/ubericon_frame.png new file mode 100755 index 0000000..342a87a Binary files /dev/null and b/xui/gnoll/ubericon_frame.png differ diff --git a/xui/gnoll/window_left.png b/xui/gnoll/window_left.png new file mode 100755 index 0000000..54e60b4 Binary files /dev/null and b/xui/gnoll/window_left.png differ diff --git a/xui/gnoll/window_lower.png b/xui/gnoll/window_lower.png new file mode 100755 index 0000000..8f62ea9 Binary files /dev/null and b/xui/gnoll/window_lower.png differ diff --git a/xui/gnoll/window_lower_left.png b/xui/gnoll/window_lower_left.png new file mode 100755 index 0000000..1b68f63 Binary files /dev/null and b/xui/gnoll/window_lower_left.png differ diff --git a/xui/gnoll/window_lower_right.png b/xui/gnoll/window_lower_right.png new file mode 100755 index 0000000..14e3543 Binary files /dev/null and b/xui/gnoll/window_lower_right.png differ diff --git a/xui/gnoll/window_right.png b/xui/gnoll/window_right.png new file mode 100755 index 0000000..587bc2a Binary files /dev/null and b/xui/gnoll/window_right.png differ diff --git a/xui/gnoll/window_upper.png b/xui/gnoll/window_upper.png new file mode 100755 index 0000000..8f62ea9 Binary files /dev/null and b/xui/gnoll/window_upper.png differ diff --git a/xui/gnoll/window_upper_left.png b/xui/gnoll/window_upper_left.png new file mode 100755 index 0000000..3e5dc89 Binary files /dev/null and b/xui/gnoll/window_upper_left.png differ diff --git a/xui/gnoll/window_upper_right.png b/xui/gnoll/window_upper_right.png new file mode 100755 index 0000000..1a24a0a Binary files /dev/null and b/xui/gnoll/window_upper_right.png differ diff --git a/xui/goblin/button_left.png b/xui/goblin/button_left.png new file mode 100755 index 0000000..81988fa Binary files /dev/null and b/xui/goblin/button_left.png differ diff --git a/xui/goblin/button_lower.png b/xui/goblin/button_lower.png new file mode 100755 index 0000000..c2f6871 Binary files /dev/null and b/xui/goblin/button_lower.png differ diff --git a/xui/goblin/button_lower_left.png b/xui/goblin/button_lower_left.png new file mode 100755 index 0000000..4159ff6 Binary files /dev/null and b/xui/goblin/button_lower_left.png differ diff --git a/xui/goblin/button_lower_right.png b/xui/goblin/button_lower_right.png new file mode 100755 index 0000000..5347b56 Binary files /dev/null and b/xui/goblin/button_lower_right.png differ diff --git a/xui/goblin/button_middle.png b/xui/goblin/button_middle.png new file mode 100755 index 0000000..6e245dc Binary files /dev/null and b/xui/goblin/button_middle.png differ diff --git a/xui/goblin/button_right.png b/xui/goblin/button_right.png new file mode 100755 index 0000000..37b71cd Binary files /dev/null and b/xui/goblin/button_right.png differ diff --git a/xui/goblin/button_upper.png b/xui/goblin/button_upper.png new file mode 100755 index 0000000..eeb3ad4 Binary files /dev/null and b/xui/goblin/button_upper.png differ diff --git a/xui/goblin/button_upper_left.png b/xui/goblin/button_upper_left.png new file mode 100755 index 0000000..be65e61 Binary files /dev/null and b/xui/goblin/button_upper_left.png differ diff --git a/xui/goblin/button_upper_right.png b/xui/goblin/button_upper_right.png new file mode 100755 index 0000000..c75c6b1 Binary files /dev/null and b/xui/goblin/button_upper_right.png differ diff --git a/xui/goblin/check_box_off.png b/xui/goblin/check_box_off.png new file mode 100755 index 0000000..1ced841 Binary files /dev/null and b/xui/goblin/check_box_off.png differ diff --git a/xui/goblin/check_box_on.png b/xui/goblin/check_box_on.png new file mode 100755 index 0000000..b6c208a Binary files /dev/null and b/xui/goblin/check_box_on.png differ diff --git a/xui/goblin/cursor.png b/xui/goblin/cursor.png new file mode 100755 index 0000000..2efa14f Binary files /dev/null and b/xui/goblin/cursor.png differ diff --git a/xui/goblin/end_turn_button.png b/xui/goblin/end_turn_button.png new file mode 100755 index 0000000..3cae1ee Binary files /dev/null and b/xui/goblin/end_turn_button.png differ diff --git a/xui/goblin/fill_bar_base.png b/xui/goblin/fill_bar_base.png new file mode 100755 index 0000000..31afc91 Binary files /dev/null and b/xui/goblin/fill_bar_base.png differ diff --git a/xui/goblin/fill_bar_left.png b/xui/goblin/fill_bar_left.png new file mode 100755 index 0000000..c230edb Binary files /dev/null and b/xui/goblin/fill_bar_left.png differ diff --git a/xui/goblin/fill_bar_middle.png b/xui/goblin/fill_bar_middle.png new file mode 100755 index 0000000..4bb058c Binary files /dev/null and b/xui/goblin/fill_bar_middle.png differ diff --git a/xui/goblin/fill_bar_right.png b/xui/goblin/fill_bar_right.png new file mode 100755 index 0000000..539e940 Binary files /dev/null and b/xui/goblin/fill_bar_right.png differ diff --git a/xui/goblin/frame_left.png b/xui/goblin/frame_left.png new file mode 100755 index 0000000..7f7e35d Binary files /dev/null and b/xui/goblin/frame_left.png differ diff --git a/xui/goblin/frame_lower.png b/xui/goblin/frame_lower.png new file mode 100755 index 0000000..ed84866 Binary files /dev/null and b/xui/goblin/frame_lower.png differ diff --git a/xui/goblin/frame_lower_left.png b/xui/goblin/frame_lower_left.png new file mode 100755 index 0000000..41154a0 Binary files /dev/null and b/xui/goblin/frame_lower_left.png differ diff --git a/xui/goblin/frame_lower_right.png b/xui/goblin/frame_lower_right.png new file mode 100755 index 0000000..d6366c7 Binary files /dev/null and b/xui/goblin/frame_lower_right.png differ diff --git a/xui/goblin/frame_right.png b/xui/goblin/frame_right.png new file mode 100755 index 0000000..41d3913 Binary files /dev/null and b/xui/goblin/frame_right.png differ diff --git a/xui/goblin/frame_upper.png b/xui/goblin/frame_upper.png new file mode 100755 index 0000000..180bf96 Binary files /dev/null and b/xui/goblin/frame_upper.png differ diff --git a/xui/goblin/frame_upper_left.png b/xui/goblin/frame_upper_left.png new file mode 100755 index 0000000..07e780d Binary files /dev/null and b/xui/goblin/frame_upper_left.png differ diff --git a/xui/goblin/frame_upper_right.png b/xui/goblin/frame_upper_right.png new file mode 100755 index 0000000..ed88553 Binary files /dev/null and b/xui/goblin/frame_upper_right.png differ diff --git a/xui/goblin/icon_frame.png b/xui/goblin/icon_frame.png new file mode 100755 index 0000000..cce0dcd Binary files /dev/null and b/xui/goblin/icon_frame.png differ diff --git a/xui/goblin/menu_left.png b/xui/goblin/menu_left.png new file mode 100755 index 0000000..c976421 Binary files /dev/null and b/xui/goblin/menu_left.png differ diff --git a/xui/goblin/menu_lower.png b/xui/goblin/menu_lower.png new file mode 100755 index 0000000..6bbb18f Binary files /dev/null and b/xui/goblin/menu_lower.png differ diff --git a/xui/goblin/menu_lower_left.png b/xui/goblin/menu_lower_left.png new file mode 100755 index 0000000..97965e4 Binary files /dev/null and b/xui/goblin/menu_lower_left.png differ diff --git a/xui/goblin/menu_lower_right.png b/xui/goblin/menu_lower_right.png new file mode 100755 index 0000000..70cdc5e Binary files /dev/null and b/xui/goblin/menu_lower_right.png differ diff --git a/xui/goblin/menu_middle.png b/xui/goblin/menu_middle.png new file mode 100755 index 0000000..6e245dc Binary files /dev/null and b/xui/goblin/menu_middle.png differ diff --git a/xui/goblin/menu_right.png b/xui/goblin/menu_right.png new file mode 100755 index 0000000..96f24b4 Binary files /dev/null and b/xui/goblin/menu_right.png differ diff --git a/xui/goblin/menu_upper.png b/xui/goblin/menu_upper.png new file mode 100755 index 0000000..075d136 Binary files /dev/null and b/xui/goblin/menu_upper.png differ diff --git a/xui/goblin/menu_upper_left.png b/xui/goblin/menu_upper_left.png new file mode 100755 index 0000000..2244e57 Binary files /dev/null and b/xui/goblin/menu_upper_left.png differ diff --git a/xui/goblin/menu_upper_right.png b/xui/goblin/menu_upper_right.png new file mode 100755 index 0000000..17a673d Binary files /dev/null and b/xui/goblin/menu_upper_right.png differ diff --git a/xui/goblin/overicon_frame.png b/xui/goblin/overicon_frame.png new file mode 100755 index 0000000..f090678 Binary files /dev/null and b/xui/goblin/overicon_frame.png differ diff --git a/xui/goblin/scroll_bar_lower.png b/xui/goblin/scroll_bar_lower.png new file mode 100755 index 0000000..0ea255d Binary files /dev/null and b/xui/goblin/scroll_bar_lower.png differ diff --git a/xui/goblin/scroll_bar_middle.png b/xui/goblin/scroll_bar_middle.png new file mode 100755 index 0000000..c13f056 Binary files /dev/null and b/xui/goblin/scroll_bar_middle.png differ diff --git a/xui/goblin/scroll_bar_slider.png b/xui/goblin/scroll_bar_slider.png new file mode 100755 index 0000000..b6c208a Binary files /dev/null and b/xui/goblin/scroll_bar_slider.png differ diff --git a/xui/goblin/scroll_bar_upper.png b/xui/goblin/scroll_bar_upper.png new file mode 100755 index 0000000..5b90ade Binary files /dev/null and b/xui/goblin/scroll_bar_upper.png differ diff --git a/xui/goblin/separator_center.png b/xui/goblin/separator_center.png new file mode 100755 index 0000000..b6c208a Binary files /dev/null and b/xui/goblin/separator_center.png differ diff --git a/xui/goblin/separator_left.png b/xui/goblin/separator_left.png new file mode 100755 index 0000000..7c9c6cf Binary files /dev/null and b/xui/goblin/separator_left.png differ diff --git a/xui/goblin/separator_middle.png b/xui/goblin/separator_middle.png new file mode 100755 index 0000000..6403039 Binary files /dev/null and b/xui/goblin/separator_middle.png differ diff --git a/xui/goblin/separator_right.png b/xui/goblin/separator_right.png new file mode 100755 index 0000000..45f639f Binary files /dev/null and b/xui/goblin/separator_right.png differ diff --git a/xui/goblin/status_left.png b/xui/goblin/status_left.png new file mode 100755 index 0000000..8b45355 Binary files /dev/null and b/xui/goblin/status_left.png differ diff --git a/xui/goblin/status_lower.png b/xui/goblin/status_lower.png new file mode 100755 index 0000000..79d5a8e Binary files /dev/null and b/xui/goblin/status_lower.png differ diff --git a/xui/goblin/status_lower_left.png b/xui/goblin/status_lower_left.png new file mode 100755 index 0000000..28778cb Binary files /dev/null and b/xui/goblin/status_lower_left.png differ diff --git a/xui/goblin/status_lower_right.png b/xui/goblin/status_lower_right.png new file mode 100755 index 0000000..63d7da9 Binary files /dev/null and b/xui/goblin/status_lower_right.png differ diff --git a/xui/goblin/status_middle.png b/xui/goblin/status_middle.png new file mode 100755 index 0000000..a412403 Binary files /dev/null and b/xui/goblin/status_middle.png differ diff --git a/xui/goblin/status_right.png b/xui/goblin/status_right.png new file mode 100755 index 0000000..6456926 Binary files /dev/null and b/xui/goblin/status_right.png differ diff --git a/xui/goblin/status_upper.png b/xui/goblin/status_upper.png new file mode 100755 index 0000000..653ca08 Binary files /dev/null and b/xui/goblin/status_upper.png differ diff --git a/xui/goblin/status_upper_left.png b/xui/goblin/status_upper_left.png new file mode 100755 index 0000000..93008da Binary files /dev/null and b/xui/goblin/status_upper_left.png differ diff --git a/xui/goblin/status_upper_right.png b/xui/goblin/status_upper_right.png new file mode 100755 index 0000000..ee50986 Binary files /dev/null and b/xui/goblin/status_upper_right.png differ diff --git a/xui/goblin/tiny_fill_bar_base.png b/xui/goblin/tiny_fill_bar_base.png new file mode 100755 index 0000000..8761bff Binary files /dev/null and b/xui/goblin/tiny_fill_bar_base.png differ diff --git a/xui/goblin/tiny_fill_bar_left.png b/xui/goblin/tiny_fill_bar_left.png new file mode 100755 index 0000000..4266bbb Binary files /dev/null and b/xui/goblin/tiny_fill_bar_left.png differ diff --git a/xui/goblin/tiny_fill_bar_middle.png b/xui/goblin/tiny_fill_bar_middle.png new file mode 100755 index 0000000..c906642 Binary files /dev/null and b/xui/goblin/tiny_fill_bar_middle.png differ diff --git a/xui/goblin/tiny_fill_bar_right.png b/xui/goblin/tiny_fill_bar_right.png new file mode 100755 index 0000000..b21e6bc Binary files /dev/null and b/xui/goblin/tiny_fill_bar_right.png differ diff --git a/xui/goblin/title_bar_left.png b/xui/goblin/title_bar_left.png new file mode 100755 index 0000000..a8eb724 Binary files /dev/null and b/xui/goblin/title_bar_left.png differ diff --git a/xui/goblin/title_bar_middle.png b/xui/goblin/title_bar_middle.png new file mode 100755 index 0000000..31f331e Binary files /dev/null and b/xui/goblin/title_bar_middle.png differ diff --git a/xui/goblin/title_bar_right.png b/xui/goblin/title_bar_right.png new file mode 100755 index 0000000..611c364 Binary files /dev/null and b/xui/goblin/title_bar_right.png differ diff --git a/xui/goblin/ubericon_frame.png b/xui/goblin/ubericon_frame.png new file mode 100755 index 0000000..a1b8b20 Binary files /dev/null and b/xui/goblin/ubericon_frame.png differ diff --git a/xui/goblin/window_left.png b/xui/goblin/window_left.png new file mode 100755 index 0000000..3d8907e Binary files /dev/null and b/xui/goblin/window_left.png differ diff --git a/xui/goblin/window_lower.png b/xui/goblin/window_lower.png new file mode 100755 index 0000000..20bb0c0 Binary files /dev/null and b/xui/goblin/window_lower.png differ diff --git a/xui/goblin/window_lower_left.png b/xui/goblin/window_lower_left.png new file mode 100755 index 0000000..71bfaa3 Binary files /dev/null and b/xui/goblin/window_lower_left.png differ diff --git a/xui/goblin/window_lower_right.png b/xui/goblin/window_lower_right.png new file mode 100755 index 0000000..8c8d536 Binary files /dev/null and b/xui/goblin/window_lower_right.png differ diff --git a/xui/goblin/window_right.png b/xui/goblin/window_right.png new file mode 100755 index 0000000..590f944 Binary files /dev/null and b/xui/goblin/window_right.png differ diff --git a/xui/goblin/window_upper.png b/xui/goblin/window_upper.png new file mode 100755 index 0000000..7033c45 Binary files /dev/null and b/xui/goblin/window_upper.png differ diff --git a/xui/goblin/window_upper_left.png b/xui/goblin/window_upper_left.png new file mode 100755 index 0000000..52275da Binary files /dev/null and b/xui/goblin/window_upper_left.png differ diff --git a/xui/goblin/window_upper_right.png b/xui/goblin/window_upper_right.png new file mode 100755 index 0000000..8ebab21 Binary files /dev/null and b/xui/goblin/window_upper_right.png differ diff --git a/xui/imp/button_left.png b/xui/imp/button_left.png new file mode 100755 index 0000000..6901c55 Binary files /dev/null and b/xui/imp/button_left.png differ diff --git a/xui/imp/button_lower.png b/xui/imp/button_lower.png new file mode 100755 index 0000000..f08242f Binary files /dev/null and b/xui/imp/button_lower.png differ diff --git a/xui/imp/button_lower_left.png b/xui/imp/button_lower_left.png new file mode 100755 index 0000000..7e32a23 Binary files /dev/null and b/xui/imp/button_lower_left.png differ diff --git a/xui/imp/button_lower_right.png b/xui/imp/button_lower_right.png new file mode 100755 index 0000000..24b711e Binary files /dev/null and b/xui/imp/button_lower_right.png differ diff --git a/xui/imp/button_middle.png b/xui/imp/button_middle.png new file mode 100755 index 0000000..251460f Binary files /dev/null and b/xui/imp/button_middle.png differ diff --git a/xui/imp/button_right.png b/xui/imp/button_right.png new file mode 100755 index 0000000..a61e82a Binary files /dev/null and b/xui/imp/button_right.png differ diff --git a/xui/imp/button_upper.png b/xui/imp/button_upper.png new file mode 100755 index 0000000..004d906 Binary files /dev/null and b/xui/imp/button_upper.png differ diff --git a/xui/imp/button_upper_left.png b/xui/imp/button_upper_left.png new file mode 100755 index 0000000..7e32a23 Binary files /dev/null and b/xui/imp/button_upper_left.png differ diff --git a/xui/imp/button_upper_right.png b/xui/imp/button_upper_right.png new file mode 100755 index 0000000..7e32a23 Binary files /dev/null and b/xui/imp/button_upper_right.png differ diff --git a/xui/imp/check_box_off.png b/xui/imp/check_box_off.png new file mode 100755 index 0000000..2fd2752 Binary files /dev/null and b/xui/imp/check_box_off.png differ diff --git a/xui/imp/check_box_on.png b/xui/imp/check_box_on.png new file mode 100755 index 0000000..4414b36 Binary files /dev/null and b/xui/imp/check_box_on.png differ diff --git a/xui/imp/cursor.png b/xui/imp/cursor.png new file mode 100755 index 0000000..31c5316 Binary files /dev/null and b/xui/imp/cursor.png differ diff --git a/xui/imp/end_turn_button.png b/xui/imp/end_turn_button.png new file mode 100755 index 0000000..57cdd80 Binary files /dev/null and b/xui/imp/end_turn_button.png differ diff --git a/xui/imp/fill_bar_base.png b/xui/imp/fill_bar_base.png new file mode 100755 index 0000000..11b3869 Binary files /dev/null and b/xui/imp/fill_bar_base.png differ diff --git a/xui/imp/fill_bar_left.png b/xui/imp/fill_bar_left.png new file mode 100755 index 0000000..47e2044 Binary files /dev/null and b/xui/imp/fill_bar_left.png differ diff --git a/xui/imp/fill_bar_middle.png b/xui/imp/fill_bar_middle.png new file mode 100755 index 0000000..b133332 Binary files /dev/null and b/xui/imp/fill_bar_middle.png differ diff --git a/xui/imp/fill_bar_right.png b/xui/imp/fill_bar_right.png new file mode 100755 index 0000000..524795f Binary files /dev/null and b/xui/imp/fill_bar_right.png differ diff --git a/xui/imp/frame_left.png b/xui/imp/frame_left.png new file mode 100755 index 0000000..246ee15 Binary files /dev/null and b/xui/imp/frame_left.png differ diff --git a/xui/imp/frame_lower.png b/xui/imp/frame_lower.png new file mode 100755 index 0000000..564f7ec Binary files /dev/null and b/xui/imp/frame_lower.png differ diff --git a/xui/imp/frame_lower_left.png b/xui/imp/frame_lower_left.png new file mode 100755 index 0000000..6b5338f Binary files /dev/null and b/xui/imp/frame_lower_left.png differ diff --git a/xui/imp/frame_lower_right.png b/xui/imp/frame_lower_right.png new file mode 100755 index 0000000..d324d70 Binary files /dev/null and b/xui/imp/frame_lower_right.png differ diff --git a/xui/imp/frame_right.png b/xui/imp/frame_right.png new file mode 100755 index 0000000..bb7fc67 Binary files /dev/null and b/xui/imp/frame_right.png differ diff --git a/xui/imp/frame_upper.png b/xui/imp/frame_upper.png new file mode 100755 index 0000000..1bb3b0d Binary files /dev/null and b/xui/imp/frame_upper.png differ diff --git a/xui/imp/frame_upper_left.png b/xui/imp/frame_upper_left.png new file mode 100755 index 0000000..82bcc93 Binary files /dev/null and b/xui/imp/frame_upper_left.png differ diff --git a/xui/imp/frame_upper_right.png b/xui/imp/frame_upper_right.png new file mode 100755 index 0000000..a415bb1 Binary files /dev/null and b/xui/imp/frame_upper_right.png differ diff --git a/xui/imp/icon_frame.png b/xui/imp/icon_frame.png new file mode 100755 index 0000000..edc3346 Binary files /dev/null and b/xui/imp/icon_frame.png differ diff --git a/xui/imp/menu_left.png b/xui/imp/menu_left.png new file mode 100755 index 0000000..d391c22 Binary files /dev/null and b/xui/imp/menu_left.png differ diff --git a/xui/imp/menu_lower.png b/xui/imp/menu_lower.png new file mode 100755 index 0000000..b278aef Binary files /dev/null and b/xui/imp/menu_lower.png differ diff --git a/xui/imp/menu_lower_left.png b/xui/imp/menu_lower_left.png new file mode 100755 index 0000000..7e32a23 Binary files /dev/null and b/xui/imp/menu_lower_left.png differ diff --git a/xui/imp/menu_lower_right.png b/xui/imp/menu_lower_right.png new file mode 100755 index 0000000..24b711e Binary files /dev/null and b/xui/imp/menu_lower_right.png differ diff --git a/xui/imp/menu_middle.png b/xui/imp/menu_middle.png new file mode 100755 index 0000000..251460f Binary files /dev/null and b/xui/imp/menu_middle.png differ diff --git a/xui/imp/menu_right.png b/xui/imp/menu_right.png new file mode 100755 index 0000000..ea0408b Binary files /dev/null and b/xui/imp/menu_right.png differ diff --git a/xui/imp/menu_upper.png b/xui/imp/menu_upper.png new file mode 100755 index 0000000..6bad659 Binary files /dev/null and b/xui/imp/menu_upper.png differ diff --git a/xui/imp/menu_upper_left.png b/xui/imp/menu_upper_left.png new file mode 100755 index 0000000..7e32a23 Binary files /dev/null and b/xui/imp/menu_upper_left.png differ diff --git a/xui/imp/menu_upper_right.png b/xui/imp/menu_upper_right.png new file mode 100755 index 0000000..7e32a23 Binary files /dev/null and b/xui/imp/menu_upper_right.png differ diff --git a/xui/imp/overicon_frame.png b/xui/imp/overicon_frame.png new file mode 100755 index 0000000..5636691 Binary files /dev/null and b/xui/imp/overicon_frame.png differ diff --git a/xui/imp/scroll_bar_lower.png b/xui/imp/scroll_bar_lower.png new file mode 100755 index 0000000..5e2e671 Binary files /dev/null and b/xui/imp/scroll_bar_lower.png differ diff --git a/xui/imp/scroll_bar_middle.png b/xui/imp/scroll_bar_middle.png new file mode 100755 index 0000000..a0cf11c Binary files /dev/null and b/xui/imp/scroll_bar_middle.png differ diff --git a/xui/imp/scroll_bar_slider.png b/xui/imp/scroll_bar_slider.png new file mode 100644 index 0000000..216040c Binary files /dev/null and b/xui/imp/scroll_bar_slider.png differ diff --git a/xui/imp/scroll_bar_upper.png b/xui/imp/scroll_bar_upper.png new file mode 100755 index 0000000..c17f9b4 Binary files /dev/null and b/xui/imp/scroll_bar_upper.png differ diff --git a/xui/imp/separator_center.png b/xui/imp/separator_center.png new file mode 100644 index 0000000..216040c Binary files /dev/null and b/xui/imp/separator_center.png differ diff --git a/xui/imp/separator_left.png b/xui/imp/separator_left.png new file mode 100755 index 0000000..96b219e Binary files /dev/null and b/xui/imp/separator_left.png differ diff --git a/xui/imp/separator_middle.png b/xui/imp/separator_middle.png new file mode 100755 index 0000000..9e3ab0e Binary files /dev/null and b/xui/imp/separator_middle.png differ diff --git a/xui/imp/separator_right.png b/xui/imp/separator_right.png new file mode 100755 index 0000000..34f1936 Binary files /dev/null and b/xui/imp/separator_right.png differ diff --git a/xui/imp/status_left.png b/xui/imp/status_left.png new file mode 100755 index 0000000..9ab40e4 Binary files /dev/null and b/xui/imp/status_left.png differ diff --git a/xui/imp/status_lower.png b/xui/imp/status_lower.png new file mode 100755 index 0000000..df5aac9 Binary files /dev/null and b/xui/imp/status_lower.png differ diff --git a/xui/imp/status_lower_left.png b/xui/imp/status_lower_left.png new file mode 100755 index 0000000..02247af Binary files /dev/null and b/xui/imp/status_lower_left.png differ diff --git a/xui/imp/status_lower_right.png b/xui/imp/status_lower_right.png new file mode 100755 index 0000000..ce9f6d6 Binary files /dev/null and b/xui/imp/status_lower_right.png differ diff --git a/xui/imp/status_middle.png b/xui/imp/status_middle.png new file mode 100755 index 0000000..9344b80 Binary files /dev/null and b/xui/imp/status_middle.png differ diff --git a/xui/imp/status_right.png b/xui/imp/status_right.png new file mode 100755 index 0000000..9ab40e4 Binary files /dev/null and b/xui/imp/status_right.png differ diff --git a/xui/imp/status_upper.png b/xui/imp/status_upper.png new file mode 100755 index 0000000..df5aac9 Binary files /dev/null and b/xui/imp/status_upper.png differ diff --git a/xui/imp/status_upper_left.png b/xui/imp/status_upper_left.png new file mode 100755 index 0000000..dfb727f Binary files /dev/null and b/xui/imp/status_upper_left.png differ diff --git a/xui/imp/status_upper_right.png b/xui/imp/status_upper_right.png new file mode 100755 index 0000000..618735b Binary files /dev/null and b/xui/imp/status_upper_right.png differ diff --git a/xui/imp/tiny_fill_bar_base.png b/xui/imp/tiny_fill_bar_base.png new file mode 100755 index 0000000..1d269a3 Binary files /dev/null and b/xui/imp/tiny_fill_bar_base.png differ diff --git a/xui/imp/tiny_fill_bar_left.png b/xui/imp/tiny_fill_bar_left.png new file mode 100755 index 0000000..273075a Binary files /dev/null and b/xui/imp/tiny_fill_bar_left.png differ diff --git a/xui/imp/tiny_fill_bar_middle.png b/xui/imp/tiny_fill_bar_middle.png new file mode 100755 index 0000000..714591c Binary files /dev/null and b/xui/imp/tiny_fill_bar_middle.png differ diff --git a/xui/imp/tiny_fill_bar_right.png b/xui/imp/tiny_fill_bar_right.png new file mode 100755 index 0000000..46e5b5f Binary files /dev/null and b/xui/imp/tiny_fill_bar_right.png differ diff --git a/xui/imp/title_bar_left.png b/xui/imp/title_bar_left.png new file mode 100755 index 0000000..0dd6e2c Binary files /dev/null and b/xui/imp/title_bar_left.png differ diff --git a/xui/imp/title_bar_middle.png b/xui/imp/title_bar_middle.png new file mode 100755 index 0000000..444f836 Binary files /dev/null and b/xui/imp/title_bar_middle.png differ diff --git a/xui/imp/title_bar_right.png b/xui/imp/title_bar_right.png new file mode 100755 index 0000000..885cf7d Binary files /dev/null and b/xui/imp/title_bar_right.png differ diff --git a/xui/imp/ubericon_frame.png b/xui/imp/ubericon_frame.png new file mode 100755 index 0000000..632db4d Binary files /dev/null and b/xui/imp/ubericon_frame.png differ diff --git a/xui/imp/window_left.png b/xui/imp/window_left.png new file mode 100755 index 0000000..8657ad3 Binary files /dev/null and b/xui/imp/window_left.png differ diff --git a/xui/imp/window_lower.png b/xui/imp/window_lower.png new file mode 100755 index 0000000..e6680fa Binary files /dev/null and b/xui/imp/window_lower.png differ diff --git a/xui/imp/window_lower_left.png b/xui/imp/window_lower_left.png new file mode 100755 index 0000000..131f1bd Binary files /dev/null and b/xui/imp/window_lower_left.png differ diff --git a/xui/imp/window_lower_right.png b/xui/imp/window_lower_right.png new file mode 100755 index 0000000..c949d66 Binary files /dev/null and b/xui/imp/window_lower_right.png differ diff --git a/xui/imp/window_right.png b/xui/imp/window_right.png new file mode 100755 index 0000000..8657ad3 Binary files /dev/null and b/xui/imp/window_right.png differ diff --git a/xui/imp/window_upper.png b/xui/imp/window_upper.png new file mode 100755 index 0000000..e43d561 Binary files /dev/null and b/xui/imp/window_upper.png differ diff --git a/xui/imp/window_upper_left.png b/xui/imp/window_upper_left.png new file mode 100755 index 0000000..5bdd80c Binary files /dev/null and b/xui/imp/window_upper_left.png differ diff --git a/xui/imp/window_upper_right.png b/xui/imp/window_upper_right.png new file mode 100755 index 0000000..f72c9e1 Binary files /dev/null and b/xui/imp/window_upper_right.png differ diff --git a/xui/kobold/button_left.png b/xui/kobold/button_left.png new file mode 100755 index 0000000..459c94e Binary files /dev/null and b/xui/kobold/button_left.png differ diff --git a/xui/kobold/button_lower.png b/xui/kobold/button_lower.png new file mode 100755 index 0000000..5f975d5 Binary files /dev/null and b/xui/kobold/button_lower.png differ diff --git a/xui/kobold/button_lower_left.png b/xui/kobold/button_lower_left.png new file mode 100755 index 0000000..8eea2c7 Binary files /dev/null and b/xui/kobold/button_lower_left.png differ diff --git a/xui/kobold/button_lower_right.png b/xui/kobold/button_lower_right.png new file mode 100755 index 0000000..d634f51 Binary files /dev/null and b/xui/kobold/button_lower_right.png differ diff --git a/xui/kobold/button_middle.png b/xui/kobold/button_middle.png new file mode 100755 index 0000000..56941d0 Binary files /dev/null and b/xui/kobold/button_middle.png differ diff --git a/xui/kobold/button_right.png b/xui/kobold/button_right.png new file mode 100755 index 0000000..d99f39c Binary files /dev/null and b/xui/kobold/button_right.png differ diff --git a/xui/kobold/button_upper.png b/xui/kobold/button_upper.png new file mode 100755 index 0000000..7913dd2 Binary files /dev/null and b/xui/kobold/button_upper.png differ diff --git a/xui/kobold/button_upper_left.png b/xui/kobold/button_upper_left.png new file mode 100755 index 0000000..8645a96 Binary files /dev/null and b/xui/kobold/button_upper_left.png differ diff --git a/xui/kobold/button_upper_right.png b/xui/kobold/button_upper_right.png new file mode 100755 index 0000000..88314ab Binary files /dev/null and b/xui/kobold/button_upper_right.png differ diff --git a/xui/kobold/check_box_off.png b/xui/kobold/check_box_off.png new file mode 100755 index 0000000..67ade15 Binary files /dev/null and b/xui/kobold/check_box_off.png differ diff --git a/xui/kobold/check_box_on.png b/xui/kobold/check_box_on.png new file mode 100755 index 0000000..a4a348c Binary files /dev/null and b/xui/kobold/check_box_on.png differ diff --git a/xui/kobold/cursor.png b/xui/kobold/cursor.png new file mode 100755 index 0000000..642d25f Binary files /dev/null and b/xui/kobold/cursor.png differ diff --git a/xui/kobold/end_turn_button.png b/xui/kobold/end_turn_button.png new file mode 100755 index 0000000..d758401 Binary files /dev/null and b/xui/kobold/end_turn_button.png differ diff --git a/xui/kobold/fill_bar_base.png b/xui/kobold/fill_bar_base.png new file mode 100755 index 0000000..9700b8d Binary files /dev/null and b/xui/kobold/fill_bar_base.png differ diff --git a/xui/kobold/fill_bar_left.png b/xui/kobold/fill_bar_left.png new file mode 100755 index 0000000..f476e09 Binary files /dev/null and b/xui/kobold/fill_bar_left.png differ diff --git a/xui/kobold/fill_bar_middle.png b/xui/kobold/fill_bar_middle.png new file mode 100755 index 0000000..7925164 Binary files /dev/null and b/xui/kobold/fill_bar_middle.png differ diff --git a/xui/kobold/fill_bar_right.png b/xui/kobold/fill_bar_right.png new file mode 100755 index 0000000..186aeef Binary files /dev/null and b/xui/kobold/fill_bar_right.png differ diff --git a/xui/kobold/frame_left.png b/xui/kobold/frame_left.png new file mode 100755 index 0000000..2992c77 Binary files /dev/null and b/xui/kobold/frame_left.png differ diff --git a/xui/kobold/frame_lower.png b/xui/kobold/frame_lower.png new file mode 100755 index 0000000..595cc28 Binary files /dev/null and b/xui/kobold/frame_lower.png differ diff --git a/xui/kobold/frame_lower_left.png b/xui/kobold/frame_lower_left.png new file mode 100755 index 0000000..a9be1d1 Binary files /dev/null and b/xui/kobold/frame_lower_left.png differ diff --git a/xui/kobold/frame_lower_right.png b/xui/kobold/frame_lower_right.png new file mode 100755 index 0000000..cc665d9 Binary files /dev/null and b/xui/kobold/frame_lower_right.png differ diff --git a/xui/kobold/frame_right.png b/xui/kobold/frame_right.png new file mode 100755 index 0000000..237f05c Binary files /dev/null and b/xui/kobold/frame_right.png differ diff --git a/xui/kobold/frame_upper.png b/xui/kobold/frame_upper.png new file mode 100755 index 0000000..df9b88d Binary files /dev/null and b/xui/kobold/frame_upper.png differ diff --git a/xui/kobold/frame_upper_left.png b/xui/kobold/frame_upper_left.png new file mode 100755 index 0000000..c6ffbf3 Binary files /dev/null and b/xui/kobold/frame_upper_left.png differ diff --git a/xui/kobold/frame_upper_right.png b/xui/kobold/frame_upper_right.png new file mode 100755 index 0000000..7dde0ca Binary files /dev/null and b/xui/kobold/frame_upper_right.png differ diff --git a/xui/kobold/icon_frame.png b/xui/kobold/icon_frame.png new file mode 100755 index 0000000..91d28b4 Binary files /dev/null and b/xui/kobold/icon_frame.png differ diff --git a/xui/kobold/menu_left.png b/xui/kobold/menu_left.png new file mode 100755 index 0000000..b03f501 Binary files /dev/null and b/xui/kobold/menu_left.png differ diff --git a/xui/kobold/menu_lower.png b/xui/kobold/menu_lower.png new file mode 100755 index 0000000..f66da0f Binary files /dev/null and b/xui/kobold/menu_lower.png differ diff --git a/xui/kobold/menu_lower_left.png b/xui/kobold/menu_lower_left.png new file mode 100755 index 0000000..bd5992a Binary files /dev/null and b/xui/kobold/menu_lower_left.png differ diff --git a/xui/kobold/menu_lower_right.png b/xui/kobold/menu_lower_right.png new file mode 100755 index 0000000..8bcfeeb Binary files /dev/null and b/xui/kobold/menu_lower_right.png differ diff --git a/xui/kobold/menu_middle.png b/xui/kobold/menu_middle.png new file mode 100755 index 0000000..a26fbaf Binary files /dev/null and b/xui/kobold/menu_middle.png differ diff --git a/xui/kobold/menu_right.png b/xui/kobold/menu_right.png new file mode 100755 index 0000000..f94d669 Binary files /dev/null and b/xui/kobold/menu_right.png differ diff --git a/xui/kobold/menu_upper.png b/xui/kobold/menu_upper.png new file mode 100755 index 0000000..ca8f63f Binary files /dev/null and b/xui/kobold/menu_upper.png differ diff --git a/xui/kobold/menu_upper_left.png b/xui/kobold/menu_upper_left.png new file mode 100755 index 0000000..ecbe19c Binary files /dev/null and b/xui/kobold/menu_upper_left.png differ diff --git a/xui/kobold/menu_upper_right.png b/xui/kobold/menu_upper_right.png new file mode 100755 index 0000000..deca995 Binary files /dev/null and b/xui/kobold/menu_upper_right.png differ diff --git a/xui/kobold/overicon_frame.png b/xui/kobold/overicon_frame.png new file mode 100755 index 0000000..f02a9e0 Binary files /dev/null and b/xui/kobold/overicon_frame.png differ diff --git a/xui/kobold/scroll_bar_lower.png b/xui/kobold/scroll_bar_lower.png new file mode 100755 index 0000000..67755e3 Binary files /dev/null and b/xui/kobold/scroll_bar_lower.png differ diff --git a/xui/kobold/scroll_bar_middle.png b/xui/kobold/scroll_bar_middle.png new file mode 100755 index 0000000..84ca0b2 Binary files /dev/null and b/xui/kobold/scroll_bar_middle.png differ diff --git a/xui/kobold/scroll_bar_slider.png b/xui/kobold/scroll_bar_slider.png new file mode 100755 index 0000000..67ade15 Binary files /dev/null and b/xui/kobold/scroll_bar_slider.png differ diff --git a/xui/kobold/scroll_bar_upper.png b/xui/kobold/scroll_bar_upper.png new file mode 100755 index 0000000..1f1ac5a Binary files /dev/null and b/xui/kobold/scroll_bar_upper.png differ diff --git a/xui/kobold/separator_center.png b/xui/kobold/separator_center.png new file mode 100755 index 0000000..67ade15 Binary files /dev/null and b/xui/kobold/separator_center.png differ diff --git a/xui/kobold/separator_left.png b/xui/kobold/separator_left.png new file mode 100755 index 0000000..fcca2e2 Binary files /dev/null and b/xui/kobold/separator_left.png differ diff --git a/xui/kobold/separator_middle.png b/xui/kobold/separator_middle.png new file mode 100755 index 0000000..3fd8a18 Binary files /dev/null and b/xui/kobold/separator_middle.png differ diff --git a/xui/kobold/separator_right.png b/xui/kobold/separator_right.png new file mode 100755 index 0000000..d0c1ff7 Binary files /dev/null and b/xui/kobold/separator_right.png differ diff --git a/xui/kobold/status_left.png b/xui/kobold/status_left.png new file mode 100755 index 0000000..5a0b0cd Binary files /dev/null and b/xui/kobold/status_left.png differ diff --git a/xui/kobold/status_lower.png b/xui/kobold/status_lower.png new file mode 100755 index 0000000..f4a3428 Binary files /dev/null and b/xui/kobold/status_lower.png differ diff --git a/xui/kobold/status_lower_left.png b/xui/kobold/status_lower_left.png new file mode 100755 index 0000000..3d3061a Binary files /dev/null and b/xui/kobold/status_lower_left.png differ diff --git a/xui/kobold/status_lower_right.png b/xui/kobold/status_lower_right.png new file mode 100755 index 0000000..4db83b4 Binary files /dev/null and b/xui/kobold/status_lower_right.png differ diff --git a/xui/kobold/status_middle.png b/xui/kobold/status_middle.png new file mode 100755 index 0000000..fc8774a Binary files /dev/null and b/xui/kobold/status_middle.png differ diff --git a/xui/kobold/status_right.png b/xui/kobold/status_right.png new file mode 100755 index 0000000..2b47206 Binary files /dev/null and b/xui/kobold/status_right.png differ diff --git a/xui/kobold/status_upper.png b/xui/kobold/status_upper.png new file mode 100755 index 0000000..8ba8817 Binary files /dev/null and b/xui/kobold/status_upper.png differ diff --git a/xui/kobold/status_upper_left.png b/xui/kobold/status_upper_left.png new file mode 100755 index 0000000..4db83b4 Binary files /dev/null and b/xui/kobold/status_upper_left.png differ diff --git a/xui/kobold/status_upper_right.png b/xui/kobold/status_upper_right.png new file mode 100755 index 0000000..616a8b5 Binary files /dev/null and b/xui/kobold/status_upper_right.png differ diff --git a/xui/kobold/tiny_fill_bar_base.png b/xui/kobold/tiny_fill_bar_base.png new file mode 100755 index 0000000..e2e8b91 Binary files /dev/null and b/xui/kobold/tiny_fill_bar_base.png differ diff --git a/xui/kobold/tiny_fill_bar_left.png b/xui/kobold/tiny_fill_bar_left.png new file mode 100755 index 0000000..72cd6af Binary files /dev/null and b/xui/kobold/tiny_fill_bar_left.png differ diff --git a/xui/kobold/tiny_fill_bar_middle.png b/xui/kobold/tiny_fill_bar_middle.png new file mode 100755 index 0000000..481637c Binary files /dev/null and b/xui/kobold/tiny_fill_bar_middle.png differ diff --git a/xui/kobold/tiny_fill_bar_right.png b/xui/kobold/tiny_fill_bar_right.png new file mode 100755 index 0000000..17ba645 Binary files /dev/null and b/xui/kobold/tiny_fill_bar_right.png differ diff --git a/xui/kobold/title_bar_left.png b/xui/kobold/title_bar_left.png new file mode 100755 index 0000000..d60d30c Binary files /dev/null and b/xui/kobold/title_bar_left.png differ diff --git a/xui/kobold/title_bar_middle.png b/xui/kobold/title_bar_middle.png new file mode 100755 index 0000000..9553b37 Binary files /dev/null and b/xui/kobold/title_bar_middle.png differ diff --git a/xui/kobold/title_bar_right.png b/xui/kobold/title_bar_right.png new file mode 100755 index 0000000..4042ee7 Binary files /dev/null and b/xui/kobold/title_bar_right.png differ diff --git a/xui/kobold/ubericon_frame.png b/xui/kobold/ubericon_frame.png new file mode 100755 index 0000000..73d3ab9 Binary files /dev/null and b/xui/kobold/ubericon_frame.png differ diff --git a/xui/kobold/window_left.png b/xui/kobold/window_left.png new file mode 100755 index 0000000..f3b9c57 Binary files /dev/null and b/xui/kobold/window_left.png differ diff --git a/xui/kobold/window_lower.png b/xui/kobold/window_lower.png new file mode 100755 index 0000000..aa024d6 Binary files /dev/null and b/xui/kobold/window_lower.png differ diff --git a/xui/kobold/window_lower_left.png b/xui/kobold/window_lower_left.png new file mode 100755 index 0000000..10fa07f Binary files /dev/null and b/xui/kobold/window_lower_left.png differ diff --git a/xui/kobold/window_lower_right.png b/xui/kobold/window_lower_right.png new file mode 100755 index 0000000..d2f38c0 Binary files /dev/null and b/xui/kobold/window_lower_right.png differ diff --git a/xui/kobold/window_right.png b/xui/kobold/window_right.png new file mode 100755 index 0000000..8d308cd Binary files /dev/null and b/xui/kobold/window_right.png differ diff --git a/xui/kobold/window_upper.png b/xui/kobold/window_upper.png new file mode 100755 index 0000000..de0988f Binary files /dev/null and b/xui/kobold/window_upper.png differ diff --git a/xui/kobold/window_upper_left.png b/xui/kobold/window_upper_left.png new file mode 100755 index 0000000..9db4b46 Binary files /dev/null and b/xui/kobold/window_upper_left.png differ diff --git a/xui/kobold/window_upper_right.png b/xui/kobold/window_upper_right.png new file mode 100755 index 0000000..22c0a6f Binary files /dev/null and b/xui/kobold/window_upper_right.png differ diff --git a/xui/main/button_left.png b/xui/main/button_left.png new file mode 100755 index 0000000..1eab978 Binary files /dev/null and b/xui/main/button_left.png differ diff --git a/xui/main/button_lower.png b/xui/main/button_lower.png new file mode 100755 index 0000000..8cde9ed Binary files /dev/null and b/xui/main/button_lower.png differ diff --git a/xui/main/button_lower_left.png b/xui/main/button_lower_left.png new file mode 100755 index 0000000..4cc4d88 Binary files /dev/null and b/xui/main/button_lower_left.png differ diff --git a/xui/main/button_lower_right.png b/xui/main/button_lower_right.png new file mode 100755 index 0000000..67631b3 Binary files /dev/null and b/xui/main/button_lower_right.png differ diff --git a/xui/main/button_middle.png b/xui/main/button_middle.png new file mode 100755 index 0000000..e59eec4 Binary files /dev/null and b/xui/main/button_middle.png differ diff --git a/xui/main/button_right.png b/xui/main/button_right.png new file mode 100755 index 0000000..ecfe5f5 Binary files /dev/null and b/xui/main/button_right.png differ diff --git a/xui/main/button_upper.png b/xui/main/button_upper.png new file mode 100755 index 0000000..58fa8d1 Binary files /dev/null and b/xui/main/button_upper.png differ diff --git a/xui/main/button_upper_left.png b/xui/main/button_upper_left.png new file mode 100755 index 0000000..84850a2 Binary files /dev/null and b/xui/main/button_upper_left.png differ diff --git a/xui/main/button_upper_right.png b/xui/main/button_upper_right.png new file mode 100755 index 0000000..32b1787 Binary files /dev/null and b/xui/main/button_upper_right.png differ diff --git a/xui/main/check_box_off.png b/xui/main/check_box_off.png new file mode 100755 index 0000000..62aad2c Binary files /dev/null and b/xui/main/check_box_off.png differ diff --git a/xui/main/check_box_on.png b/xui/main/check_box_on.png new file mode 100755 index 0000000..46d48ee Binary files /dev/null and b/xui/main/check_box_on.png differ diff --git a/xui/main/cursor.png b/xui/main/cursor.png new file mode 100755 index 0000000..d2df188 Binary files /dev/null and b/xui/main/cursor.png differ diff --git a/xui/main/end_turn_button.png b/xui/main/end_turn_button.png new file mode 100755 index 0000000..62e857b Binary files /dev/null and b/xui/main/end_turn_button.png differ diff --git a/xui/main/fill_bar_base.png b/xui/main/fill_bar_base.png new file mode 100755 index 0000000..a00e65c Binary files /dev/null and b/xui/main/fill_bar_base.png differ diff --git a/xui/main/fill_bar_left.png b/xui/main/fill_bar_left.png new file mode 100755 index 0000000..718b784 Binary files /dev/null and b/xui/main/fill_bar_left.png differ diff --git a/xui/main/fill_bar_middle.png b/xui/main/fill_bar_middle.png new file mode 100755 index 0000000..09c7742 Binary files /dev/null and b/xui/main/fill_bar_middle.png differ diff --git a/xui/main/fill_bar_right.png b/xui/main/fill_bar_right.png new file mode 100755 index 0000000..7b0d2b3 Binary files /dev/null and b/xui/main/fill_bar_right.png differ diff --git a/xui/main/frame_left.png b/xui/main/frame_left.png new file mode 100755 index 0000000..a2a958a Binary files /dev/null and b/xui/main/frame_left.png differ diff --git a/xui/main/frame_lower.png b/xui/main/frame_lower.png new file mode 100755 index 0000000..81ca5e6 Binary files /dev/null and b/xui/main/frame_lower.png differ diff --git a/xui/main/frame_lower_left.png b/xui/main/frame_lower_left.png new file mode 100755 index 0000000..a72209e Binary files /dev/null and b/xui/main/frame_lower_left.png differ diff --git a/xui/main/frame_lower_right.png b/xui/main/frame_lower_right.png new file mode 100755 index 0000000..e6ce5ef Binary files /dev/null and b/xui/main/frame_lower_right.png differ diff --git a/xui/main/frame_right.png b/xui/main/frame_right.png new file mode 100755 index 0000000..f13c0c1 Binary files /dev/null and b/xui/main/frame_right.png differ diff --git a/xui/main/frame_upper.png b/xui/main/frame_upper.png new file mode 100755 index 0000000..1836052 Binary files /dev/null and b/xui/main/frame_upper.png differ diff --git a/xui/main/frame_upper_left.png b/xui/main/frame_upper_left.png new file mode 100755 index 0000000..0ceca8d Binary files /dev/null and b/xui/main/frame_upper_left.png differ diff --git a/xui/main/frame_upper_right.png b/xui/main/frame_upper_right.png new file mode 100755 index 0000000..9e81eb0 Binary files /dev/null and b/xui/main/frame_upper_right.png differ diff --git a/xui/main/icon_frame.png b/xui/main/icon_frame.png new file mode 100755 index 0000000..0f1db5c Binary files /dev/null and b/xui/main/icon_frame.png differ diff --git a/xui/main/menu_left.png b/xui/main/menu_left.png new file mode 100755 index 0000000..ad04d19 Binary files /dev/null and b/xui/main/menu_left.png differ diff --git a/xui/main/menu_lower.png b/xui/main/menu_lower.png new file mode 100755 index 0000000..664e550 Binary files /dev/null and b/xui/main/menu_lower.png differ diff --git a/xui/main/menu_lower_left.png b/xui/main/menu_lower_left.png new file mode 100755 index 0000000..6a45100 Binary files /dev/null and b/xui/main/menu_lower_left.png differ diff --git a/xui/main/menu_lower_right.png b/xui/main/menu_lower_right.png new file mode 100755 index 0000000..8fb6a26 Binary files /dev/null and b/xui/main/menu_lower_right.png differ diff --git a/xui/main/menu_middle.png b/xui/main/menu_middle.png new file mode 100755 index 0000000..687c3c2 Binary files /dev/null and b/xui/main/menu_middle.png differ diff --git a/xui/main/menu_right.png b/xui/main/menu_right.png new file mode 100755 index 0000000..0901983 Binary files /dev/null and b/xui/main/menu_right.png differ diff --git a/xui/main/menu_upper.png b/xui/main/menu_upper.png new file mode 100755 index 0000000..1468519 Binary files /dev/null and b/xui/main/menu_upper.png differ diff --git a/xui/main/menu_upper_left.png b/xui/main/menu_upper_left.png new file mode 100755 index 0000000..7f50d67 Binary files /dev/null and b/xui/main/menu_upper_left.png differ diff --git a/xui/main/menu_upper_right.png b/xui/main/menu_upper_right.png new file mode 100755 index 0000000..5237243 Binary files /dev/null and b/xui/main/menu_upper_right.png differ diff --git a/xui/main/overicon_frame.png b/xui/main/overicon_frame.png new file mode 100755 index 0000000..44a13fa Binary files /dev/null and b/xui/main/overicon_frame.png differ diff --git a/xui/main/scroll_bar_lower.png b/xui/main/scroll_bar_lower.png new file mode 100755 index 0000000..6ae9c44 Binary files /dev/null and b/xui/main/scroll_bar_lower.png differ diff --git a/xui/main/scroll_bar_middle.png b/xui/main/scroll_bar_middle.png new file mode 100755 index 0000000..734c732 Binary files /dev/null and b/xui/main/scroll_bar_middle.png differ diff --git a/xui/main/scroll_bar_slider.png b/xui/main/scroll_bar_slider.png new file mode 100755 index 0000000..62aad2c Binary files /dev/null and b/xui/main/scroll_bar_slider.png differ diff --git a/xui/main/scroll_bar_upper.png b/xui/main/scroll_bar_upper.png new file mode 100755 index 0000000..81fba3c Binary files /dev/null and b/xui/main/scroll_bar_upper.png differ diff --git a/xui/main/separator_center.png b/xui/main/separator_center.png new file mode 100755 index 0000000..62aad2c Binary files /dev/null and b/xui/main/separator_center.png differ diff --git a/xui/main/separator_left.png b/xui/main/separator_left.png new file mode 100755 index 0000000..728d4ff Binary files /dev/null and b/xui/main/separator_left.png differ diff --git a/xui/main/separator_middle.png b/xui/main/separator_middle.png new file mode 100755 index 0000000..d14912e Binary files /dev/null and b/xui/main/separator_middle.png differ diff --git a/xui/main/separator_right.png b/xui/main/separator_right.png new file mode 100755 index 0000000..6481f60 Binary files /dev/null and b/xui/main/separator_right.png differ diff --git a/xui/main/status_left.png b/xui/main/status_left.png new file mode 100755 index 0000000..ecd9b46 Binary files /dev/null and b/xui/main/status_left.png differ diff --git a/xui/main/status_lower.png b/xui/main/status_lower.png new file mode 100755 index 0000000..3a59006 Binary files /dev/null and b/xui/main/status_lower.png differ diff --git a/xui/main/status_lower_left.png b/xui/main/status_lower_left.png new file mode 100755 index 0000000..d75c94a Binary files /dev/null and b/xui/main/status_lower_left.png differ diff --git a/xui/main/status_lower_right.png b/xui/main/status_lower_right.png new file mode 100755 index 0000000..e0cda06 Binary files /dev/null and b/xui/main/status_lower_right.png differ diff --git a/xui/main/status_middle.png b/xui/main/status_middle.png new file mode 100755 index 0000000..bf70085 Binary files /dev/null and b/xui/main/status_middle.png differ diff --git a/xui/main/status_right.png b/xui/main/status_right.png new file mode 100755 index 0000000..ecd9b46 Binary files /dev/null and b/xui/main/status_right.png differ diff --git a/xui/main/status_upper.png b/xui/main/status_upper.png new file mode 100755 index 0000000..3a59006 Binary files /dev/null and b/xui/main/status_upper.png differ diff --git a/xui/main/status_upper_left.png b/xui/main/status_upper_left.png new file mode 100755 index 0000000..a83439b Binary files /dev/null and b/xui/main/status_upper_left.png differ diff --git a/xui/main/status_upper_right.png b/xui/main/status_upper_right.png new file mode 100755 index 0000000..ac1a9e2 Binary files /dev/null and b/xui/main/status_upper_right.png differ diff --git a/xui/main/tiny_fill_bar_base.png b/xui/main/tiny_fill_bar_base.png new file mode 100755 index 0000000..338b4a0 Binary files /dev/null and b/xui/main/tiny_fill_bar_base.png differ diff --git a/xui/main/tiny_fill_bar_left.png b/xui/main/tiny_fill_bar_left.png new file mode 100755 index 0000000..0017889 Binary files /dev/null and b/xui/main/tiny_fill_bar_left.png differ diff --git a/xui/main/tiny_fill_bar_middle.png b/xui/main/tiny_fill_bar_middle.png new file mode 100755 index 0000000..bd35d5a Binary files /dev/null and b/xui/main/tiny_fill_bar_middle.png differ diff --git a/xui/main/tiny_fill_bar_right.png b/xui/main/tiny_fill_bar_right.png new file mode 100755 index 0000000..1d0cfd5 Binary files /dev/null and b/xui/main/tiny_fill_bar_right.png differ diff --git a/xui/main/title_bar_left.png b/xui/main/title_bar_left.png new file mode 100755 index 0000000..270bf4a Binary files /dev/null and b/xui/main/title_bar_left.png differ diff --git a/xui/main/title_bar_middle.png b/xui/main/title_bar_middle.png new file mode 100755 index 0000000..75ad065 Binary files /dev/null and b/xui/main/title_bar_middle.png differ diff --git a/xui/main/title_bar_right.png b/xui/main/title_bar_right.png new file mode 100755 index 0000000..e2cf22d Binary files /dev/null and b/xui/main/title_bar_right.png differ diff --git a/xui/main/ubericon_frame.png b/xui/main/ubericon_frame.png new file mode 100755 index 0000000..f6907d3 Binary files /dev/null and b/xui/main/ubericon_frame.png differ diff --git a/xui/main/window_left.png b/xui/main/window_left.png new file mode 100755 index 0000000..e87a3de Binary files /dev/null and b/xui/main/window_left.png differ diff --git a/xui/main/window_lower.png b/xui/main/window_lower.png new file mode 100755 index 0000000..09b9e7e Binary files /dev/null and b/xui/main/window_lower.png differ diff --git a/xui/main/window_lower_left.png b/xui/main/window_lower_left.png new file mode 100755 index 0000000..389a476 Binary files /dev/null and b/xui/main/window_lower_left.png differ diff --git a/xui/main/window_lower_right.png b/xui/main/window_lower_right.png new file mode 100755 index 0000000..7584dfb Binary files /dev/null and b/xui/main/window_lower_right.png differ diff --git a/xui/main/window_right.png b/xui/main/window_right.png new file mode 100755 index 0000000..d41293a Binary files /dev/null and b/xui/main/window_right.png differ diff --git a/xui/main/window_upper.png b/xui/main/window_upper.png new file mode 100755 index 0000000..6f68fcf Binary files /dev/null and b/xui/main/window_upper.png differ diff --git a/xui/main/window_upper_left.png b/xui/main/window_upper_left.png new file mode 100755 index 0000000..e43fc73 Binary files /dev/null and b/xui/main/window_upper_left.png differ diff --git a/xui/main/window_upper_right.png b/xui/main/window_upper_right.png new file mode 100755 index 0000000..be10a83 Binary files /dev/null and b/xui/main/window_upper_right.png differ diff --git a/xui/map_preview_panel_off.png b/xui/map_preview_panel_off.png new file mode 100755 index 0000000..d0fb58a Binary files /dev/null and b/xui/map_preview_panel_off.png differ diff --git a/xui/map_preview_panel_on.png b/xui/map_preview_panel_on.png new file mode 100755 index 0000000..08dd569 Binary files /dev/null and b/xui/map_preview_panel_on.png differ diff --git a/xui/monospace.png b/xui/monospace.png new file mode 100755 index 0000000..074f192 Binary files /dev/null and b/xui/monospace.png differ diff --git a/xui/palette.png b/xui/palette.png new file mode 100755 index 0000000..8a8ab27 Binary files /dev/null and b/xui/palette.png differ diff --git a/xui/regular.png b/xui/regular.png new file mode 100755 index 0000000..0e5bfe7 Binary files /dev/null and b/xui/regular.png differ diff --git a/xui/status_preview_panel_off.png b/xui/status_preview_panel_off.png new file mode 100755 index 0000000..fdb5173 Binary files /dev/null and b/xui/status_preview_panel_off.png differ diff --git a/xui/status_preview_panel_on.png b/xui/status_preview_panel_on.png new file mode 100755 index 0000000..530fc12 Binary files /dev/null and b/xui/status_preview_panel_on.png differ diff --git a/xui/text_box_panel_off.png b/xui/text_box_panel_off.png new file mode 100755 index 0000000..06efe6c Binary files /dev/null and b/xui/text_box_panel_off.png differ diff --git a/xui/text_box_panel_on.png b/xui/text_box_panel_on.png new file mode 100755 index 0000000..0576c96 Binary files /dev/null and b/xui/text_box_panel_on.png differ diff --git a/xulkan.h b/xulkan.h new file mode 100755 index 0000000..4a3b2fc --- /dev/null +++ b/xulkan.h @@ -0,0 +1,2351 @@ +/// _ _ +/// __ ___ _| | | ____ _ _ __ +/// \ \/ / | | | | |/ / _` | '_ \ +/// > <| |_| | | < (_| | | | | +/// /_/\_\\__,_|_|_|\_\__,_|_| |_| +/// +/// 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 + +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); +} diff --git a/xungeon.h b/xungeon.h new file mode 100755 index 0000000..b88cf7a --- /dev/null +++ b/xungeon.h @@ -0,0 +1,271 @@ +// __ ___ _ _ __ __ _ ___ ___ _ __ +// \ \/ / | | | '_ \ / _` |/ _ \/ _ \| '_ \ +// > <| |_| | | | | (_| | __/ (_) | | | | +// /_/\_\\__,_|_| |_|\__, |\___|\___/|_| |_| +// |___/ +// +// 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); +} diff --git a/xuxuxu.c b/xuxuxu.c new file mode 100755 index 0000000..ee77e9c --- /dev/null +++ b/xuxuxu.c @@ -0,0 +1,130 @@ +#include +#include +#include + +#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); +} diff --git a/xyntax.h b/xyntax.h new file mode 100755 index 0000000..849d44c --- /dev/null +++ b/xyntax.h @@ -0,0 +1,175 @@ +/// _ +/// __ ___ _ _ __ | |_ __ ___ __ +/// \ \/ / | | | '_ \| __/ _` \ \/ / +/// > <| |_| | | | | || (_| |> < +/// /_/\_\\__, |_| |_|\__\__,_/_/\_\ +/// |___/ +/// +/// 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); +}