commit 8d66b18495e6d39df15f97e90f89124faec8bab7 Author: rw-r-r_0644 Date: Wed Oct 5 16:03:29 2016 +0200 Final Release! diff --git a/GX2_template.cbp b/GX2_template.cbp new file mode 100644 index 0000000..e28a604 --- /dev/null +++ b/GX2_template.cbp @@ -0,0 +1,281 @@ + + + + + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9cecc1d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +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: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..149acec --- /dev/null +++ b/Makefile @@ -0,0 +1,227 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPRO") +endif +export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH) +export LIBOGC_INC := $(DEVKITPRO)/libogc/include +export LIBOGC_LIB := $(DEVKITPRO)/libogc/lib/wii +export PORTLIBS := $(DEVKITPRO)/portlibs/ppc + +PREFIX := powerpc-eabi- + +export AS := $(PREFIX)as +export CC := $(PREFIX)gcc +export CXX := $(PREFIX)g++ +export AR := $(PREFIX)ar +export OBJCOPY := $(PREFIX)objcopy + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := gx2_template +BUILD := build +BUILD_DBG := $(TARGET)_dbg +SOURCES := src \ + src/common \ + src/dynamic_libs \ + src/fs \ + src/game \ + src/gui \ + src/menu \ + src/resources \ + src/sounds \ + src/system \ + src/utils \ + src/video \ + src/video/shaders +DATA := data \ + data/images \ + data/fonts \ + data/sounds + +INCLUDES := src + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +CFLAGS := -std=gnu11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ + -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) +CXXFLAGS := -std=gnu++11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ + -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) +ASFLAGS := -mregnames +LDFLAGS := -nostartfiles -Wl,-Map,$(notdir $@).map,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size,-wrap,_malloc_r,-wrap,_free_r,-wrap,_realloc_r,-wrap,_calloc_r,-wrap,_memalign_r,-wrap,_malloc_usable_size_r,-wrap,valloc,-wrap,_valloc_r,-wrap,_pvalloc_r,--gc-sections + +#--------------------------------------------------------------------------------- +Q := @ +MAKEFLAGS += --no-print-directory +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lgcc -lgd -lpng -ljpeg -lz -lfreetype -lmad -lvorbisidec + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CURDIR) \ + $(DEVKITPPC)/lib \ + $(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2 + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- +export PROJECTDIR := $(CURDIR) +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +FILELIST := $(shell bash ./filelist.sh) +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) +TTFFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf))) +PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) \ + $(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES)) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) -I$(LIBOGC_INC) \ + -I$(PORTLIBS)/include -I$(PORTLIBS)/include/freetype2 + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) -L$(PORTLIBS)/lib + +export OUTPUT := $(CURDIR)/$(TARGET) +.PHONY: $(BUILD) clean install + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with the .jpg extension +#--------------------------------------------------------------------------------- +%.elf: link.ld $(OFILES) + @echo "linking ... $(TARGET).elf" + $(Q)$(LD) -n -T $^ $(LDFLAGS) -o ../$(BUILD_DBG).elf $(LIBPATHS) $(LIBS) + $(Q)$(OBJCOPY) -S -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@ + +../data/loader.bin: + $(MAKE) -C ../loader clean + $(MAKE) -C ../loader +#--------------------------------------------------------------------------------- +%.a: +#--------------------------------------------------------------------------------- + @echo $(notdir $@) + @rm -f $@ + @$(AR) -rc $@ $^ + +#--------------------------------------------------------------------------------- +%.o: %.cpp + @echo $(notdir $<) + @$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.o: %.c + @echo $(notdir $<) + @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.o: %.S + @echo $(notdir $<) + @$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER) + +#--------------------------------------------------------------------------------- +%.png.o : %.png + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.jpg.o : %.jpg + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.ttf.o : %.ttf + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.bin.o : %.bin + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.wav.o : %.wav + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.mp3.o : %.mp3 + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +#--------------------------------------------------------------------------------- +%.ogg.o : %.ogg + @echo $(notdir $<) + @bin2s -a 32 $< | $(AS) -o $(@) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/README.md b/README.md new file mode 100644 index 0000000..65f4f74 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +#Flappy Bird GX2# +A GX2 Flappy Bird port for WiiU +Assest from floppy bird HTML5 and original android game + +#Usage# +Press A to begin the Game +Press A to jump +Press HOME to exit +Avoid the pipes and the flor! + +#Building# +In order to build this application, you need the custom liboGC and portlibs modified/created by dimok. You can find them on the loadiine_gx2 repo (https://github.com/dimok789/loadiine_gx2/releases/tag/v0.2). Simply put the files in your devkit folder and run the Makefile. + +#Credits:# +dimok - WiiU librabries, dynamic_libs, examples, Homebrew Launcher +Maschell - GX2_Example and coding help +vgmoose - Coding help +pwsincd - Icon diff --git a/data/fonts/font.ttf b/data/fonts/font.ttf new file mode 100644 index 0000000..04be6f5 Binary files /dev/null and b/data/fonts/font.ttf differ diff --git a/data/images/bg_back.png b/data/images/bg_back.png new file mode 100755 index 0000000..7ce9951 Binary files /dev/null and b/data/images/bg_back.png differ diff --git a/data/images/bg_front.png b/data/images/bg_front.png new file mode 100755 index 0000000..5143749 Binary files /dev/null and b/data/images/bg_front.png differ diff --git a/data/images/flappy_bird_1.png b/data/images/flappy_bird_1.png new file mode 100755 index 0000000..f98dc06 Binary files /dev/null and b/data/images/flappy_bird_1.png differ diff --git a/data/images/flappy_bird_2.png b/data/images/flappy_bird_2.png new file mode 100755 index 0000000..efeebb2 Binary files /dev/null and b/data/images/flappy_bird_2.png differ diff --git a/data/images/flappy_bird_3.png b/data/images/flappy_bird_3.png new file mode 100755 index 0000000..e56c6ed Binary files /dev/null and b/data/images/flappy_bird_3.png differ diff --git a/data/images/flappy_bird_4.png b/data/images/flappy_bird_4.png new file mode 100755 index 0000000..efeebb2 Binary files /dev/null and b/data/images/flappy_bird_4.png differ diff --git a/data/images/font_big_0.png b/data/images/font_big_0.png new file mode 100755 index 0000000..938a3d1 Binary files /dev/null and b/data/images/font_big_0.png differ diff --git a/data/images/font_big_1.png b/data/images/font_big_1.png new file mode 100755 index 0000000..ba40e0c Binary files /dev/null and b/data/images/font_big_1.png differ diff --git a/data/images/font_big_2.png b/data/images/font_big_2.png new file mode 100755 index 0000000..4d0d700 Binary files /dev/null and b/data/images/font_big_2.png differ diff --git a/data/images/font_big_3.png b/data/images/font_big_3.png new file mode 100755 index 0000000..479d6e6 Binary files /dev/null and b/data/images/font_big_3.png differ diff --git a/data/images/font_big_4.png b/data/images/font_big_4.png new file mode 100755 index 0000000..14d938c Binary files /dev/null and b/data/images/font_big_4.png differ diff --git a/data/images/font_big_5.png b/data/images/font_big_5.png new file mode 100755 index 0000000..1339258 Binary files /dev/null and b/data/images/font_big_5.png differ diff --git a/data/images/font_big_6.png b/data/images/font_big_6.png new file mode 100755 index 0000000..c1dae50 Binary files /dev/null and b/data/images/font_big_6.png differ diff --git a/data/images/font_big_7.png b/data/images/font_big_7.png new file mode 100755 index 0000000..39434c5 Binary files /dev/null and b/data/images/font_big_7.png differ diff --git a/data/images/font_big_8.png b/data/images/font_big_8.png new file mode 100755 index 0000000..3892afd Binary files /dev/null and b/data/images/font_big_8.png differ diff --git a/data/images/font_big_9.png b/data/images/font_big_9.png new file mode 100755 index 0000000..3897c9d Binary files /dev/null and b/data/images/font_big_9.png differ diff --git a/data/images/font_big_null.png b/data/images/font_big_null.png new file mode 100755 index 0000000..773a6db Binary files /dev/null and b/data/images/font_big_null.png differ diff --git a/data/images/loose.png b/data/images/loose.png new file mode 100755 index 0000000..ab681cc Binary files /dev/null and b/data/images/loose.png differ diff --git a/data/images/pipe_down.png b/data/images/pipe_down.png new file mode 100755 index 0000000..b284ad1 Binary files /dev/null and b/data/images/pipe_down.png differ diff --git a/data/images/pipe_up.png b/data/images/pipe_up.png new file mode 100755 index 0000000..b5b9d8d Binary files /dev/null and b/data/images/pipe_up.png differ diff --git a/data/images/splash.png b/data/images/splash.png new file mode 100755 index 0000000..85f3ec6 Binary files /dev/null and b/data/images/splash.png differ diff --git a/data/sounds/bgMusic.ogg b/data/sounds/bgMusic.ogg new file mode 100644 index 0000000..d341468 Binary files /dev/null and b/data/sounds/bgMusic.ogg differ diff --git a/data/sounds/button_click.mp3 b/data/sounds/button_click.mp3 new file mode 100644 index 0000000..ec4aad7 Binary files /dev/null and b/data/sounds/button_click.mp3 differ diff --git a/data/sounds/sfx_die.ogg b/data/sounds/sfx_die.ogg new file mode 100755 index 0000000..04c9a26 Binary files /dev/null and b/data/sounds/sfx_die.ogg differ diff --git a/data/sounds/sfx_point.ogg b/data/sounds/sfx_point.ogg new file mode 100755 index 0000000..efb2d99 Binary files /dev/null and b/data/sounds/sfx_point.ogg differ diff --git a/data/sounds/sfx_swooshing.ogg b/data/sounds/sfx_swooshing.ogg new file mode 100755 index 0000000..f483cd6 Binary files /dev/null and b/data/sounds/sfx_swooshing.ogg differ diff --git a/data/sounds/sfx_wing.ogg b/data/sounds/sfx_wing.ogg new file mode 100755 index 0000000..76e3a2a Binary files /dev/null and b/data/sounds/sfx_wing.ogg differ diff --git a/filelist.sh b/filelist.sh new file mode 100755 index 0000000..87cbee1 --- /dev/null +++ b/filelist.sh @@ -0,0 +1,83 @@ +#! /bin/bash +# +# Automatic resource file list generation +# Created by Dimok + +outFile="./src/resources/filelist.h" +count_old=$(cat $outFile 2>/dev/null | tr -d '\n\n' | sed 's/[^0-9]*\([0-9]*\).*/\1/') + +count=0 +if [[ $OSTYPE == darwin* ]]; +then + +for i in $(gfind ./data/images/ ./data/sounds/ ./data/fonts/ -maxdepth 1 -type f \( ! -printf "%f\n" \) | sort -f) +do + files[count]=$i + count=$((count+1)) +done + +else + +for i in $(find ./data/images/ ./data/sounds/ ./data/fonts/ -maxdepth 1 -type f \( ! -printf "%f\n" \) | sort -f) +do + files[count]=$i + count=$((count+1)) +done + +fi + +if [ "$count_old" != "$count" ] || [ ! -f $outFile ] +then + +echo "Generating filelist.h for $count files." >&2 +cat < $outFile +/**************************************************************************** + * Loadiine resource files. + * This file is generated automatically. + * Includes $count files. + * + * NOTE: + * Any manual modification of this file will be overwriten by the generation. + ****************************************************************************/ +#ifndef _FILELIST_H_ +#define _FILELIST_H_ + +#include + +typedef struct _RecourceFile +{ + const char *filename; + const u8 *DefaultFile; + const u32 &DefaultFileSize; + u8 *CustomFile; + u32 CustomFileSize; +} RecourceFile; + +EOF + +for i in ${files[@]} +do + filename=${i%.*} + extension=${i##*.} + echo 'extern const u8 '$filename'_'$extension'[];' >> $outFile + echo 'extern const u32 '$filename'_'$extension'_size;' >> $outFile + echo '' >> $outFile +done + +echo 'static RecourceFile RecourceList[] =' >> $outFile +echo '{' >> $outFile + +for i in ${files[@]} +do + filename=${i%.*} + extension=${i##*.} + echo -e '\t{"'$i'", '$filename'_'$extension', '$filename'_'$extension'_size, NULL, 0},' >> $outFile +done + +echo -e '\t{NULL, NULL, 0, NULL, 0}' >> $outFile +echo '};' >> $outFile + +echo '' >> $outFile +echo '#endif' >> $outFile + +fi diff --git a/refresh.sh b/refresh.sh new file mode 100755 index 0000000..7d72d6b --- /dev/null +++ b/refresh.sh @@ -0,0 +1,6 @@ +rm src/resources/filelist.h +make clean +make -j4 +rm /media/sf_con_mint/gx2_template.elf +cp gx2_template.elf /media/sf_con_mint/gx2_template.elf + diff --git a/src/Application.cpp b/src/Application.cpp new file mode 100644 index 0000000..51c01d4 --- /dev/null +++ b/src/Application.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "Application.h" +#include "common/common.h" +#include "dynamic_libs/os_functions.h" +#include "gui/FreeTypeGX.h" +#include "gui/VPadController.h" +#include "gui/WPadController.h" +#include "resources/Resources.h" +#include "sounds/SoundHandler.hpp" +#include "utils/logger.h" + +Application *Application::applicationInstance = NULL; +bool Application::exitApplication = false; + +Application::Application() + : CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x20000) + , bgMusic(NULL) + , video(NULL) + , mainWindow(NULL) + , exitCode(EXIT_RELAUNCH_ON_LOAD) +{ + controller[0] = new VPadController(GuiTrigger::CHANNEL_1); + controller[1] = new WPadController(GuiTrigger::CHANNEL_2); + controller[2] = new WPadController(GuiTrigger::CHANNEL_3); + controller[3] = new WPadController(GuiTrigger::CHANNEL_4); + controller[4] = new WPadController(GuiTrigger::CHANNEL_5); + + //! create bgMusic + /* + bgMusic = new GuiSound(Resources::GetFile("bgMusic.ogg"), Resources::GetFileSize("bgMusic.ogg")); + bgMusic->SetLoop(true); + bgMusic->Play(); + bgMusic->SetVolume(50);*/ + + exitApplication = false; +} + +Application::~Application(){ + log_printf("Destroy music\n"); + + delete bgMusic; + + log_printf("Destroy controller\n"); + + for(int i = 0; i < 5; i++) + delete controller[i]; + + log_printf("Destroy async deleter\n"); + AsyncDeleter::triggerDeleteProcess(); + AsyncDeleter::destroyInstance(); + + log_printf("Clear resources\n"); + Resources::Clear(); + + log_printf("Stop sound handler\n"); + SoundHandler::DestroyInstance(); +} + +int Application::exec(){ + //! start main GX2 thread + resumeThread(); + //! now wait for thread to finish + shutdownThread(); + + return exitCode; +} + +void Application::fadeOut(){ + GuiImage fadeOut(video->getTvWidth(), video->getTvHeight(), (GX2Color){ 0, 0, 0, 255 }); + + for(int i = 0; i < 255; i += 10) + { + if(i > 255) + i = 255; + + fadeOut.setAlpha(i / 255.0f); + + //! start rendering DRC + video->prepareDrcRendering(); + mainWindow->drawDrc(video); + + GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_ALWAYS); + fadeOut.draw(video); + GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL); + + video->drcDrawDone(); + + //! start rendering TV + video->prepareTvRendering(); + + mainWindow->drawTv(video); + + GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_ALWAYS); + fadeOut.draw(video); + GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL); + + video->tvDrawDone(); + + //! as last point update the effects as it can drop elements + mainWindow->updateEffects(); + + video->waitForVSync(); + } + + //! one last cleared black screen + video->prepareDrcRendering(); + video->drcDrawDone(); + video->prepareTvRendering(); + video->tvDrawDone(); + video->waitForVSync(); + video->tvEnable(false); + video->drcEnable(false); +} + +void Application::executeThread(void){ + log_printf("Initialize video\n"); + video = new CVideo(GX2_TV_SCAN_MODE_720P, GX2_DRC_SINGLE); + + log_printf("Video size %i x %i\n", video->getTvWidth(), video->getTvHeight()); + + //! setup default Font + log_printf("Initialize main font system\n"); + FreeTypeGX *fontSystem = new FreeTypeGX(Resources::GetFile("font.ttf"), Resources::GetFileSize("font.ttf"), true); + GuiText::setPresetFont(fontSystem); + + log_printf("Initialize main window\n"); + + mainWindow = new MainWindow(video->getTvWidth(), video->getTvHeight()); + + log_printf("Entering main loop\n"); + + //! main GX2 loop (60 Hz cycle with max priority on core 1) + while(!exitApplication) + { + //! Read out inputs + for(int i = 0; i < 5; i++) + { + if(controller[i]->update(video->getTvWidth(), video->getTvHeight()) == false) + continue; + + if(controller[i]->data.buttons_d & VPAD_BUTTON_HOME){ + exitApplication = true; + } + + //! update controller states + mainWindow->update(controller[i]); + } + + mainWindow->process(); + + //! start rendering DRC + video->prepareDrcRendering(); + mainWindow->drawDrc(video); + video->drcDrawDone(); + + //! start rendering TV + video->prepareTvRendering(); + mainWindow->drawTv(video); + video->tvDrawDone(); + + //! enable screen after first frame render + if(video->getFrameCount() == 0) { + video->tvEnable(true); + video->drcEnable(true); + } + + //! as last point update the effects as it can drop elements + mainWindow->updateEffects(); + + video->waitForVSync(); + + //! transfer elements to real delete list here after all processes are finished + //! the elements are transfered to another list to delete the elements in a separate thread + //! and avoid blocking the GUI thread + AsyncDeleter::triggerDeleteProcess(); + } + + fadeOut(); + + delete mainWindow; + delete fontSystem; + delete video; +} diff --git a/src/Application.h b/src/Application.h new file mode 100644 index 0000000..9abbafd --- /dev/null +++ b/src/Application.h @@ -0,0 +1,73 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef _APPLICATION_H +#define _APPLICATION_H + +#include "menu/MainWindow.h" +#include "video/CVideo.h" +#include "system/CThread.h" + +class Application : public CThread +{ +public: + static Application * instance() { + if(!applicationInstance) + applicationInstance = new Application(); + return applicationInstance; + } + static void destroyInstance() { + if(applicationInstance) { + delete applicationInstance; + applicationInstance = NULL; + } + } + + CVideo *getVideo(void) const { + return video; + } + MainWindow *getMainWindow(void) const { + return mainWindow; + } + + GuiSound *getBgMusic(void) const { + return bgMusic; + } + + int exec(void); + void fadeOut(void); + + void quit(int code) { + exitCode = code; + exitApplication = true; + } +private: + Application(); + virtual ~Application(); + + static Application *applicationInstance; + static bool exitApplication; + + void executeThread(void); + + GuiSound *bgMusic; + CVideo *video; + MainWindow *mainWindow; + GuiController *controller[5]; + int exitCode; +}; + +#endif //_APPLICATION_H diff --git a/src/common/common.h b/src/common/common.h new file mode 100644 index 0000000..7d224c8 --- /dev/null +++ b/src/common/common.h @@ -0,0 +1,59 @@ +#ifndef COMMON_H +#define COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "os_defs.h" + +#define CAFE_OS_SD_PATH "/vol/external01" +#define SD_PATH "sd:" +#define WIIU_PATH "/wiiu" + +/* Macros for libs */ +#define LIB_CORE_INIT 0 +#define LIB_NSYSNET 1 +#define LIB_GX2 2 +#define LIB_AOC 3 +#define LIB_AX 4 +#define LIB_FS 5 +#define LIB_OS 6 +#define LIB_PADSCORE 7 +#define LIB_SOCKET 8 +#define LIB_SYS 9 +#define LIB_VPAD 10 +#define LIB_NN_ACP 11 +#define LIB_SYSHID 12 +#define LIB_VPADBASE 13 + +// functions types +#define STATIC_FUNCTION 0 +#define DYNAMIC_FUNCTION 1 + +// none dynamic libs +#define LIB_LOADER 0x1001 + +#ifndef MEM_BASE +#define MEM_BASE (0x00800000) +#endif + +#define ELF_DATA_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x00)) +#define ELF_DATA_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x04)) +#define MAIN_ENTRY_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x00)) +#define OS_FIRMWARE (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x04)) + +#define OS_SPECIFICS ((OsSpecifics*)(MEM_BASE + 0x1500)) + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif +#define EXIT_HBL_EXIT 0xFFFFFFFE +#define EXIT_RELAUNCH_ON_LOAD 0xFFFFFFFD + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_H */ + diff --git a/src/common/os_defs.h b/src/common/os_defs.h new file mode 100644 index 0000000..48a4c8f --- /dev/null +++ b/src/common/os_defs.h @@ -0,0 +1,25 @@ +#ifndef __OS_DEFS_H_ +#define __OS_DEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _OsSpecifics +{ + unsigned int addr_OSDynLoad_Acquire; + unsigned int addr_OSDynLoad_FindExport; + unsigned int addr_OSTitle_main_entry; + + unsigned int addr_KernSyscallTbl1; + unsigned int addr_KernSyscallTbl2; + unsigned int addr_KernSyscallTbl3; + unsigned int addr_KernSyscallTbl4; + unsigned int addr_KernSyscallTbl5; +} OsSpecifics; + +#ifdef __cplusplus +} +#endif + +#endif // __OS_DEFS_H_ diff --git a/src/common/types.h b/src/common/types.h new file mode 100644 index 0000000..3435e56 --- /dev/null +++ b/src/common/types.h @@ -0,0 +1,7 @@ +#ifndef TYPES_H +#define TYPES_H + +#include + +#endif /* TYPES_H */ + diff --git a/src/dynamic_libs/README.md b/src/dynamic_libs/README.md new file mode 100644 index 0000000..be82302 --- /dev/null +++ b/src/dynamic_libs/README.md @@ -0,0 +1,2 @@ +# dynamic_libs +Dynamic libs for WiiU homebrew diff --git a/src/dynamic_libs/acp_functions.c b/src/dynamic_libs/acp_functions.c new file mode 100644 index 0000000..eb931f8 --- /dev/null +++ b/src/dynamic_libs/acp_functions.c @@ -0,0 +1,40 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "os_functions.h" +#include "acp_functions.h" + +unsigned int acp_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, GetMetaXml, void * _ACPMetaXml); + +void InitAcquireACP(void) +{ + OSDynLoad_Acquire("nn_acp.rpl", &acp_handle); +} + +void InitACPFunctionPointers(void) +{ + InitAcquireACP(); + OSDynLoad_FindExport(acp_handle,0,"GetMetaXml__Q2_2nn3acpFP11_ACPMetaXml",&GetMetaXml); +} diff --git a/src/dynamic_libs/acp_functions.h b/src/dynamic_libs/acp_functions.h new file mode 100644 index 0000000..dc1822d --- /dev/null +++ b/src/dynamic_libs/acp_functions.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __ACP_FUNCTIONS_H_ +#define __ACP_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern unsigned int acp_handle; + +void InitACPFunctionPointers(void); +void InitAcquireACP(void); + +#ifdef __cplusplus +} +#endif + +#endif // __VPAD_FUNCTIONS_H_ diff --git a/src/dynamic_libs/aoc_functions.c b/src/dynamic_libs/aoc_functions.c new file mode 100644 index 0000000..e74306d --- /dev/null +++ b/src/dynamic_libs/aoc_functions.c @@ -0,0 +1,58 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "os_functions.h" +#include "aoc_functions.h" + +unsigned int aoc_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(s32, AOC_Initialize, void); +EXPORT_DECL(s32, AOC_Finalize, void); +EXPORT_DECL(u32, AOC_CalculateWorkBufferSize, u32 num_titles); +EXPORT_DECL(s32, AOC_ListTitle, u32 * num_titles, void * titles, u32 max_titles, void * buffer, u32 buffer_size); +EXPORT_DECL(s32, AOC_OpenTitle, char* aoc_path, void * title, void * buffer, u32 buffer_size); +EXPORT_DECL(s32, AOC_CloseTitle, void * title); +EXPORT_DECL(s32, AOC_DeleteContent, u64 title_id, u16 contentIndexes[], u32 numberOfContent, void* buffer, u32 buffer_size); +EXPORT_DECL(s32, AOC_GetPurchaseInfo, u32 * bResult, u64 title_id, u16 contentIndexes[], u32 numberOfContent, void * buffer, u32 buffer_size); + +void InitAcquireAoc(void) +{ + OSDynLoad_Acquire("nn_aoc.rpl", &aoc_handle); +} + +void InitAocFunctionPointers(void) +{ + InitAcquireAoc(); + if(aoc_handle == 0) + return; + + //! assigning those is not mandatory and it does not always work to load them + OSDynLoad_FindExport(aoc_handle, 0, "AOC_Initialize", &AOC_Initialize); + OSDynLoad_FindExport(aoc_handle, 0, "AOC_Finalize", &AOC_Finalize); + OSDynLoad_FindExport(aoc_handle, 0, "AOC_CalculateWorkBufferSize", &AOC_CalculateWorkBufferSize); + OSDynLoad_FindExport(aoc_handle, 0, "AOC_ListTitle", &AOC_ListTitle); + OSDynLoad_FindExport(aoc_handle, 0, "AOC_OpenTitle", &AOC_OpenTitle); + OSDynLoad_FindExport(aoc_handle, 0, "AOC_CloseTitle", &AOC_CloseTitle); + OSDynLoad_FindExport(aoc_handle, 0, "AOC_DeleteContent", &AOC_DeleteContent); + OSDynLoad_FindExport(aoc_handle, 0, "AOC_GetPurchaseInfo", &AOC_GetPurchaseInfo); +} diff --git a/src/dynamic_libs/aoc_functions.h b/src/dynamic_libs/aoc_functions.h new file mode 100644 index 0000000..efca771 --- /dev/null +++ b/src/dynamic_libs/aoc_functions.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __AOC_FUNCTIONS_H_ +#define __AOC_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned int aoc_handle; + +#define AOC_TITLE_SIZE 104 + +typedef struct { + u64 title_ID; + u32 group_ID; + u16 version; + char path[88]; +} AOC_TitleListType; + + +void InitAocFunctionPointers(void); +void InitAcquireAoc(void); + +extern s32 (* AOC_Initialize)(void); +extern s32 (* AOC_Finalize)(void); +extern u32 (* AOC_CalculateWorkBufferSize)(u32 num_titles); +extern s32 (* AOC_ListTitle)(u32 * num_titles, void * titles, u32 max_titles, void * buffer, u32 buffer_size); +extern s32 (* AOC_OpenTitle)(char* aoc_path, void * title, void * buffer, u32 buffer_size); +extern s32 (* AOC_CloseTitle)(void * title); +extern s32 (* AOC_DeleteContent)(u64 title_id, u16 contentIndexes[], u32 numberOfContent, void * buffer, u32 buffer_size); +extern s32 (* AOC_GetPurchaseInfo)(u32 * bResult, u64 title_id, u16 contentIndexes[], u32 numberOfContent, void * buffer, u32 buffer_size); +#ifdef __cplusplus +} +#endif + +#endif // __AOC_FUNCTIONS_H_ diff --git a/src/dynamic_libs/ax_functions.c b/src/dynamic_libs/ax_functions.c new file mode 100644 index 0000000..e517f6d --- /dev/null +++ b/src/dynamic_libs/ax_functions.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "common/common.h" +#include "os_functions.h" +#include "ax_functions.h" + +unsigned int sound_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, AXInitWithParams, u32 * params); +EXPORT_DECL(void, AXInit, void); +EXPORT_DECL(void, AXQuit, void); +EXPORT_DECL(u32, AXGetInputSamplesPerSec, void); +EXPORT_DECL(u32, AXGetInputSamplesPerFrame, void); +EXPORT_DECL(s32, AXVoiceBegin, void *v); +EXPORT_DECL(s32, AXVoiceEnd, void *v); +EXPORT_DECL(void, AXSetVoiceType, void *v, u16 type); +EXPORT_DECL(void, AXSetVoiceOffsets, void *v, const void *buf); +EXPORT_DECL(void, AXSetVoiceSrcType, void *v, u32 type); +EXPORT_DECL(void, AXSetVoiceVe, void *v, const void *vol); +EXPORT_DECL(s32, AXSetVoiceDeviceMix, void *v, s32 device, u32 id, void *mix); +EXPORT_DECL(void, AXSetVoiceState, void *v, u16 state); +EXPORT_DECL(void, AXSetVoiceSrc, void *v, const void *src); +EXPORT_DECL(s32, AXSetVoiceSrcRatio, void *v,f32 ratio) +EXPORT_DECL(void *, AXAcquireVoice, u32 prio, void * callback, u32 arg); +EXPORT_DECL(void, AXFreeVoice, void *v); +EXPORT_DECL(void, AXRegisterFrameCallback, void * callback); +EXPORT_DECL(u32, AXGetVoiceLoopCount, void *v); +EXPORT_DECL(void, AXSetVoiceEndOffset, void *v, u32 offset); +EXPORT_DECL(void, AXSetVoiceLoopOffset, void *v, u32 offset); + +void InitAcquireAX(void) +{ + unsigned int *funcPointer = 0; + + if(OS_FIRMWARE >= 400) + { + AXInit = 0; + + OSDynLoad_Acquire("sndcore2.rpl", &sound_handle); + OS_FIND_EXPORT(sound_handle, AXInitWithParams); + OS_FIND_EXPORT(sound_handle, AXGetInputSamplesPerSec); + } + else + { + AXInitWithParams = 0; + AXGetInputSamplesPerSec = 0; + + OSDynLoad_Acquire("snd_core.rpl", &sound_handle); + OS_FIND_EXPORT(sound_handle, AXInit); + } +} + +void InitAXFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + + InitAcquireAX(); + + OS_FIND_EXPORT(sound_handle, AXQuit); + OS_FIND_EXPORT(sound_handle, AXVoiceBegin); + OS_FIND_EXPORT(sound_handle, AXVoiceEnd); + OS_FIND_EXPORT(sound_handle, AXSetVoiceType); + OS_FIND_EXPORT(sound_handle, AXSetVoiceOffsets); + OS_FIND_EXPORT(sound_handle, AXSetVoiceSrcType); + OS_FIND_EXPORT(sound_handle, AXSetVoiceVe); + OS_FIND_EXPORT(sound_handle, AXSetVoiceDeviceMix); + OS_FIND_EXPORT(sound_handle, AXSetVoiceState); + OS_FIND_EXPORT(sound_handle, AXSetVoiceSrc); + OS_FIND_EXPORT(sound_handle, AXSetVoiceSrcRatio); + OS_FIND_EXPORT(sound_handle, AXAcquireVoice); + OS_FIND_EXPORT(sound_handle, AXFreeVoice); + OS_FIND_EXPORT(sound_handle, AXRegisterFrameCallback); + OS_FIND_EXPORT(sound_handle, AXGetVoiceLoopCount); + OS_FIND_EXPORT(sound_handle, AXSetVoiceEndOffset); + OS_FIND_EXPORT(sound_handle, AXSetVoiceLoopOffset); +} + +void ProperlyEndTransitionAudio(void) +{ + bool (* check_os_audio_transition_flag_old)(void); + void (* AXInit_old)(void); + void (* AXQuit_old)(void); + + unsigned int *funcPointer = 0; + unsigned int sound_handle; + OSDynLoad_Acquire("snd_core.rpl", &sound_handle); + + OS_FIND_EXPORT_EX(sound_handle, check_os_audio_transition_flag, check_os_audio_transition_flag_old); + OS_FIND_EXPORT_EX(sound_handle, AXInit, AXInit_old); + OS_FIND_EXPORT_EX(sound_handle, AXQuit, AXQuit_old); + + if (check_os_audio_transition_flag_old()) + { + AXInit_old(); + AXQuit_old(); + } +} diff --git a/src/dynamic_libs/ax_functions.h b/src/dynamic_libs/ax_functions.h new file mode 100644 index 0000000..086346f --- /dev/null +++ b/src/dynamic_libs/ax_functions.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __AX_FUNCTIONS_H_ +#define __AX_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern unsigned int sound_handle; + +void InitAXFunctionPointers(void); +void InitAcquireAX(void); +void ProperlyEndTransitionAudio(void); + +extern void (* AXInitWithParams)(u32 * params); +extern void (* AXInit)(void); +extern void (* AXQuit)(void); +extern u32 (* AXGetInputSamplesPerSec)(void); +extern s32 (* AXVoiceBegin)(void *v); +extern s32 (* AXVoiceEnd)(void *v); +extern void (* AXSetVoiceType)(void *v, u16 type); +extern void (* AXSetVoiceOffsets)(void *v, const void *buf); +extern void (* AXSetVoiceSrcType)(void *v, u32 type); +extern void (* AXSetVoiceVe)(void *v, const void *vol); +extern s32 (* AXSetVoiceDeviceMix)(void *v, s32 device, u32 id, void *mix); +extern void (* AXSetVoiceState)(void *v, u16 state); +extern void (* AXSetVoiceSrc)(void *v, const void *src); +extern s32 (* AXSetVoiceSrcRatio)(void *v, f32 ratio); +extern void * (* AXAcquireVoice)(u32 prio, void * callback, u32 arg); +extern void (* AXFreeVoice)(void *v); +extern void (* AXRegisterFrameCallback)(void * callback); +extern u32 (* AXGetVoiceLoopCount)(void * v); +extern void (* AXSetVoiceEndOffset)(void * v, u32 offset); +extern void (* AXSetVoiceLoopOffset)(void * v, u32 offset); + +#ifdef __cplusplus +} +#endif + +#endif // __VPAD_FUNCTIONS_H_ diff --git a/src/dynamic_libs/curl_functions.c b/src/dynamic_libs/curl_functions.c new file mode 100644 index 0000000..d828cdb --- /dev/null +++ b/src/dynamic_libs/curl_functions.c @@ -0,0 +1,54 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "os_functions.h" +#include "curl_functions.h" + +unsigned int libcurl_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(CURLcode, n_curl_global_init, long flags); +EXPORT_DECL(CURL *, n_curl_easy_init, void); +EXPORT_DECL(CURLcode, n_curl_easy_setopt, CURL *curl, CURLoption option, ...); +EXPORT_DECL(CURLcode, n_curl_easy_perform, CURL *curl); +EXPORT_DECL(void, n_curl_easy_cleanup, CURL *curl); +EXPORT_DECL(CURLcode, n_curl_easy_getinfo, CURL *curl, CURLINFO info, ...); + +void InitAcquireCurl(void) +{ + OSDynLoad_Acquire("nlibcurl", &libcurl_handle); +} + +void InitCurlFunctionPointers(void) +{ + InitAcquireCurl(); + unsigned int *funcPointer = 0; + + OS_FIND_EXPORT_EX(libcurl_handle, curl_global_init, n_curl_global_init); + OS_FIND_EXPORT_EX(libcurl_handle, curl_easy_init, n_curl_easy_init); + OS_FIND_EXPORT_EX(libcurl_handle, curl_easy_setopt, n_curl_easy_setopt); + OS_FIND_EXPORT_EX(libcurl_handle, curl_easy_perform, n_curl_easy_perform); + OS_FIND_EXPORT_EX(libcurl_handle, curl_easy_cleanup, n_curl_easy_cleanup); + OS_FIND_EXPORT_EX(libcurl_handle, curl_easy_getinfo, n_curl_easy_getinfo); + + n_curl_global_init(CURL_GLOBAL_ALL); +} diff --git a/src/dynamic_libs/curl_functions.h b/src/dynamic_libs/curl_functions.h new file mode 100644 index 0000000..e40740b --- /dev/null +++ b/src/dynamic_libs/curl_functions.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __CURL_FUNCTIONS_H_ +#define __CURL_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "socket_functions.h" +typedef int socklen_t; +#include +#include + +void InitCurlFunctionPointers(void); +void InitAcquireCurl(void); + +extern CURLcode (* n_curl_global_init)(long flags); +extern CURL * (* n_curl_easy_init)(void); +extern CURLcode (* n_curl_easy_setopt)(CURL *curl, CURLoption option, ...); +extern CURLcode (* n_curl_easy_perform)(CURL *curl); +extern void (* n_curl_easy_cleanup)(CURL *curl); +extern CURLcode (* n_curl_easy_getinfo)(CURL *curl, CURLINFO info, ...); + +#ifdef __cplusplus +} +#endif + +#endif // __CURL_FUNCTIONS_H_ diff --git a/src/dynamic_libs/fs_defs.h b/src/dynamic_libs/fs_defs.h new file mode 100644 index 0000000..1b1bc41 --- /dev/null +++ b/src/dynamic_libs/fs_defs.h @@ -0,0 +1,61 @@ +#ifndef FS_DEFS_H +#define FS_DEFS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* FS defines and types */ +#define FS_MAX_LOCALPATH_SIZE 511 +#define FS_MAX_MOUNTPATH_SIZE 128 +#define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE) +#define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE + +#define FS_STATUS_OK 0 +#define FS_RET_UNSUPPORTED_CMD 0x0400 +#define FS_RET_NO_ERROR 0x0000 +#define FS_RET_ALL_ERROR (unsigned int)(-1) + +#define FS_STAT_FLAG_IS_DIRECTORY 0x80000000 + +/* max length of file/dir name */ +#define FS_MAX_ENTNAME_SIZE 256 + +#define FS_SOURCETYPE_EXTERNAL 0 +#define FS_SOURCETYPE_HFIO 1 + +#define FS_MOUNT_SOURCE_SIZE 0x300 +#define FS_CLIENT_SIZE 0x1700 +#define FS_CMD_BLOCK_SIZE 0xA80 + +typedef struct +{ + uint32_t flag; + uint32_t permission; + uint32_t owner_id; + uint32_t group_id; + uint32_t size; + uint32_t alloc_size; + uint64_t quota_size; + uint32_t ent_id; + uint64_t ctime; + uint64_t mtime; + uint8_t attributes[48]; +} __attribute__((packed)) FSStat; + +typedef struct +{ + FSStat stat; + char name[FS_MAX_ENTNAME_SIZE]; +} FSDirEntry; + + +#ifdef __cplusplus +} +#endif + +#endif /* FS_DEFS_H */ + diff --git a/src/dynamic_libs/fs_functions.c b/src/dynamic_libs/fs_functions.c new file mode 100644 index 0000000..08a4fb6 --- /dev/null +++ b/src/dynamic_libs/fs_functions.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "fs_functions.h" +#include "os_functions.h" + +EXPORT_DECL(int, FSInit, void); +EXPORT_DECL(int, FSShutdown, void); +EXPORT_DECL(int, FSAddClientEx, void *pClient, int unk_zero_param, int errHandling); +EXPORT_DECL(int, FSDelClient, void *pClient); +EXPORT_DECL(void, FSInitCmdBlock, void *pCmd); +EXPORT_DECL(int, FSGetMountSource, void *pClient, void *pCmd, int type, void *source, int errHandling); + +EXPORT_DECL(int, FSMount, void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int errHandling); +EXPORT_DECL(int, FSUnmount, void *pClient, void *pCmd, const char *target, int errHandling); + +EXPORT_DECL(int, FSGetStat, void *pClient, void *pCmd, const char *path, FSStat *stats, int errHandling); +EXPORT_DECL(int, FSGetStatAsync, void *pClient, void *pCmd, const char *path, void *stats, int error, void *asyncParams); +EXPORT_DECL(int, FSRename, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); +EXPORT_DECL(int, FSRenameAsync, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); +EXPORT_DECL(int, FSRemove, void *pClient, void *pCmd, const char *path, int error); +EXPORT_DECL(int, FSRemoveAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +EXPORT_DECL(int, FSFlushQuota, void *pClient, void *pCmd, const char* path, int error); +EXPORT_DECL(int, FSFlushQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +EXPORT_DECL(int, FSGetFreeSpaceSize, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error); +EXPORT_DECL(int, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams); +EXPORT_DECL(int, FSRollbackQuota, void *pClient, void *pCmd, const char *path, int error); +EXPORT_DECL(int, FSRollbackQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +EXPORT_DECL(int, FSOpenDir, void *pClient, void *pCmd, const char *path, int *dh, int errHandling); +EXPORT_DECL(int, FSOpenDirAsync, void *pClient, void* pCmd, const char *path, int *handle, int error, void *asyncParams); +EXPORT_DECL(int, FSReadDir, void *pClient, void *pCmd, int dh, FSDirEntry *dir_entry, int errHandling); +EXPORT_DECL(int, FSRewindDir, void *pClient, void *pCmd, int dh, int errHandling); +EXPORT_DECL(int, FSCloseDir, void *pClient, void *pCmd, int dh, int errHandling); +EXPORT_DECL(int, FSChangeDir, void *pClient, void *pCmd, const char *path, int errHandling); +EXPORT_DECL(int, FSChangeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +EXPORT_DECL(int, FSMakeDir, void *pClient, void *pCmd, const char *path, int errHandling); +EXPORT_DECL(int, FSMakeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +EXPORT_DECL(int, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling); +EXPORT_DECL(int, FSOpenFileAsync, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const void *asyncParams); +EXPORT_DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling); +EXPORT_DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int errHandling); + +EXPORT_DECL(int, FSFlushFile, void *pClient, void *pCmd, int fd, int error); +EXPORT_DECL(int, FSTruncateFile, void *pClient, void *pCmd, int fd, int error); +EXPORT_DECL(int, FSGetStatFile, void *pClient, void *pCmd, int fd, void *buffer, int error); +EXPORT_DECL(int, FSSetPosFile, void *pClient, void *pCmd, int fd, int pos, int error); +EXPORT_DECL(int, FSWriteFile, void *pClient, void *pCmd, const void *source, int block_size, int block_count, int fd, int flag, int error); + +EXPORT_DECL(int, FSBindMount, void *pClient, void *pCmd, char *source, char *target, int error); +EXPORT_DECL(int, FSBindUnmount, void *pClient, void *pCmd, char *target, int error); + +EXPORT_DECL(int, FSMakeQuota, void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling); +EXPORT_DECL(int, FSMakeQuotaAsync ,void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling,const void *asyncParams); + +void InitFSFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + + OS_FIND_EXPORT(coreinit_handle, FSInit); + OS_FIND_EXPORT(coreinit_handle, FSShutdown); + OS_FIND_EXPORT(coreinit_handle, FSAddClientEx); + OS_FIND_EXPORT(coreinit_handle, FSDelClient); + OS_FIND_EXPORT(coreinit_handle, FSInitCmdBlock); + OS_FIND_EXPORT(coreinit_handle, FSGetMountSource); + + OS_FIND_EXPORT(coreinit_handle, FSMount); + OS_FIND_EXPORT(coreinit_handle, FSUnmount); + + OS_FIND_EXPORT(coreinit_handle, FSGetStat); + OS_FIND_EXPORT(coreinit_handle, FSGetStatAsync); + OS_FIND_EXPORT(coreinit_handle, FSRename); + OS_FIND_EXPORT(coreinit_handle, FSRenameAsync); + OS_FIND_EXPORT(coreinit_handle, FSRemove); + OS_FIND_EXPORT(coreinit_handle, FSRemoveAsync); + OS_FIND_EXPORT(coreinit_handle, FSFlushQuota); + OS_FIND_EXPORT(coreinit_handle, FSFlushQuotaAsync); + OS_FIND_EXPORT(coreinit_handle, FSGetFreeSpaceSize); + OS_FIND_EXPORT(coreinit_handle, FSGetFreeSpaceSizeAsync); + OS_FIND_EXPORT(coreinit_handle, FSRollbackQuota); + OS_FIND_EXPORT(coreinit_handle, FSRollbackQuotaAsync); + + OS_FIND_EXPORT(coreinit_handle, FSOpenDir); + OS_FIND_EXPORT(coreinit_handle, FSOpenDirAsync); + OS_FIND_EXPORT(coreinit_handle, FSReadDir); + OS_FIND_EXPORT(coreinit_handle, FSRewindDir); + OS_FIND_EXPORT(coreinit_handle, FSCloseDir); + OS_FIND_EXPORT(coreinit_handle, FSChangeDir); + OS_FIND_EXPORT(coreinit_handle, FSChangeDirAsync); + OS_FIND_EXPORT(coreinit_handle, FSMakeDir); + OS_FIND_EXPORT(coreinit_handle, FSMakeDirAsync); + + + OS_FIND_EXPORT(coreinit_handle, FSOpenFile); + OS_FIND_EXPORT(coreinit_handle, FSOpenFileAsync); + OS_FIND_EXPORT(coreinit_handle, FSReadFile); + OS_FIND_EXPORT(coreinit_handle, FSCloseFile); + + OS_FIND_EXPORT(coreinit_handle, FSFlushFile); + OS_FIND_EXPORT(coreinit_handle, FSTruncateFile); + OS_FIND_EXPORT(coreinit_handle, FSGetStatFile); + OS_FIND_EXPORT(coreinit_handle, FSSetPosFile); + OS_FIND_EXPORT(coreinit_handle, FSWriteFile); + + OS_FIND_EXPORT(coreinit_handle, FSBindMount); + OS_FIND_EXPORT(coreinit_handle, FSBindUnmount); + + OS_FIND_EXPORT(coreinit_handle, FSMakeQuota); + OS_FIND_EXPORT(coreinit_handle, FSMakeQuotaAsync); +} diff --git a/src/dynamic_libs/fs_functions.h b/src/dynamic_libs/fs_functions.h new file mode 100644 index 0000000..d024655 --- /dev/null +++ b/src/dynamic_libs/fs_functions.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __FS_FUNCTIONS_H_ +#define __FS_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "fs_defs.h" + +void InitFSFunctionPointers(void); + +extern int (* FSInit)(void); +extern int (* FSShutdown)(void); +extern int (* FSAddClientEx)(void *pClient, int unk_zero_param, int errHandling); +extern int (* FSDelClient)(void *pClient); +extern void (* FSInitCmdBlock)(void *pCmd); +extern int (* FSGetMountSource)(void *pClient, void *pCmd, int type, void *source, int errHandling); + +extern int (* FSMount)(void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int errHandling); +extern int (* FSUnmount)(void *pClient, void *pCmd, const char *target, int errHandling); +extern int (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); +extern int (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); +extern int (* FSRemove)(void *pClient, void *pCmd, const char *path, int error); +extern int (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +extern int (* FSGetStat)(void *pClient, void *pCmd, const char *path, FSStat *stats, int errHandling); +extern int (* FSGetStatAsync)(void *pClient, void *pCmd, const char *path, void *stats, int error, void *asyncParams); +extern int (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error); +extern int (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams); +extern int (* FSRemove)(void *pClient, void *pCmd, const char *path, int error); +extern int (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +extern int (* FSFlushQuota)(void *pClient, void *pCmd, const char* path, int error); +extern int (* FSFlushQuotaAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +extern int (* FSGetFreeSpaceSize)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error); +extern int (* FSGetFreeSpaceSizeAsync)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams); +extern int (* FSRollbackQuota)(void *pClient, void *pCmd, const char *path, int error); +extern int (* FSRollbackQuotaAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +extern int (* FSOpenDir)(void *pClient, void *pCmd, const char *path, int *dh, int errHandling); +extern int (* FSOpenDirAsync)(void *pClient, void* pCmd, const char *path, int *handle, int error, void *asyncParams); +extern int (* FSReadDir)(void *pClient, void *pCmd, int dh, FSDirEntry *dir_entry, int errHandling); +extern int (* FSRewindDir)(void *pClient, void *pCmd, int dh, int errHandling); +extern int (* FSCloseDir)(void *pClient, void *pCmd, int dh, int errHandling); +extern int (* FSChangeDir)(void *pClient, void *pCmd, const char *path, int errHandling); +extern int (* FSChangeDirAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); +extern int (* FSMakeDir)(void *pClient, void *pCmd, const char *path, int errHandling); +extern int (* FSMakeDirAsync)(void *pClient, void *pCmd, const char *path, int error, void *asyncParams); + +extern int (* FSOpenFile)(void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling); +extern int (* FSOpenFileAsync)(void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const void *asyncParams); +extern int (* FSReadFile)(void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling); +extern int (* FSCloseFile)(void *pClient, void *pCmd, int fd, int errHandling); + +extern int (* FSFlushFile)(void *pClient, void *pCmd, int fd, int error); +extern int (* FSTruncateFile)(void *pClient, void *pCmd, int fd, int error); +extern int (* FSGetStatFile)(void *pClient, void *pCmd, int fd, void *buffer, int error); +extern int (* FSSetPosFile)(void *pClient, void *pCmd, int fd, int pos, int error); +extern int (* FSWriteFile)(void *pClient, void *pCmd, const void *source, int block_size, int block_count, int fd, int flag, int error); + +extern int (* FSBindMount)(void *pClient, void *pCmd, char *source, char *target, int error); +extern int (* FSBindUnmount)(void *pClient, void *pCmd, char *target, int error); + +extern int (* FSMakeQuota)( void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling); +extern int (* FSMakeQuotaAsync)(void *pClient, void *pCmd, const char *path,u32 mode, u64 size, int errHandling,const void *asyncParams); + + +#ifdef __cplusplus +} +#endif + +#endif // __FS_FUNCTIONS_H_ diff --git a/src/dynamic_libs/gx2_functions.c b/src/dynamic_libs/gx2_functions.c new file mode 100644 index 0000000..a34807e --- /dev/null +++ b/src/dynamic_libs/gx2_functions.c @@ -0,0 +1,173 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "os_functions.h" +#include "gx2_types.h" + +unsigned int gx2_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, GX2Init, u32 * init_attribs); +EXPORT_DECL(void, GX2Shutdown, void); +EXPORT_DECL(void, GX2Flush, void); +EXPORT_DECL(s32, GX2GetMainCoreId, void) ; +EXPORT_DECL(s32, GX2DrawDone, void); +EXPORT_DECL(void, GX2ClearColor, GX2ColorBuffer *colorBuffer, f32 r, f32 g, f32 b, f32 a); +EXPORT_DECL(void, GX2SetViewport, f32 x, f32 y, f32 w, f32 h, f32 nearZ, f32 farZ); +EXPORT_DECL(void, GX2SetScissor, u32 x_orig, u32 y_orig, u32 wd, u32 ht); +EXPORT_DECL(void, GX2SetContextState, const GX2ContextState* state); +EXPORT_DECL(void, GX2DrawEx, s32 primitive_type, u32 count, u32 first_vertex, u32 instances_count); +EXPORT_DECL(void, GX2DrawIndexedEx, s32 primitive_type, u32 count, s32 index_format, const void* idx, u32 first_vertex, u32 instances_count); +EXPORT_DECL(void, GX2ClearDepthStencilEx, GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value, s32 clear_mode); +EXPORT_DECL(void, GX2SetClearDepthStencil, GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value); +EXPORT_DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 scan_target); +EXPORT_DECL(void, GX2SwapScanBuffers, void); +EXPORT_DECL(void, GX2SetTVEnable, s32 enable); +EXPORT_DECL(void, GX2SetSwapInterval, u32 swap_interval); +EXPORT_DECL(u32, GX2GetSwapInterval, void); +EXPORT_DECL(void, GX2WaitForVsync, void); +EXPORT_DECL(void, GX2CalcTVSize, s32 tv_render_mode, s32 format, s32 buffering_mode, u32 * size, s32 * scale_needed); +EXPORT_DECL(void, GX2Invalidate, s32 invalidate_type, void * ptr, u32 buffer_size); +EXPORT_DECL(void, GX2SetTVBuffer, void *buffer, u32 buffer_size, s32 tv_render_mode, s32 format, s32 buffering_mode); +EXPORT_DECL(void, GX2CalcSurfaceSizeAndAlignment, GX2Surface *surface); +EXPORT_DECL(void, GX2InitDepthBufferRegs, GX2DepthBuffer *depthBuffer); +EXPORT_DECL(void, GX2InitColorBufferRegs, GX2ColorBuffer *colorBuffer); +EXPORT_DECL(void, GX2CalcColorBufferAuxInfo, GX2ColorBuffer *colorBuffer, u32 *size, u32 *align); +EXPORT_DECL(void, GX2CalcDepthBufferHiZInfo, GX2DepthBuffer *depthBuffer, u32 *size, u32 *align); +EXPORT_DECL(void, GX2InitDepthBufferHiZEnable, GX2DepthBuffer *depthBuffer, s32 hiZ_enable); +EXPORT_DECL(void, GX2SetupContextStateEx, GX2ContextState* state, s32 enable_profiling); +EXPORT_DECL(void, GX2SetColorBuffer, const GX2ColorBuffer *colorBuffer, s32 target); +EXPORT_DECL(void, GX2SetDepthBuffer, const GX2DepthBuffer *depthBuffer); +EXPORT_DECL(void, GX2SetAttribBuffer, u32 attr_index, u32 attr_size, u32 stride, const void* attr); +EXPORT_DECL(void, GX2InitTextureRegs, GX2Texture *texture); +EXPORT_DECL(void, GX2InitSampler, GX2Sampler *sampler, s32 tex_clamp, s32 min_mag_filter); +EXPORT_DECL(u32, GX2CalcFetchShaderSizeEx, u32 num_attrib, s32 fetch_shader_type, s32 tessellation_mode); +EXPORT_DECL(void, GX2InitFetchShaderEx, GX2FetchShader* fs, void* fs_buffer, u32 count, const GX2AttribStream* attribs, s32 fetch_shader_type, s32 tessellation_mode); +EXPORT_DECL(void, GX2SetFetchShader, const GX2FetchShader* fs); +EXPORT_DECL(void, GX2SetVertexUniformReg, u32 offset, u32 count, const void *values); +EXPORT_DECL(void, GX2SetPixelUniformReg, u32 offset, u32 count, const void *values); +EXPORT_DECL(void, GX2SetPixelTexture, const GX2Texture *texture, u32 texture_hw_location); +EXPORT_DECL(void, GX2SetVertexTexture, const GX2Texture *texture, u32 texture_hw_location); +EXPORT_DECL(void, GX2SetPixelSampler, const GX2Sampler *sampler, u32 sampler_hw_location); +EXPORT_DECL(void, GX2SetVertexSampler, const GX2Sampler *sampler, u32 sampler_hw_location); +EXPORT_DECL(void, GX2SetPixelShader, const GX2PixelShader* pixelShader); +EXPORT_DECL(void, GX2SetVertexShader, const GX2VertexShader* vertexShader); +EXPORT_DECL(void, GX2InitSamplerZMFilter, GX2Sampler *sampler, s32 z_filter, s32 mip_filter); +EXPORT_DECL(void, GX2SetColorControl, s32 lop, u8 blend_enable_mask, s32 enable_multi_write, s32 enable_color_buffer); +EXPORT_DECL(void, GX2SetDepthOnlyControl, s32 enable_depth, s32 enable_depth_write, s32 depth_comp_function); +EXPORT_DECL(void, GX2SetBlendControl, s32 target, s32 color_src_blend, s32 color_dst_blend, s32 color_combine, s32 separate_alpha_blend, s32 alpha_src_blend, s32 alpha_dst_blend, s32 alpha_combine); +EXPORT_DECL(void, GX2CalcDRCSize, s32 drc_mode, s32 format, s32 buffering_mode, u32 *size, s32 *scale_needed); +EXPORT_DECL(void, GX2SetDRCBuffer, void *buffer, u32 buffer_size, s32 drc_mode, s32 surface_format, s32 buffering_mode); +EXPORT_DECL(void, GX2SetDRCScale, u32 width, u32 height); +EXPORT_DECL(void, GX2SetDRCEnable, s32 enable); +EXPORT_DECL(void, GX2SetPolygonControl, s32 front_face_mode, s32 cull_front, s32 cull_back, s32 enable_mode, s32 mode_font, s32 mode_back, s32 poly_offset_front, s32 poly_offset_back, s32 point_line_offset); +EXPORT_DECL(void, GX2SetCullOnlyControl, s32 front_face_mode, s32 cull_front, s32 cull_back); +EXPORT_DECL(void, GX2SetDepthStencilControl, s32 enable_depth_test, s32 enable_depth_write, s32 depth_comp_function, s32 stencil_test_enable, s32 back_stencil_enable, + s32 font_stencil_func, s32 front_stencil_z_pass, s32 front_stencil_z_fail, s32 front_stencil_fail, + s32 back_stencil_func, s32 back_stencil_z_pass, s32 back_stencil_z_fail, s32 back_stencil_fail); +EXPORT_DECL(void, GX2SetStencilMask, u8 mask_front, u8 write_mask_front, u8 ref_front, u8 mask_back, u8 write_mask_back, u8 ref_back); +EXPORT_DECL(void, GX2SetLineWidth, f32 width); +EXPORT_DECL(void, GX2SetTVGamma, f32 val); +EXPORT_DECL(void, GX2SetDRCGamma, f32 gam); +EXPORT_DECL(s32, GX2GetSystemTVScanMode, void); +EXPORT_DECL(s32, GX2GetSystemDRCScanMode, void); +EXPORT_DECL(void, GX2RSetAllocator, void * (* allocFunc)(u32, u32, u32), void (* freeFunc)(u32, void*)); +EXPORT_DECL(void, GX2CopySurface, GX2Surface * srcSurface,u32 srcMip,u32 srcSlice,GX2Surface * dstSurface,u32 dstMip,u32 dstSlice ); + +EXPORT_DECL(void, GX2ClearBuffersEx, GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,f32 r, f32 g, f32 b, f32 a,f32 depthValue,u8 stencilValue,int clearFlags); + +void InitAcquireGX2(void) +{ + OSDynLoad_Acquire("gx2.rpl", &gx2_handle); +} + +void InitGX2FunctionPointers(void) +{ + unsigned int *funcPointer = 0; + InitAcquireGX2(); + + OS_FIND_EXPORT(gx2_handle, GX2Init); + OS_FIND_EXPORT(gx2_handle, GX2Shutdown); + OS_FIND_EXPORT(gx2_handle, GX2Flush); + OS_FIND_EXPORT(gx2_handle, GX2GetMainCoreId); + OS_FIND_EXPORT(gx2_handle, GX2DrawDone); + OS_FIND_EXPORT(gx2_handle, GX2ClearColor); + OS_FIND_EXPORT(gx2_handle, GX2SetViewport); + OS_FIND_EXPORT(gx2_handle, GX2SetScissor); + OS_FIND_EXPORT(gx2_handle, GX2SetContextState); + OS_FIND_EXPORT(gx2_handle, GX2DrawEx); + OS_FIND_EXPORT(gx2_handle, GX2DrawIndexedEx); + OS_FIND_EXPORT(gx2_handle, GX2ClearDepthStencilEx); + OS_FIND_EXPORT(gx2_handle, GX2CopyColorBufferToScanBuffer); + OS_FIND_EXPORT(gx2_handle, GX2SwapScanBuffers); + OS_FIND_EXPORT(gx2_handle, GX2SetTVEnable); + OS_FIND_EXPORT(gx2_handle, GX2SetSwapInterval); + OS_FIND_EXPORT(gx2_handle, GX2GetSwapInterval); + OS_FIND_EXPORT(gx2_handle, GX2WaitForVsync); + OS_FIND_EXPORT(gx2_handle, GX2CalcTVSize); + OS_FIND_EXPORT(gx2_handle, GX2Invalidate); + OS_FIND_EXPORT(gx2_handle, GX2SetTVBuffer); + OS_FIND_EXPORT(gx2_handle, GX2CalcSurfaceSizeAndAlignment); + OS_FIND_EXPORT(gx2_handle, GX2InitDepthBufferRegs); + OS_FIND_EXPORT(gx2_handle, GX2InitColorBufferRegs); + OS_FIND_EXPORT(gx2_handle, GX2CalcColorBufferAuxInfo); + OS_FIND_EXPORT(gx2_handle, GX2CalcDepthBufferHiZInfo); + OS_FIND_EXPORT(gx2_handle, GX2InitDepthBufferHiZEnable); + OS_FIND_EXPORT(gx2_handle, GX2SetupContextStateEx); + OS_FIND_EXPORT(gx2_handle, GX2SetColorBuffer); + OS_FIND_EXPORT(gx2_handle, GX2SetDepthBuffer); + OS_FIND_EXPORT(gx2_handle, GX2SetAttribBuffer); + OS_FIND_EXPORT(gx2_handle, GX2InitTextureRegs); + OS_FIND_EXPORT(gx2_handle, GX2InitSampler); + OS_FIND_EXPORT(gx2_handle, GX2CalcFetchShaderSizeEx); + OS_FIND_EXPORT(gx2_handle, GX2InitFetchShaderEx); + OS_FIND_EXPORT(gx2_handle, GX2SetFetchShader); + OS_FIND_EXPORT(gx2_handle, GX2SetVertexUniformReg); + OS_FIND_EXPORT(gx2_handle, GX2SetPixelUniformReg); + OS_FIND_EXPORT(gx2_handle, GX2SetPixelTexture); + OS_FIND_EXPORT(gx2_handle, GX2SetVertexTexture); + OS_FIND_EXPORT(gx2_handle, GX2SetPixelSampler); + OS_FIND_EXPORT(gx2_handle, GX2SetVertexSampler); + OS_FIND_EXPORT(gx2_handle, GX2SetPixelShader); + OS_FIND_EXPORT(gx2_handle, GX2SetVertexShader); + OS_FIND_EXPORT(gx2_handle, GX2InitSamplerZMFilter); + OS_FIND_EXPORT(gx2_handle, GX2SetColorControl); + OS_FIND_EXPORT(gx2_handle, GX2SetDepthOnlyControl); + OS_FIND_EXPORT(gx2_handle, GX2SetBlendControl); + OS_FIND_EXPORT(gx2_handle, GX2CalcDRCSize); + OS_FIND_EXPORT(gx2_handle, GX2SetDRCBuffer); + OS_FIND_EXPORT(gx2_handle, GX2SetDRCScale); + OS_FIND_EXPORT(gx2_handle, GX2SetDRCEnable); + OS_FIND_EXPORT(gx2_handle, GX2SetPolygonControl); + OS_FIND_EXPORT(gx2_handle, GX2SetCullOnlyControl); + OS_FIND_EXPORT(gx2_handle, GX2SetDepthStencilControl); + OS_FIND_EXPORT(gx2_handle, GX2SetStencilMask); + OS_FIND_EXPORT(gx2_handle, GX2SetLineWidth); + OS_FIND_EXPORT(gx2_handle, GX2SetDRCGamma); + OS_FIND_EXPORT(gx2_handle, GX2SetTVGamma); + OS_FIND_EXPORT(gx2_handle, GX2GetSystemTVScanMode); + OS_FIND_EXPORT(gx2_handle, GX2GetSystemDRCScanMode); + OS_FIND_EXPORT(gx2_handle, GX2RSetAllocator); + OS_FIND_EXPORT(gx2_handle, GX2CopySurface); + OS_FIND_EXPORT(gx2_handle, GX2ClearBuffersEx); + OS_FIND_EXPORT(gx2_handle, GX2SetClearDepthStencil); +} diff --git a/src/dynamic_libs/gx2_functions.h b/src/dynamic_libs/gx2_functions.h new file mode 100644 index 0000000..0b06826 --- /dev/null +++ b/src/dynamic_libs/gx2_functions.h @@ -0,0 +1,211 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __GX2_FUNCTIONS_H_ +#define __GX2_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gx2_types.h" + +extern unsigned int gx2_handle; + +void InitGX2FunctionPointers(void); +void InitAcquireGX2(void); + +extern void (* GX2Init)(u32 * init_attribs); +extern void (* GX2Shutdown)(void); +extern void (* GX2Flush)(void); +extern s32 (* GX2GetMainCoreId)(void) ; +extern s32 (* GX2DrawDone)(void); +extern void (* GX2ClearColor)(GX2ColorBuffer *colorBuffer, f32 r, f32 g, f32 b, f32 a); +extern void (* GX2SetViewport)(f32 x, f32 y, f32 w, f32 h, f32 nearZ, f32 farZ); +extern void (* GX2SetScissor)(u32 x_orig, u32 y_orig, u32 wd, u32 ht); +extern void (* GX2SetContextState)(const GX2ContextState* state); +extern void (* GX2DrawEx)(s32 primitive_type, u32 count, u32 first_vertex, u32 instances_count); +extern void (* GX2DrawIndexedEx)(s32 primitive_type, u32 count, s32 index_format, const void* idx, u32 first_vertex, u32 instances_count); +extern void (* GX2ClearDepthStencilEx)(GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value, s32 clear_mode); +extern void (* GX2SetClearDepthStencil)(GX2DepthBuffer *depthBuffer, f32 depth_value, u8 stencil_value); +extern void (* GX2CopyColorBufferToScanBuffer)(const GX2ColorBuffer *colorBuffer, s32 scan_target); +extern void (* GX2SwapScanBuffers)(void); +extern void (* GX2SetTVEnable)(s32 enable); +extern void (* GX2SetSwapInterval)(u32 swap_interval); +extern u32 (* GX2GetSwapInterval)(void); +extern void (* GX2WaitForVsync)(void); +extern void (* GX2CalcTVSize)(s32 tv_render_mode, s32 format, s32 buffering_mode, u32 * size, s32 * scale_needed); +extern void (* GX2Invalidate)(s32 invalidate_type, void * ptr, u32 buffer_size); +extern void (* GX2SetTVBuffer)(void *buffer, u32 buffer_size, s32 tv_render_mode, s32 format, s32 buffering_mode); +extern void (* GX2CalcSurfaceSizeAndAlignment)(GX2Surface *surface); +extern void (* GX2InitDepthBufferRegs)(GX2DepthBuffer *depthBuffer); +extern void (* GX2InitColorBufferRegs)(GX2ColorBuffer *colorBuffer); +extern void (* GX2CalcColorBufferAuxInfo)(GX2ColorBuffer *colorBuffer, u32 *size, u32 *align); +extern void (* GX2CalcDepthBufferHiZInfo)(GX2DepthBuffer *depthBuffer, u32 *size, u32 *align); +extern void (* GX2InitDepthBufferHiZEnable)(GX2DepthBuffer *depthBuffer, s32 hiZ_enable); +extern void (* GX2SetupContextStateEx)(GX2ContextState* state, s32 enable_profiling); +extern void (* GX2SetColorBuffer)(const GX2ColorBuffer *colorBuffer, s32 target); +extern void (* GX2SetDepthBuffer)(const GX2DepthBuffer *depthBuffer); +extern void (* GX2SetAttribBuffer)(u32 attr_index, u32 attr_size, u32 stride, const void* attr); +extern void (* GX2InitTextureRegs)(GX2Texture *texture); +extern void (* GX2InitSampler)(GX2Sampler *sampler, s32 tex_clamp, s32 min_mag_filter); +extern u32 (* GX2CalcFetchShaderSizeEx)(u32 num_attrib, s32 fetch_shader_type, s32 tessellation_mode); +extern void (* GX2InitFetchShaderEx)(GX2FetchShader* fs, void* fs_buffer, u32 count, const GX2AttribStream* attribs, s32 fetch_shader_type, s32 tessellation_mode); +extern void (* GX2SetFetchShader)(const GX2FetchShader* fs); +extern void (* GX2SetVertexUniformReg)(u32 offset, u32 count, const void *values); +extern void (* GX2SetPixelUniformReg)(u32 offset, u32 count, const void *values); +extern void (* GX2SetPixelTexture)(const GX2Texture *texture, u32 texture_hw_location); +extern void (* GX2SetVertexTexture)(const GX2Texture *texture, u32 texture_hw_location); +extern void (* GX2SetPixelSampler)(const GX2Sampler *sampler, u32 sampler_hw_location); +extern void (* GX2SetVertexSampler)(const GX2Sampler *sampler, u32 sampler_hw_location); +extern void (* GX2SetPixelShader)(const GX2PixelShader* pixelShader); +extern void (* GX2SetVertexShader)(const GX2VertexShader* vertexShader); +extern void (* GX2InitSamplerZMFilter)(GX2Sampler *sampler, s32 z_filter, s32 mip_filter); +extern void (* GX2SetColorControl)(s32 lop, u8 blend_enable_mask, s32 enable_multi_write, s32 enable_color_buffer); +extern void (* GX2SetDepthOnlyControl)(s32 enable_depth, s32 enable_depth_write, s32 depth_comp_function); +extern void (* GX2SetBlendControl)(s32 target, s32 color_src_blend, s32 color_dst_blend, s32 color_combine, s32 separate_alpha_blend, s32 alpha_src_blend, s32 alpha_dst_blend, s32 alpha_combine); +extern void (* GX2CalcDRCSize)(s32 drc_mode, s32 format, s32 buffering_mode, u32 *size, s32 *scale_needed); +extern void (* GX2SetDRCBuffer)(void *buffer, u32 buffer_size, s32 drc_mode, s32 surface_format, s32 buffering_mode); +extern void (* GX2SetDRCScale)(u32 width, u32 height); +extern void (* GX2SetDRCEnable)(s32 enable); +extern void (* GX2SetPolygonControl)(s32 front_face_mode, s32 cull_front, s32 cull_back, s32 enable_mode, s32 mode_font, s32 mode_back, s32 poly_offset_front, s32 poly_offset_back, s32 point_line_offset); +extern void (* GX2SetCullOnlyControl)(s32 front_face_mode, s32 cull_front, s32 cull_back); +extern void (* GX2SetDepthStencilControl)(s32 enable_depth_test, s32 enable_depth_write, s32 depth_comp_function, s32 stencil_test_enable, s32 back_stencil_enable, + s32 font_stencil_func, s32 front_stencil_z_pass, s32 front_stencil_z_fail, s32 front_stencil_fail, + s32 back_stencil_func, s32 back_stencil_z_pass, s32 back_stencil_z_fail, s32 back_stencil_fail); +extern void (* GX2SetStencilMask)(u8 mask_front, u8 write_mask_front, u8 ref_front, u8 mask_back, u8 write_mask_back, u8 ref_back); +extern void (* GX2SetLineWidth)(f32 width); +extern void (* GX2SetTVGamma)(f32 val); +extern void (* GX2SetDRCGamma)(f32 val); +extern s32 (* GX2GetSystemTVScanMode)(void); +extern s32 (* GX2GetSystemDRCScanMode)(void); +extern void (* GX2RSetAllocator)(void * (*allocFunc)(u32, u32, u32), void (*freeFunc)(u32, void*)); +extern void (* GX2CopySurface)(GX2Surface * srcSurface,u32 srcMip,u32 srcSlice,GX2Surface * dstSurface,u32 dstMip,u32 dstSlice ); +extern void (* GX2ClearBuffersEx)(GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,f32 r, f32 g, f32 b, f32 a,f32 depthValue,u8 stencilValue,int clearFlags); + +static inline void GX2InitDepthBuffer(GX2DepthBuffer *depthBuffer, s32 dimension, u32 width, u32 height, u32 depth, s32 format, s32 aa) +{ + depthBuffer->surface.dimension = dimension; + depthBuffer->surface.width = width; + depthBuffer->surface.height = height; + depthBuffer->surface.depth = depth; + depthBuffer->surface.num_mips = 1; + depthBuffer->surface.format = format; + depthBuffer->surface.aa = aa; + depthBuffer->surface.use = ((format==GX2_SURFACE_FORMAT_D_D24_S8_UNORM) || (format==GX2_SURFACE_FORMAT_D_D24_S8_FLOAT)) ? GX2_SURFACE_USE_DEPTH_BUFFER : GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE; + depthBuffer->surface.tile = GX2_TILE_MODE_DEFAULT; + depthBuffer->surface.swizzle = 0; + depthBuffer->view_mip = 0; + depthBuffer->view_first_slice = 0; + depthBuffer->view_slices_count = depth; + depthBuffer->clear_depth = 1.0f; + depthBuffer->clear_stencil = 0; + depthBuffer->hiZ_data = NULL; + depthBuffer->hiZ_size = 0; + GX2CalcSurfaceSizeAndAlignment(&depthBuffer->surface); + GX2InitDepthBufferRegs(depthBuffer); +} + +static inline void GX2InitColorBuffer(GX2ColorBuffer *colorBuffer, s32 dimension, u32 width, u32 height, u32 depth, s32 format, s32 aa) +{ + colorBuffer->surface.dimension = dimension; + colorBuffer->surface.width = width; + colorBuffer->surface.height = height; + colorBuffer->surface.depth = depth; + colorBuffer->surface.num_mips = 1; + colorBuffer->surface.format = format; + colorBuffer->surface.aa = aa; + colorBuffer->surface.use = GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE_FTV; + colorBuffer->surface.image_size = 0; + colorBuffer->surface.image_data = NULL; + colorBuffer->surface.mip_size = 0; + colorBuffer->surface.mip_data = NULL; + colorBuffer->surface.tile = GX2_TILE_MODE_DEFAULT; + colorBuffer->surface.swizzle = 0; + colorBuffer->surface.align = 0; + colorBuffer->surface.pitch = 0; + u32 i; + for(i = 0; i < 13; i++) + colorBuffer->surface.mip_offset[i] = 0; + colorBuffer->view_mip = 0; + colorBuffer->view_first_slice = 0; + colorBuffer->view_slices_count = depth; + colorBuffer->aux_data = NULL; + colorBuffer->aux_size = 0; + for(i = 0; i < 5; i++) + colorBuffer->regs[i] = 0; + + GX2CalcSurfaceSizeAndAlignment(&colorBuffer->surface); + GX2InitColorBufferRegs(colorBuffer); +} + +static inline void GX2InitAttribStream(GX2AttribStream* attr, u32 location, u32 buffer, u32 offset, s32 format) +{ + attr->location = location; + attr->buffer = buffer; + attr->offset = offset; + attr->format = format; + attr->index_type = 0; + attr->divisor = 0; + attr->destination_selector = attribute_dest_comp_selector[format & 0xff]; + attr->endian_swap = GX2_ENDIANSWAP_DEFAULT; +} + +static inline void GX2InitTexture(GX2Texture *tex, u32 width, u32 height, u32 depth, u32 num_mips, s32 format, s32 dimension, s32 tile) +{ + tex->surface.dimension = dimension; + tex->surface.width = width; + tex->surface.height = height; + tex->surface.depth = depth; + tex->surface.num_mips = num_mips; + tex->surface.format = format; + tex->surface.aa = GX2_AA_MODE_1X; + tex->surface.use = GX2_SURFACE_USE_TEXTURE; + tex->surface.image_size = 0; + tex->surface.image_data = NULL; + tex->surface.mip_size = 0; + tex->surface.mip_data = NULL; + tex->surface.tile = tile; + tex->surface.swizzle = 0; + tex->surface.align = 0; + tex->surface.pitch = 0; + u32 i; + for(i = 0; i < 13; i++) + tex->surface.mip_offset[i] = 0; + tex->view_first_mip = 0; + tex->view_mips_count = num_mips; + tex->view_first_slice = 0; + tex->view_slices_count = depth; + tex->component_selector = texture_comp_selector[format & 0x3f]; + for(i = 0; i < 5; i++) + tex->regs[i] = 0; + + GX2CalcSurfaceSizeAndAlignment(&tex->surface); + GX2InitTextureRegs(tex); +} + +#ifdef __cplusplus +} +#endif + +#endif // __GX2_FUNCTIONS_H_ diff --git a/src/dynamic_libs/gx2_types.h b/src/dynamic_libs/gx2_types.h new file mode 100644 index 0000000..e292318 --- /dev/null +++ b/src/dynamic_libs/gx2_types.h @@ -0,0 +1,699 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef _GX2_TYPES_H_ +#define _GX2_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +//!----------------------------------------------------------------------------------------------------------------------- +//! Constants +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_COMMAND_BUFFER_SIZE 0x400000 +#define GX2_SCAN_BUFFER_ALIGNMENT 0x1000 +#define GX2_SHADER_ALIGNMENT 0x100 +#define GX2_CONTEXT_STATE_ALIGNMENT 0x100 +#define GX2_DISPLAY_LIST_ALIGNMENT 0x20 +#define GX2_VERTEX_BUFFER_ALIGNMENT 0x40 +#define GX2_INDEX_BUFFER_ALIGNMENT 0x20 + +#define GX2_CONTEXT_STATE_SIZE 0xA100 + +#define GX2_AUX_BUFFER_CLEAR_VALUE 0xCC + +//!----------------------------------------------------------------------------------------------------------------------- +//! Common +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_FALSE 0 +#define GX2_TRUE 1 +#define GX2_DISABLE 0 +#define GX2_ENABLE 1 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2InitAttrib +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_INIT_ATTRIB_NULL 0 +#define GX2_INIT_ATTRIB_CB_BASE 1 +#define GX2_INIT_ATTRIB_CB_SIZE 2 +#define GX2_INIT_ATTRIB_ARGC 7 +#define GX2_INIT_ATTRIB_ARGV 8 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 compare functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_COMPARE_NEVER 0 +#define GX2_COMPARE_LESS 1 +#define GX2_COMPARE_EQUAL 2 +#define GX2_COMPARE_LEQUAL 3 +#define GX2_COMPARE_GREATER 4 +#define GX2_COMPARE_NOTEQUAL 5 +#define GX2_COMPARE_GEQUAL 6 +#define GX2_COMPARE_ALWAYS 7 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 stencil functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_STENCIL_KEEP 0 +#define GX2_STENCIL_ZERO 1 +#define GX2_STENCIL_REPLACE 2 +#define GX2_STENCIL_INCR 3 +#define GX2_STENCIL_DECR 4 +#define GX2_STENCIL_INVERT 5 +#define GX2_STENCIL_INCR_WRAP 6 +#define GX2_STENCIL_DECR_WRAP 7 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 logic op functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_LOGIC_OP_CLEAR 0x00 +#define GX2_LOGIC_OP_NOR 0x11 +#define GX2_LOGIC_OP_INVAND 0x22 +#define GX2_LOGIC_OP_INVCOPY 0x33 +#define GX2_LOGIC_OP_REVAND 0x44 +#define GX2_LOGIC_OP_INV 0x55 +#define GX2_LOGIC_OP_XOR 0x66 +#define GX2_LOGIC_OP_NAND 0x77 +#define GX2_LOGIC_OP_AND 0x88 +#define GX2_LOGIC_OP_EQUIV 0x99 +#define GX2_LOGIC_OP_NOOP 0xAA +#define GX2_LOGIC_OP_INVOR 0xBB +#define GX2_LOGIC_OP_COPY 0xCC +#define GX2_LOGIC_OP_REVOR 0xDD +#define GX2_LOGIC_OP_OR 0xEE +#define GX2_LOGIC_OP_SET 0xFF + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 blend combination functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_BLEND_COMBINE_ADD 0x00 +#define GX2_BLEND_COMBINE_SRC_MINUS_DST 0x01 +#define GX2_BLEND_COMBINE_MIN 0x02 +#define GX2_BLEND_COMBINE_MAX 0x03 +#define GX2_BLEND_COMBINE_DST_MINUS_SRC 0x04 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 blend functions +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_BLEND_ZERO 0x00 +#define GX2_BLEND_ONE 0x01 +#define GX2_BLEND_SRC_ALPHA 0x04 +#define GX2_BLEND_ONE_MINUS_SRC_ALPHA 0x05 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 render targets +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_RENDER_TARGET_0 0 +#define GX2_RENDER_TARGET_1 1 +#define GX2_RENDER_TARGET_2 2 +#define GX2_RENDER_TARGET_3 3 +#define GX2_RENDER_TARGET_4 4 +#define GX2_RENDER_TARGET_5 5 +#define GX2_RENDER_TARGET_6 6 +#define GX2_RENDER_TARGET_7 7 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 cull modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_FRONT_FACE_CCW 0 +#define GX2_FRONT_FACE_CW 1 +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 polygon modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_POLYGON_MODE_POINT 0 +#define GX2_POLYGON_MODE_LINE 1 +#define GX2_POLYGON_MODE_TRIANGLE 2 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 special states +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SPECIAL_STATE_CLEAR 0 +#define GX2_SPECIAL_STATE_CLEAR_HIZ 1 +#define GX2_SPECIAL_STATE_COPY 2 +#define GX2_SPECIAL_STATE_EXPAND_COLOR 3 +#define GX2_SPECIAL_STATE_EXPAND_DEPTH 4 +#define GX2_SPECIAL_STATE_CONVERT_DEPTH 5 +#define GX2_SPECIAL_STATE_CONVERT_AADEPTH 6 +#define GX2_SPECIAL_STATE_RESOLVE_COLOR 7 +#define GX2_SPECIAL_STATE_CLEAR_COLOR_AS_DEPTH 8 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 attribute formats +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_ATTRIB_FORMAT_8_UNORM 0x00000000 +#define GX2_ATTRIB_FORMAT_4_4_UNORM 0x00000001 +#define GX2_ATTRIB_FORMAT_16_UNORM 0x00000002 +#define GX2_ATTRIB_FORMAT_8_8_UNORM 0x00000004 +#define GX2_ATTRIB_FORMAT_16_16_UNORM 0x00000007 +#define GX2_ATTRIB_FORMAT_8_8_8_8_UNORM 0x0000000A +#define GX2_ATTRIB_FORMAT_10_10_10_2_UNORM 0x0000000B +#define GX2_ATTRIB_FORMAT_16_16_16_16_UNORM 0x0000000E + +#define GX2_ATTRIB_FORMAT_8_UINT 0x00000100 +#define GX2_ATTRIB_FORMAT_16_UINT 0x00000102 +#define GX2_ATTRIB_FORMAT_8_8_UINT 0x00000104 +#define GX2_ATTRIB_FORMAT_32_UINT 0x00000105 +#define GX2_ATTRIB_FORMAT_16_16_UINT 0x00000107 +#define GX2_ATTRIB_FORMAT_8_8_8_8_UINT 0x0000010A +#define GX2_ATTRIB_FORMAT_10_10_10_2_UINT 0x0000010B +#define GX2_ATTRIB_FORMAT_32_32_UINT 0x0000010C +#define GX2_ATTRIB_FORMAT_16_16_16_16_UINT 0x0000010E +#define GX2_ATTRIB_FORMAT_32_32_32_UINT 0x00000110 +#define GX2_ATTRIB_FORMAT_32_32_32_32_UINT 0x00000112 + +#define GX2_ATTRIB_FORMAT_8_SNORM 0x00000200 +#define GX2_ATTRIB_FORMAT_16_SNORM 0x00000202 +#define GX2_ATTRIB_FORMAT_8_8_SNORM 0x00000204 +#define GX2_ATTRIB_FORMAT_16_16_SNORM 0x00000207 +#define GX2_ATTRIB_FORMAT_8_8_8_8_SNORM 0x0000020A +#define GX2_ATTRIB_FORMAT_10_10_10_2_SNORM 0x0000020B +#define GX2_ATTRIB_FORMAT_16_16_16_16_SNORM 0x0000020E + +#define GX2_ATTRIB_FORMAT_8_SINT 0x00000300 +#define GX2_ATTRIB_FORMAT_16_SINT 0x00000303 +#define GX2_ATTRIB_FORMAT_8_8_SINT 0x00000304 +#define GX2_ATTRIB_FORMAT_32_SINT 0x00000305 +#define GX2_ATTRIB_FORMAT_16_16_SINT 0x00000307 +#define GX2_ATTRIB_FORMAT_8_8_8_8_SINT 0x0000030A +#define GX2_ATTRIB_FORMAT_10_10_10_2_SINT 0x0000030B +#define GX2_ATTRIB_FORMAT_32_32_SINT 0x0000030C +#define GX2_ATTRIB_FORMAT_16_16_16_16_SINT 0x0000030E +#define GX2_ATTRIB_FORMAT_32_32_32_SINT 0x00000310 +#define GX2_ATTRIB_FORMAT_32_32_32_32_SINT 0x00000312 + +#define GX2_ATTRIB_FORMAT_8_UINT_TO_FLOAT 0x00000800 +#define GX2_ATTRIB_FORMAT_16_UINT_TO_FLOAT 0x00000802 +#define GX2_ATTRIB_FORMAT_16_FLOAT 0x00000803 +#define GX2_ATTRIB_FORMAT_8_8_UINT_TO_FLOAT 0x00000804 +#define GX2_ATTRIB_FORMAT_32_FLOAT 0x00000806 +#define GX2_ATTRIB_FORMAT_16_16_UINT_TO_FLOAT 0x00000807 +#define GX2_ATTRIB_FORMAT_16_16_FLOAT 0x00000808 +#define GX2_ATTRIB_FORMAT_10_11_11_FLOAT 0x00000809 +#define GX2_ATTRIB_FORMAT_8_8_8_8_UINT_TO_FLOAT 0x0000080A +#define GX2_ATTRIB_FORMAT_32_32_FLOAT 0x0000080D +#define GX2_ATTRIB_FORMAT_16_16_16_16_UINT_TO_FLOAT 0x0000080E +#define GX2_ATTRIB_FORMAT_16_16_16_16_FLOAT 0x0000080F +#define GX2_ATTRIB_FORMAT_32_32_32_FLOAT 0x00000811 +#define GX2_ATTRIB_FORMAT_32_32_32_32_FLOAT 0x00000813 + +#define GX2_ATTRIB_FORMAT_8_SINT_TO_FLOAT 0x00000A00 +#define GX2_ATTRIB_FORMAT_16_SINT_TO_FLOAT 0x00000A02 +#define GX2_ATTRIB_FORMAT_8_8_SINT_TO_FLOAT 0x00000A04 +#define GX2_ATTRIB_FORMAT_16_16_SINT_TO_FLOAT 0x00000A07 +#define GX2_ATTRIB_FORMAT_8_8_8_8_SINT_TO_FLOAT 0x00000A0A +#define GX2_ATTRIB_FORMAT_16_16_16_16_SINT_TO_FLOAT 0x00000A0E + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 shader modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SHADER_MODE_UNIFORM_REGISTER 0 +#define GX2_SHADER_MODE_UNIFORM_BLOCK 1 +#define GX2_SHADER_MODE_GEOMETRY_SHADER 2 +#define GX2_SHADER_MODE_COMPUTE_SHADER 3 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 shader modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_COMP_SEL_NONE 0x04040405 +#define GX2_COMP_SEL_X001 0x00040405 +#define GX2_COMP_SEL_XY01 0x00010405 +#define GX2_COMP_SEL_XYZ1 0x00010205 +#define GX2_COMP_SEL_XYZW 0x00010203 +#define GX2_COMP_SEL_XXXX 0x00000000 +#define GX2_COMP_SEL_YYYY 0x01010101 +#define GX2_COMP_SEL_ZZZZ 0x02020202 +#define GX2_COMP_SEL_WWWW 0x03030303 +#define GX2_COMP_SEL_WZYX 0x03020100 +#define GX2_COMP_SEL_WXYZ 0x03000102 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 variable types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_VAR_TYPE_VOID 0 +#define GX2_VAR_TYPE_BOOL 1 +#define GX2_VAR_TYPE_INT 2 +#define GX2_VAR_TYPE_UINT 3 +#define GX2_VAR_TYPE_FLOAT 4 +#define GX2_VAR_TYPE_DOUBLE 5 +#define GX2_VAR_TYPE_VEC2 9 +#define GX2_VAR_TYPE_VEC3 10 +#define GX2_VAR_TYPE_VEC4 11 +#define GX2_VAR_TYPE_MAT2 21 +#define GX2_VAR_TYPE_MAT3 25 +#define GX2_VAR_TYPE_MAT4 29 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 sample types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SAMPLER_TYPE_2D 1 + + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 index formats +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_INDEX_FORMAT_U16 4 +#define GX2_INDEX_FORMAT_U32 9 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 primitive types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_PRIMITIVE_POINTS 0x01 +#define GX2_PRIMITIVE_LINES 0x02 +#define GX2_PRIMITIVE_LINE_STRIP 0x03 +#define GX2_PRIMITIVE_TRIANGLES 0x04 +#define GX2_PRIMITIVE_TRIANGLE_FAN 0x05 +#define GX2_PRIMITIVE_TRIANGLE_STRIP 0x06 +#define GX2_PRIMITIVE_RECTS 0x11 +#define GX2_PRIMITIVE_QUADS 0x13 +#define GX2_PRIMITIVE_QUAD_STRIP 0x14 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 clear modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_CLEAR_DEPTH 0x01 +#define GX2_CLEAR_STENCIL 0x02 +#define GX2_CLEAR_BOTH (GX2_CLEAR_DEPTH | GX2_CLEAR_STENCIL) + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 surface formats +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SURFACE_FORMAT_TC_R8_UNORM 0x00000001 +#define GX2_SURFACE_FORMAT_T_R4_G4_UNORM 0x00000002 +#define GX2_SURFACE_FORMAT_TCD_R16_UNORM 0x00000005 +#define GX2_SURFACE_FORMAT_TC_R8_G8_UNORM 0x00000007 +#define GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM 0x00000008 +#define GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM 0x0000000a +#define GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM 0x0000000b +#define GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM 0x0000000c +#define GX2_SURFACE_FORMAT_TC_R16_G16_UNORM 0x0000000f +#define GX2_SURFACE_FORMAT_D_D24_S8_UNORM 0x00000011 +#define GX2_SURFACE_FORMAT_T_R24_UNORM_X8 0x00000011 +#define GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM 0x00000019 +#define GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM 0x0000001a +#define GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM 0x0000001b +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM 0x0000001f +#define GX2_SURFACE_FORMAT_T_BC1_UNORM 0x00000031 +#define GX2_SURFACE_FORMAT_T_BC2_UNORM 0x00000032 +#define GX2_SURFACE_FORMAT_T_BC3_UNORM 0x00000033 +#define GX2_SURFACE_FORMAT_T_BC4_UNORM 0x00000034 +#define GX2_SURFACE_FORMAT_T_BC5_UNORM 0x00000035 +#define GX2_SURFACE_FORMAT_T_NV12_UNORM 0x00000081 + +#define GX2_SURFACE_FORMAT_TC_R8_UINT 0x00000101 +#define GX2_SURFACE_FORMAT_TC_R16_UINT 0x00000105 +#define GX2_SURFACE_FORMAT_TC_R8_G8_UINT 0x00000107 +#define GX2_SURFACE_FORMAT_TC_R32_UINT 0x0000010d +#define GX2_SURFACE_FORMAT_TC_R16_G16_UINT 0x0000010f +#define GX2_SURFACE_FORMAT_T_X24_G8_UINT 0x00000111 +#define GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT 0x00000119 +#define GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT 0x0000011a +#define GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT 0x0000011b +#define GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24 0x0000011c +#define GX2_SURFACE_FORMAT_TC_R32_G32_UINT 0x0000011d +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT 0x0000011f +#define GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT 0x00000122 + +#define GX2_SURFACE_FORMAT_TC_R8_SNORM 0x00000201 +#define GX2_SURFACE_FORMAT_TC_R16_SNORM 0x00000205 +#define GX2_SURFACE_FORMAT_TC_R8_G8_SNORM 0x00000207 +#define GX2_SURFACE_FORMAT_TC_R16_G16_SNORM 0x0000020f +#define GX2_SURFACE_FORMAT_T_R10_G10_B10_A2_SNORM 0x00000219 +#define GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SNORM 0x00000219 +#define GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM 0x0000021a +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM 0x0000021f +#define GX2_SURFACE_FORMAT_T_BC4_SNORM 0x00000234 +#define GX2_SURFACE_FORMAT_T_BC5_SNORM 0x00000235 + +#define GX2_SURFACE_FORMAT_TC_R8_SINT 0x00000301 +#define GX2_SURFACE_FORMAT_TC_R16_SINT 0x00000305 +#define GX2_SURFACE_FORMAT_TC_R8_G8_SINT 0x00000307 +#define GX2_SURFACE_FORMAT_TC_R32_SINT 0x0000030d +#define GX2_SURFACE_FORMAT_TC_R16_G16_SINT 0x0000030f +#define GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SINT 0x00000319 +#define GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT 0x0000031a +#define GX2_SURFACE_FORMAT_TC_R32_G32_SINT 0x0000031d +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT 0x0000031f +#define GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT 0x00000322 + +#define GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB 0x0000041a +#define GX2_SURFACE_FORMAT_T_BC1_SRGB 0x00000431 +#define GX2_SURFACE_FORMAT_T_BC2_SRGB 0x00000432 +#define GX2_SURFACE_FORMAT_T_BC3_SRGB 0x00000433 + +#define GX2_SURFACE_FORMAT_TC_R16_FLOAT 0x00000806 +#define GX2_SURFACE_FORMAT_TCD_R32_FLOAT 0x0000080e +#define GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT 0x00000810 +#define GX2_SURFACE_FORMAT_D_D24_S8_FLOAT 0x00000811 +#define GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT 0x00000816 +#define GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24 0x0000081c +#define GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24 0x0000081c +#define GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT 0x0000081e +#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT 0x00000820 +#define GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT 0x00000823 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 tile modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TILE_MODE_DEFAULT 0x00000000 +#define GX2_TILE_MODE_LINEAR_ALIGNED 0x00000001 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 surface use +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SURFACE_USE_TEXTURE 0x00000001 +#define GX2_SURFACE_USE_COLOR_BUFFER 0x00000002 +#define GX2_SURFACE_USE_DEPTH_BUFFER 0x00000004 +#define GX2_SURFACE_USE_SCAN_BUFFER 0x00000008 +#define GX2_SURFACE_USE_FTV 0x80000000 +#define GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_TEXTURE) +#define GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE (GX2_SURFACE_USE_DEPTH_BUFFER | GX2_SURFACE_USE_TEXTURE) +#define GX2_SURFACE_USE_COLOR_BUFFER_FTV (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_FTV) +#define GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE_FTV (GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE | GX2_SURFACE_USE_FTV) + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 surface dim +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SURFACE_DIM_1D 0x00000000 +#define GX2_SURFACE_DIM_2D 0x00000001 +#define GX2_SURFACE_DIM_3D 0x00000002 +#define GX2_SURFACE_DIM_CUBE 0x00000003 +#define GX2_SURFACE_DIM_1D_ARRAY 0x00000004 +#define GX2_SURFACE_DIM_2D_ARRAY 0x00000005 +#define GX2_SURFACE_DIM_2D_MSAA 0x00000006 +#define GX2_SURFACE_DIM_2D_MSAA_ARRAY 0x00000007 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 AA modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_AA_MODE_1X 0x00000000 +#define GX2_AA_MODE_2X 0x00000001 +#define GX2_AA_MODE_4X 0x00000002 +#define GX2_AA_MODE_8X 0x00000003 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 texture clamp +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TEX_CLAMP_WRAP 0x00000000 +#define GX2_TEX_CLAMP_MIRROR 0x00000001 +#define GX2_TEX_CLAMP_CLAMP 0x00000002 +#define GX2_TEX_CLAMP_MIRROR_ONCE 0x00000003 +#define GX2_TEX_CLAMP_CLAMP_HALF_BORDER 0x00000004 +#define GX2_TEX_CLAMP_MIRROR_ONCE_HALF_BORDER 0x00000005 +#define GX2_TEX_CLAMP_CLAMP_BORDER 0x00000006 +#define GX2_TEX_CLAMP_MIRROR_ONCE_BORDER 0x00000007 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 texture filter +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TEX_XY_FILTER_POINT 0x00000000 +#define GX2_TEX_XY_FILTER_BILINEAR 0x00000001 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 TV scan modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TV_SCAN_MODE_NONE 0x00000000 +#define GX2_TV_SCAN_MODE_576I 0x00000001 +#define GX2_TV_SCAN_MODE_480I 0x00000002 +#define GX2_TV_SCAN_MODE_480P 0x00000003 +#define GX2_TV_SCAN_MODE_720P 0x00000004 +#define GX2_TV_SCAN_MODE_1080I 0x00000006 +#define GX2_TV_SCAN_MODE_1080P 0x00000007 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 TV render modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TV_RENDER_480_NARROW 0x00000001 +#define GX2_TV_RENDER_480_WIDE 0x00000002 +#define GX2_TV_RENDER_720 0x00000003 +#define GX2_TV_RENDER_1080 0x00000005 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 DRC render modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_DRC_NONE 0x00000000 +#define GX2_DRC_SINGLE 0x00000001 +#define GX2_DRC_DOUBLE 0x00000002 +#define GX2_DRC_SINGLE_30HZ 0x00000004 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 buffering mode +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_BUFFERING_SINGLE 0x00000001 +#define GX2_BUFFERING_DOUBLE 0x00000002 +#define GX2_BUFFERING_TRIPLE 0x00000003 +#define GX2_BUFFERING_QUAD +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 scan targets +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_SCAN_TARGET_TV 0x00000001 +#define GX2_SCAN_TARGET_DRC_FIRST 0x00000004 +#define GX2_SCAN_TARGET_DRC_SECOND 0x00000008 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 invalidate types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_INVALIDATE_ATTRIB_BUFFER 0x00000001 +#define GX2_INVALIDATE_TEXTURE 0x00000002 +#define GX2_INVALIDATE_UNIFORM_BLOCK 0x00000004 +#define GX2_INVALIDATE_SHADER 0x00000008 +#define GX2_INVALIDATE_COLOR_BUFFER 0x00000010 +#define GX2_INVALIDATE_DEPTH_BUFFER 0x00000020 +#define GX2_INVALIDATE_CPU 0x00000040 +#define GX2_INVALIDATE_CPU_ATTRIB_BUFFER (GX2_INVALIDATE_CPU | GX2_INVALIDATE_ATTRIB_BUFFER) +#define GX2_INVALIDATE_CPU_TEXTURE (GX2_INVALIDATE_CPU | GX2_INVALIDATE_TEXTURE) +#define GX2_INVALIDATE_CPU_UNIFORM_BLOCK (GX2_INVALIDATE_CPU | GX2_INVALIDATE_UNIFORM_BLOCK) +#define GX2_INVALIDATE_CPU_SHADER (GX2_INVALIDATE_CPU | GX2_INVALIDATE_SHADER) + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 swap modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_ENDIANSWAP_DEFAULT 0x00000003 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 tessellation modes +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_TESSELLATION_MODE_DISCRETE 0x00000000 +#define GX2_TESSELLATION_MODE_CONTINUOUS 0x00000001 +#define GX2_TESSELLATION_MODE_ADAPTIVE 0x00000002 + +//!----------------------------------------------------------------------------------------------------------------------- +//! GX2 fetch shader types +//!----------------------------------------------------------------------------------------------------------------------- +#define GX2_FETCH_SHADER_TESSELATION_NONE 0x00000000 +#define GX2_FETCH_SHADER_TESSELATION_LINES 0x00000001 +#define GX2_FETCH_SHADER_TESSELATION_TRIANGLES 0x00000002 +#define GX2_FETCH_SHADER_TESSELATION_QUADS 0x00000003 + + +typedef struct _GX2ContextState { + u8 data[GX2_CONTEXT_STATE_SIZE]; +} GX2ContextState; + +typedef struct _GX2Surface { + s32 dimension; + u32 width; + u32 height; + u32 depth; + u32 num_mips; + s32 format; + s32 aa; + s32 use; + u32 image_size; + void *image_data; + u32 mip_size; + void *mip_data; + s32 tile; + u32 swizzle; + u32 align; + u32 pitch; + u32 mip_offset[13]; +} GX2Surface; + +typedef struct _GX2ColorBuffer { + GX2Surface surface; + u32 view_mip; + u32 view_first_slice; + u32 view_slices_count; + void *aux_data; + u32 aux_size; + u32 regs[5]; +} GX2ColorBuffer; + +typedef struct _GX2DepthBuffer { + GX2Surface surface; + u32 view_mip; + u32 view_first_slice; + u32 view_slices_count; + void *hiZ_data; + u32 hiZ_size; + f32 clear_depth; + u32 clear_stencil; + u32 regs[7]; +} GX2DepthBuffer; + + +typedef struct _GX2Texture { + GX2Surface surface; + u32 view_first_mip; + u32 view_mips_count; + u32 view_first_slice; + u32 view_slices_count; + u32 component_selector; + u32 regs[5]; +} GX2Texture; + + +typedef struct _GX2Sampler { + u32 regs[3]; +} GX2Sampler; + +typedef struct _GX2AttribStream { + u32 location; + u32 buffer; + u32 offset; + s32 format; + s32 index_type; + u32 divisor; + u32 destination_selector; + s32 endian_swap; +} GX2AttribStream; + +typedef struct _GX2FetchShader { + s32 type; + u32 reg; + u32 shader_size; + void *shader_program; + u32 attributes_count; + u32 divisor[3]; +} GX2FetchShader; + +typedef struct _GX2AttribVar +{ + const char *name; + s32 var_type; + u32 array_count; + u32 location; +} GX2AttribVar; + + +typedef struct _GX2UniformBlock { + const char *name; + u32 location; + u32 block_size; +} GX2UniformBlock; + +typedef struct _GX2UniformInitialValue { + f32 value[4]; + u32 offset; +} GX2UniformInitialValue; + +typedef struct _GX2SamplerVar +{ + const char *name; + s32 sampler_type; + u32 location; +} GX2SamplerVar; + +typedef struct _GX2UniformVar +{ + const char *name; + s32 var_type; + u32 array_count; + u32 offset; + u32 block_index; +} GX2UniformVar; + +typedef struct _GX2VertexShader { + u32 regs[52]; + u32 shader_size; + void *shader_data; + s32 shader_mode; + u32 uniform_blocks_count; + GX2UniformBlock *uniform_block; + u32 uniform_vars_count; + GX2UniformVar *uniform_var; + u32 initial_values_count; + GX2UniformInitialValue *initial_value; + u32 loops_count; + void *loops_data; + u32 sampler_vars_count; + GX2SamplerVar *sampler_var; + u32 attribute_vars_count; + GX2AttribVar *attribute_var; + u32 data[6]; + u32 shader_program_buffer[16]; +} GX2VertexShader; + +typedef struct _GX2PixelShader { + u32 regs[41]; + u32 shader_size; + void *shader_data; + s32 shader_mode; + u32 uniform_blocks_count; + GX2UniformBlock *uniform_block; + u32 uniform_vars_count; + GX2UniformVar *uniform_var; + u32 initial_values_count; + GX2UniformInitialValue *initial_value; + u32 loops_count; + void *loops_data; + u32 sampler_vars_count; + GX2SamplerVar *sampler_var; + u32 shader_program_buffer[16]; +} GX2PixelShader; + +static const u32 attribute_dest_comp_selector[20] = { + GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_X001, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_X001, + GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, + GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZ1, + GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW +}; + +static const u32 texture_comp_selector[54] = { + GX2_COMP_SEL_NONE, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_X001, + GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, + GX2_COMP_SEL_WZYX, GX2_COMP_SEL_X001, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, GX2_COMP_SEL_NONE, + GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_NONE, + GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_WZYX, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, + GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, + GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_X001, + GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZ1, + GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01 +}; + +typedef struct _GX2Color { + u8 r, g, b, a; +} GX2Color; + +typedef struct _GX2ColorF32 { + f32 r, g, b, a; +} GX2ColorF32; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/dynamic_libs/os_functions.c b/src/dynamic_libs/os_functions.c new file mode 100644 index 0000000..734e2e5 --- /dev/null +++ b/src/dynamic_libs/os_functions.c @@ -0,0 +1,326 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "common/common.h" +#include "os_functions.h" + +unsigned int coreinit_handle __attribute__((section(".data"))) = 0; + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Lib handle functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, OSDynLoad_Acquire, const char* rpl, u32 *handle); +EXPORT_DECL(int, OSDynLoad_FindExport, u32 handle, int isdata, const char *symbol, void *address); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Security functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, OSGetSecurityLevel, void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Thread functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, OSCreateThread, void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); +EXPORT_DECL(int, OSResumeThread, void *thread); +EXPORT_DECL(int, OSSuspendThread, void *thread); +EXPORT_DECL(int, OSIsThreadTerminated, void *thread); +EXPORT_DECL(int, OSIsThreadSuspended, void *thread); +EXPORT_DECL(int, OSSetThreadPriority, void * thread, int priority); +EXPORT_DECL(int, OSJoinThread, void * thread, int * ret_val); +EXPORT_DECL(void, OSDetachThread, void * thread); +EXPORT_DECL(void, OSSleepTicks, u64 ticks); +EXPORT_DECL(u64, OSGetTick, void); +EXPORT_DECL(u64, OSGetTime, void); +EXPORT_DECL(void, OSTicksToCalendarTime, u64 time, OSCalendarTime * calendarTime); + + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Mutex functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(void, OSInitMutex, void* mutex); +EXPORT_DECL(void, OSLockMutex, void* mutex); +EXPORT_DECL(void, OSUnlockMutex, void* mutex); +EXPORT_DECL(int, OSTryLockMutex, void* mutex); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! System functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(u64, OSGetTitleID, void); +EXPORT_DECL(void, OSGetArgcArgv, int* argc, char*** argv); +EXPORT_DECL(void, __Exit, void); +EXPORT_DECL(void, OSFatal, const char* msg); +EXPORT_DECL(void, OSSetExceptionCallback, u8 exceptionType, exception_callback newCallback); +EXPORT_DECL(void, DCFlushRange, const void *addr, u32 length); +EXPORT_DECL(void, ICInvalidateRange, const void *addr, u32 length); +EXPORT_DECL(void*, OSEffectiveToPhysical, const void*); +EXPORT_DECL(int, __os_snprintf, char* s, int n, const char * format, ...); +EXPORT_DECL(int *, __gh_errno_ptr, void); + +EXPORT_DECL(void, OSScreenInit, void); +EXPORT_DECL(unsigned int, OSScreenGetBufferSizeEx, unsigned int bufferNum); +EXPORT_DECL(int, OSScreenSetBufferEx, unsigned int bufferNum, void * addr); +EXPORT_DECL(int, OSScreenClearBufferEx, unsigned int bufferNum, unsigned int temp); +EXPORT_DECL(int, OSScreenFlipBuffersEx, unsigned int bufferNum); +EXPORT_DECL(int, OSScreenPutFontEx, unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer); +EXPORT_DECL(int, OSScreenEnableEx, unsigned int bufferNum, int enable); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Memory functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_VAR(unsigned int *, pMEMAllocFromDefaultHeapEx); +EXPORT_VAR(unsigned int *, pMEMAllocFromDefaultHeap); +EXPORT_VAR(unsigned int *, pMEMFreeToDefaultHeap); + +EXPORT_DECL(int, MEMGetBaseHeapHandle, int mem_arena); +EXPORT_DECL(unsigned int, MEMGetAllocatableSizeForFrmHeapEx, int heap, int align); +EXPORT_DECL(void *, MEMAllocFromFrmHeapEx, int heap, unsigned int size, int align); +EXPORT_DECL(void, MEMFreeToFrmHeap, int heap, int mode); +EXPORT_DECL(void *, MEMAllocFromExpHeapEx, int heap, unsigned int size, int align); +EXPORT_DECL(int , MEMCreateExpHeapEx, void* address, unsigned int size, unsigned short flags); +EXPORT_DECL(void *, MEMDestroyExpHeap, int heap); +EXPORT_DECL(void, MEMFreeToExpHeap, int heap, void* ptr); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! MCP functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, MCP_Open, void); +EXPORT_DECL(int, MCP_Close, int handle); +EXPORT_DECL(int, MCP_GetOwnTitleInfo, int handle, void * data); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Loader functions (not real rpl) +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, LiWaitIopComplete, int unknown_syscall_arg_r3, int * remaining_bytes); +EXPORT_DECL(int, LiWaitIopCompleteWithInterrupts, int unknown_syscall_arg_r3, int * remaining_bytes); +EXPORT_DECL(void, addr_LiWaitOneChunk, void); +EXPORT_DECL(void, addr_sgIsLoadingBuffer, void); +EXPORT_DECL(void, addr_gDynloadInitialized, void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Kernel function addresses +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(void, addr_PrepareTitle_hook, void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Other function addresses +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(void, DCInvalidateRange, void *buffer, uint32_t length); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Energy Saver functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//Burn-in Reduction +EXPORT_DECL(int, IMEnableDim,void); +EXPORT_DECL(int, IMDisableDim,void); +EXPORT_DECL(int, IMIsDimEnabled,int * result); +//Auto power down +EXPORT_DECL(int, IMEnableAPD,void); +EXPORT_DECL(int, IMDisableAPD,void); +EXPORT_DECL(int, IMIsAPDEnabled,int * result); +EXPORT_DECL(int, IMIsAPDEnabledBySysSettings,int * result); + +void InitAcquireOS(void) +{ + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Lib handle functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + EXPORT_FUNC_WRITE(OSDynLoad_Acquire, (int (*)(const char*, unsigned *))OS_SPECIFICS->addr_OSDynLoad_Acquire); + EXPORT_FUNC_WRITE(OSDynLoad_FindExport, (int (*)(u32, int, const char *, void *))OS_SPECIFICS->addr_OSDynLoad_FindExport); + + OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); +} + +void InitOSFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + + InitAcquireOS(); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Security functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSGetSecurityLevel); + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! System functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSFatal); + OS_FIND_EXPORT(coreinit_handle, OSGetTitleID); + OS_FIND_EXPORT(coreinit_handle, OSGetArgcArgv); + OS_FIND_EXPORT(coreinit_handle, OSSetExceptionCallback); + OS_FIND_EXPORT(coreinit_handle, DCFlushRange); + OS_FIND_EXPORT(coreinit_handle, ICInvalidateRange); + OS_FIND_EXPORT(coreinit_handle, OSEffectiveToPhysical); + OS_FIND_EXPORT(coreinit_handle, __os_snprintf); + OS_FIND_EXPORT(coreinit_handle, __gh_errno_ptr); + + OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &__Exit); + + OS_FIND_EXPORT(coreinit_handle, OSScreenInit); + OS_FIND_EXPORT(coreinit_handle, OSScreenGetBufferSizeEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenSetBufferEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenClearBufferEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenFlipBuffersEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenPutFontEx); + OS_FIND_EXPORT(coreinit_handle, OSScreenEnableEx); + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Thread functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSCreateThread); + OS_FIND_EXPORT(coreinit_handle, OSResumeThread); + OS_FIND_EXPORT(coreinit_handle, OSSuspendThread); + OS_FIND_EXPORT(coreinit_handle, OSIsThreadTerminated); + OS_FIND_EXPORT(coreinit_handle, OSIsThreadSuspended); + OS_FIND_EXPORT(coreinit_handle, OSJoinThread); + OS_FIND_EXPORT(coreinit_handle, OSSetThreadPriority); + OS_FIND_EXPORT(coreinit_handle, OSDetachThread); + OS_FIND_EXPORT(coreinit_handle, OSSleepTicks); + OS_FIND_EXPORT(coreinit_handle, OSGetTick); + OS_FIND_EXPORT(coreinit_handle, OSGetTime); + OS_FIND_EXPORT(coreinit_handle, OSTicksToCalendarTime); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Mutex functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSInitMutex); + OS_FIND_EXPORT(coreinit_handle, OSLockMutex); + OS_FIND_EXPORT(coreinit_handle, OSUnlockMutex); + OS_FIND_EXPORT(coreinit_handle, OSTryLockMutex); + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! MCP functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, MCP_Open); + OS_FIND_EXPORT(coreinit_handle, MCP_Close); + OS_FIND_EXPORT(coreinit_handle, MCP_GetOwnTitleInfo); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Memory functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeapEx", &pMEMAllocFromDefaultHeapEx); + OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeap", &pMEMAllocFromDefaultHeap); + OSDynLoad_FindExport(coreinit_handle, 1, "MEMFreeToDefaultHeap", &pMEMFreeToDefaultHeap); + + OS_FIND_EXPORT(coreinit_handle, MEMGetBaseHeapHandle); + OS_FIND_EXPORT(coreinit_handle, MEMGetAllocatableSizeForFrmHeapEx); + OS_FIND_EXPORT(coreinit_handle, MEMAllocFromFrmHeapEx); + OS_FIND_EXPORT(coreinit_handle, MEMFreeToFrmHeap); + OS_FIND_EXPORT(coreinit_handle, MEMAllocFromExpHeapEx); + OS_FIND_EXPORT(coreinit_handle, MEMCreateExpHeapEx); + OS_FIND_EXPORT(coreinit_handle, MEMDestroyExpHeap); + OS_FIND_EXPORT(coreinit_handle, MEMFreeToExpHeap); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Other function addresses + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, DCInvalidateRange); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Energy Saver functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //Burn-in Reduction + OS_FIND_EXPORT(coreinit_handle, IMEnableDim); + OS_FIND_EXPORT(coreinit_handle, IMDisableDim); + OS_FIND_EXPORT(coreinit_handle, IMIsDimEnabled); + //Auto power down + OS_FIND_EXPORT(coreinit_handle, IMEnableAPD); + OS_FIND_EXPORT(coreinit_handle, IMDisableAPD); + OS_FIND_EXPORT(coreinit_handle, IMIsAPDEnabled); + OS_FIND_EXPORT(coreinit_handle, IMIsAPDEnabledBySysSettings); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Special non library functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + if(OS_FIRMWARE == 532 || OS_FIRMWARE == 540) + { + EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100FFA4); // loader.elf + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100FE90); // loader.elf + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007EC); // loader.elf + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF18558); // kernel.elf + + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19D00); // loader.elf + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13C3C); // loader.elf + } + else if(OS_FIRMWARE == 500 || OS_FIRMWARE == 510) + { + EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100FBC4); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100FAB0); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007EC); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF18534); + + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19D00); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13C3C); + } + else if(OS_FIRMWARE == 410) + { + EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100F78C); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100F678); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007F8); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF166DC); + + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19CC0); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13BFC); + } + else if(OS_FIRMWARE == 400) //same for 402 and 403 + { + EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100F78C); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100F678); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010007F8); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF15E70); + + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19CC0); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13BFC); + } + else if(OS_FIRMWARE == 550) + { + EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x01010180); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0101006C); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x0100080C); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF184E4); + + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19E80); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE13DBC); + } + else if(OS_FIRMWARE == 310) + { + EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100C4E4); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100C3D4); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010004D8); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF15A0C); + + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19340); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE1329C); + } + else if(OS_FIRMWARE == 300) + { + EXPORT_FUNC_WRITE(LiWaitIopComplete, (int (*)(int, int *))0x0100C4E4); + EXPORT_FUNC_WRITE(LiWaitIopCompleteWithInterrupts, (int (*)(int, int *))0x0100C3D4); + EXPORT_FUNC_WRITE(addr_LiWaitOneChunk, (int (*)(int, int *))0x010004D8); + EXPORT_FUNC_WRITE(addr_PrepareTitle_hook, (int (*)(int, int *))0xFFF15974); + + EXPORT_FUNC_WRITE(addr_sgIsLoadingBuffer, (int (*)(int, int *))0xEFE19340); + EXPORT_FUNC_WRITE(addr_gDynloadInitialized, (int (*)(int, int *))0xEFE1329C); + } + else + { + OSFatal("Missing all OS specific addresses."); + } +} diff --git a/src/dynamic_libs/os_functions.h b/src/dynamic_libs/os_functions.h new file mode 100644 index 0000000..347da67 --- /dev/null +++ b/src/dynamic_libs/os_functions.h @@ -0,0 +1,174 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __OS_FUNCTIONS_H_ +#define __OS_FUNCTIONS_H_ + +#include +#include "common/os_defs.h" +#include "os_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BUS_SPEED 248625000 +#define SECS_TO_TICKS(sec) (((unsigned long long)(sec)) * (BUS_SPEED/4)) +#define MILLISECS_TO_TICKS(msec) (SECS_TO_TICKS(msec) / 1000) +#define MICROSECS_TO_TICKS(usec) (SECS_TO_TICKS(usec) / 1000000) + +#define usleep(usecs) OSSleepTicks(MICROSECS_TO_TICKS(usecs)) +#define sleep(secs) OSSleepTicks(SECS_TO_TICKS(secs)) + +#define FLUSH_DATA_BLOCK(addr) asm volatile("dcbf 0, %0; sync" : : "r"(((addr) & ~31))) +#define INVAL_DATA_BLOCK(addr) asm volatile("dcbi 0, %0; sync" : : "r"(((addr) & ~31))) + +#define EXPORT_DECL(res, func, ...) res (* func)(__VA_ARGS__) __attribute__((section(".data"))) = 0; +#define EXPORT_VAR(type, var) type var __attribute__((section(".data"))); + + +#define EXPORT_FUNC_WRITE(func, val) *(u32*)(((u32)&func) + 0) = (u32)val + +#define OS_FIND_EXPORT(handle, func) funcPointer = 0; \ + OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ + if(!funcPointer) \ + OSFatal("Function " # func " is NULL"); \ + EXPORT_FUNC_WRITE(func, funcPointer); + +#define OS_FIND_EXPORT_EX(handle, func, func_p) \ + funcPointer = 0; \ + OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ + if(!funcPointer) \ + OSFatal("Function " # func " is NULL"); \ + EXPORT_FUNC_WRITE(func_p, funcPointer); + +#define OS_MUTEX_SIZE 44 + +/* Handle for coreinit */ +extern unsigned int coreinit_handle; +void InitOSFunctionPointers(void); +void InitAcquireOS(void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Lib handle functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* OSDynLoad_Acquire)(const char* rpl, u32 *handle); +extern int (* OSDynLoad_FindExport)(u32 handle, int isdata, const char *symbol, void *address); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Security functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* OSGetSecurityLevel)(void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Thread functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* OSCreateThread)(void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); +extern int (* OSResumeThread)(void *thread); +extern int (* OSSuspendThread)(void *thread); +extern int (* OSIsThreadTerminated)(void *thread); +extern int (* OSIsThreadSuspended)(void *thread); +extern int (* OSJoinThread)(void * thread, int * ret_val); +extern int (* OSSetThreadPriority)(void * thread, int priority); +extern void (* OSDetachThread)(void * thread); +extern void (* OSSleepTicks)(u64 ticks); +extern u64 (* OSGetTick)(void); +extern u64 (* OSGetTime)(void); +extern void (*OSTicksToCalendarTime)(u64 time, OSCalendarTime *calendarTime); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Mutex functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern void (* OSInitMutex)(void* mutex); +extern void (* OSLockMutex)(void* mutex); +extern void (* OSUnlockMutex)(void* mutex); +extern int (* OSTryLockMutex)(void* mutex); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! System functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern u64 (* OSGetTitleID)(void); +extern void (* OSGetArgcArgv)(int* argc, char*** argv); +extern void (* __Exit)(void); +extern void (* OSFatal)(const char* msg); +extern void (* DCFlushRange)(const void *addr, u32 length); +extern void (* ICInvalidateRange)(const void *addr, u32 length); +extern void* (* OSEffectiveToPhysical)(const void*); +extern int (* __os_snprintf)(char* s, int n, const char * format, ...); +extern int * (* __gh_errno_ptr)(void); + +extern void (*OSScreenInit)(void); +extern unsigned int (*OSScreenGetBufferSizeEx)(unsigned int bufferNum); +extern int (*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr); +extern int (*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp); +extern int (*OSScreenFlipBuffersEx)(unsigned int bufferNum); +extern int (*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer); +extern int (*OSScreenEnableEx)(unsigned int bufferNum, int enable); + +typedef unsigned char (*exception_callback)(void * interruptedContext); +extern void (* OSSetExceptionCallback)(u8 exceptionType, exception_callback newCallback); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! MCP functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* MCP_Open)(void); +extern int (* MCP_Close)(int handle); +extern int (* MCP_GetOwnTitleInfo)(int handle, void * data); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! LOADER functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* LiWaitIopComplete)(int unknown_syscall_arg_r3, int * remaining_bytes); +extern int (* LiWaitIopCompleteWithInterrupts)(int unknown_syscall_arg_r3, int * remaining_bytes); +extern void (* addr_LiWaitOneChunk)(void); +extern void (* addr_sgIsLoadingBuffer)(void); +extern void (* addr_gDynloadInitialized)(void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Kernel function addresses +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern void (* addr_PrepareTitle_hook)(void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Other function addresses +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern void (*DCInvalidateRange)(void *buffer, uint32_t length); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Energy Saver functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +////Burn-in Reduction +extern int (*IMEnableDim)(void); +extern int (*IMDisableDim)(void); +extern int (*IMIsDimEnabled)(int * result); +//Auto power down +extern int (*IMEnableAPD)(void); +extern int (*IMDisableAPD)(void); +extern int (*IMIsAPDEnabled)(int * result); +extern int (*IMIsAPDEnabledBySysSettings)(int * result); + +#ifdef __cplusplus +} +#endif + +#endif // __OS_FUNCTIONS_H_ diff --git a/src/dynamic_libs/os_types.h b/src/dynamic_libs/os_types.h new file mode 100644 index 0000000..aaa18fe --- /dev/null +++ b/src/dynamic_libs/os_types.h @@ -0,0 +1,27 @@ +#ifndef _OS_TYPES_H_ +#define _OS_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct _OSCalendarTime { + int sec; + int min; + int hour; + int mday; + int mon; + int year; + int wday; + int yday; + int msec; + int usec; +} OSCalendarTime; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/dynamic_libs/padscore_functions.c b/src/dynamic_libs/padscore_functions.c new file mode 100644 index 0000000..f7ca8e9 --- /dev/null +++ b/src/dynamic_libs/padscore_functions.c @@ -0,0 +1,61 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "os_functions.h" +#include "padscore_functions.h" + +unsigned int padscore_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, KPADInit, void); +EXPORT_DECL(void, WPADInit, void); +EXPORT_DECL(s32, WPADProbe, s32 chan, u32 * pad_type); +EXPORT_DECL(s32, WPADSetDataFormat, s32 chan, s32 format); +EXPORT_DECL(void, WPADEnableURCC, s32 enable); +EXPORT_DECL(void, WPADRead, s32 chan, void * data); +EXPORT_DECL(s32, KPADRead, s32 chan, void * data, u32 size); +EXPORT_DECL(void,WPADSetAutoSleepTime,u8 minute); +EXPORT_DECL(void,WPADDisconnect,s32 chan); + +void InitAcquirePadScore(void) +{ + OSDynLoad_Acquire("padscore.rpl", &padscore_handle); +} + +void InitPadScoreFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + InitAcquirePadScore(); + + OS_FIND_EXPORT(padscore_handle, WPADInit); + OS_FIND_EXPORT(padscore_handle, KPADInit); + OS_FIND_EXPORT(padscore_handle, WPADProbe); + OS_FIND_EXPORT(padscore_handle, WPADSetDataFormat); + OS_FIND_EXPORT(padscore_handle, WPADEnableURCC); + OS_FIND_EXPORT(padscore_handle, WPADRead); + OS_FIND_EXPORT(padscore_handle, KPADRead); + OS_FIND_EXPORT(padscore_handle, WPADSetAutoSleepTime); + OS_FIND_EXPORT(padscore_handle, WPADDisconnect); + + KPADInit(); + WPADEnableURCC(1); +} diff --git a/src/dynamic_libs/padscore_functions.h b/src/dynamic_libs/padscore_functions.h new file mode 100644 index 0000000..5b000b1 --- /dev/null +++ b/src/dynamic_libs/padscore_functions.h @@ -0,0 +1,171 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __PAD_SCORE_FUNCTIONS_H_ +#define __PAD_SCORE_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "dynamic_libs/vpad_functions.h" + +extern unsigned int padscore_handle; + +#include + +#define WPAD_BUTTON_LEFT 0x0001 +#define WPAD_BUTTON_RIGHT 0x0002 +#define WPAD_BUTTON_DOWN 0x0004 +#define WPAD_BUTTON_UP 0x0008 +#define WPAD_BUTTON_PLUS 0x0010 +#define WPAD_BUTTON_2 0x0100 +#define WPAD_BUTTON_1 0x0200 +#define WPAD_BUTTON_B 0x0400 +#define WPAD_BUTTON_A 0x0800 +#define WPAD_BUTTON_MINUS 0x1000 +#define WPAD_BUTTON_Z 0x2000 +#define WPAD_BUTTON_C 0x4000 +#define WPAD_BUTTON_HOME 0x8000 + +#define WPAD_CLASSIC_BUTTON_UP 0x0001 +#define WPAD_CLASSIC_BUTTON_LEFT 0x0002 +#define WPAD_CLASSIC_BUTTON_ZR 0x0004 +#define WPAD_CLASSIC_BUTTON_X 0x0008 +#define WPAD_CLASSIC_BUTTON_A 0x0010 +#define WPAD_CLASSIC_BUTTON_Y 0x0020 +#define WPAD_CLASSIC_BUTTON_B 0x0040 +#define WPAD_CLASSIC_BUTTON_ZL 0x0080 +#define WPAD_CLASSIC_BUTTON_R 0x0200 +#define WPAD_CLASSIC_BUTTON_PLUS 0x0400 +#define WPAD_CLASSIC_BUTTON_HOME 0x0800 +#define WPAD_CLASSIC_BUTTON_MINUS 0x1000 +#define WPAD_CLASSIC_BUTTON_L 0x2000 +#define WPAD_CLASSIC_BUTTON_DOWN 0x4000 +#define WPAD_CLASSIC_BUTTON_RIGHT 0x8000 + +#define WPAD_PRO_BUTTON_UP 0x00000001 +#define WPAD_PRO_BUTTON_LEFT 0x00000002 +#define WPAD_PRO_TRIGGER_ZR 0x00000004 +#define WPAD_PRO_BUTTON_X 0x00000008 +#define WPAD_PRO_BUTTON_A 0x00000010 +#define WPAD_PRO_BUTTON_Y 0x00000020 +#define WPAD_PRO_BUTTON_B 0x00000040 +#define WPAD_PRO_TRIGGER_ZL 0x00000080 +#define WPAD_PRO_RESERVED 0x00000100 +#define WPAD_PRO_TRIGGER_R 0x00000200 +#define WPAD_PRO_BUTTON_PLUS 0x00000400 +#define WPAD_PRO_BUTTON_HOME 0x00000800 +#define WPAD_PRO_BUTTON_MINUS 0x00001000 +#define WPAD_PRO_TRIGGER_L 0x00002000 +#define WPAD_PRO_BUTTON_DOWN 0x00004000 +#define WPAD_PRO_BUTTON_RIGHT 0x00008000 +#define WPAD_PRO_BUTTON_STICK_R 0x00010000 +#define WPAD_PRO_BUTTON_STICK_L 0x00020000 + +#define WPAD_PRO_STICK_L_EMULATION_UP 0x00200000 +#define WPAD_PRO_STICK_L_EMULATION_DOWN 0x00100000 +#define WPAD_PRO_STICK_L_EMULATION_LEFT 0x00040000 +#define WPAD_PRO_STICK_L_EMULATION_RIGHT 0x00080000 + +#define WPAD_PRO_STICK_R_EMULATION_UP 0x02000000 +#define WPAD_PRO_STICK_R_EMULATION_DOWN 0x01000000 +#define WPAD_PRO_STICK_R_EMULATION_LEFT 0x00400000 +#define WPAD_PRO_STICK_R_EMULATION_RIGHT 0x00800000 + +typedef struct _KPADData +{ + u32 btns_h; + u32 btns_d; + u32 btns_r; + u32 unused_1[5]; + f32 pos_x; + f32 pos_y; + u32 unused_2[3]; + f32 angle_x; + f32 angle_y; + u32 unused_3[8]; + u8 device_type; + u8 wpad_error; + u8 pos_valid; + u8 format; + + union + { + struct + { + f32 stick_x; + f32 stick_y; + } nunchuck; + + struct + { + u32 btns_h; + u32 btns_d; + u32 btns_r; + f32 lstick_x; + f32 lstick_y; + f32 rstick_x; + f32 rstick_y; + f32 ltrigger; + f32 rtrigger; + } classic; + + struct + { + u32 btns_h; + u32 btns_d; + u32 btns_r; + f32 lstick_x; + f32 lstick_y; + f32 rstick_x; + f32 rstick_y; + int charging; + int wired; + } pro; + + u32 unused_6[20]; + }; + u32 unused_7[16]; +} KPADData; +void InitPadScoreFunctionPointers(void); +void InitAcquirePadScore(void); + +typedef void (* wpad_connect_callback_t)(s32 chan, s32 status); + +extern void (* KPADInit)(void); +extern void (* WPADInit)(void); +extern s32 (* WPADProbe)(s32 chan, u32 * pad_type); +extern s32 (* WPADSetDataFormat)(s32 chan, s32 format); +extern void (* WPADEnableURCC)(s32 enable); +extern void (* WPADRead)(s32 chan, void * data); +extern s32 (* KPADRead)(s32 chan, void * data, u32 size); +extern s32 (* KPADReadEx)(s32 chan, KPADData * data, u32 size, s32 *error); +extern void (*WPADSetAutoSleepTime)(u8 time); +extern void (*WPADDisconnect)( s32 chan ); + +#ifdef __cplusplus +} +#endif + +#endif // __PAD_SCORE_FUNCTIONS_H_ diff --git a/src/dynamic_libs/socket_functions.c b/src/dynamic_libs/socket_functions.c new file mode 100644 index 0000000..de2c31f --- /dev/null +++ b/src/dynamic_libs/socket_functions.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "os_functions.h" +#include "socket_functions.h" + +u32 hostIpAddress = 0; + +unsigned int nsysnet_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, socket_lib_init, void); +EXPORT_DECL(int, socket, int domain, int type, int protocol); +EXPORT_DECL(int, socketclose, int s); +EXPORT_DECL(int, connect, int s, void *addr, int addrlen); +EXPORT_DECL(int, bind, s32 s,struct sockaddr *name,s32 namelen); +EXPORT_DECL(int, listen, s32 s,u32 backlog); +EXPORT_DECL(int, accept, s32 s,struct sockaddr *addr,s32 *addrlen); +EXPORT_DECL(int, send, int s, const void *buffer, int size, int flags); +EXPORT_DECL(int, recv, int s, void *buffer, int size, int flags); +EXPORT_DECL(int, recvfrom,int sockfd, void *buf, int len, int flags,struct sockaddr *src_addr, int *addrlen); +EXPORT_DECL(int, sendto, int s, const void *buffer, int size, int flags, const struct sockaddr *dest, int dest_len); +EXPORT_DECL(int, setsockopt, int s, int level, int optname, void *optval, int optlen); +EXPORT_DECL(char *, inet_ntoa, struct in_addr in); +EXPORT_DECL(int, inet_aton, const char *cp, struct in_addr *inp); + +EXPORT_DECL(int, NSSLWrite, int connection, const void* buf, int len,int * written); +EXPORT_DECL(int, NSSLRead, int connection, const void* buf, int len,int * read); +EXPORT_DECL(int, NSSLCreateConnection, int context, const char* host, int hotlen,int options,int sock,int block); + +void InitAcquireSocket(void) +{ + OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle); +} + +void InitSocketFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + + InitAcquireSocket(); + + OS_FIND_EXPORT(nsysnet_handle, socket_lib_init); + OS_FIND_EXPORT(nsysnet_handle, socket); + OS_FIND_EXPORT(nsysnet_handle, socketclose); + OS_FIND_EXPORT(nsysnet_handle, connect); + OS_FIND_EXPORT(nsysnet_handle, bind); + OS_FIND_EXPORT(nsysnet_handle, listen); + OS_FIND_EXPORT(nsysnet_handle, accept); + OS_FIND_EXPORT(nsysnet_handle, send); + OS_FIND_EXPORT(nsysnet_handle, recv); + OS_FIND_EXPORT(nsysnet_handle, recvfrom); + OS_FIND_EXPORT(nsysnet_handle, sendto); + OS_FIND_EXPORT(nsysnet_handle, setsockopt); + OS_FIND_EXPORT(nsysnet_handle, inet_ntoa); + OS_FIND_EXPORT(nsysnet_handle, inet_aton); + + OS_FIND_EXPORT(nsysnet_handle, NSSLWrite); + OS_FIND_EXPORT(nsysnet_handle, NSSLRead); + OS_FIND_EXPORT(nsysnet_handle, NSSLCreateConnection); + + socket_lib_init(); +} diff --git a/src/dynamic_libs/socket_functions.h b/src/dynamic_libs/socket_functions.h new file mode 100644 index 0000000..1e4df1a --- /dev/null +++ b/src/dynamic_libs/socket_functions.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __SOCKET_FUNCTIONS_H_ +#define __SOCKET_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned int nsysnet_handle; + +#include + +#define INADDR_ANY 0 + +#define AF_INET 2 + +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 + +#define IPPROTO_IP 0 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 + +#define TCP_NODELAY 0x2004 + +#define SOL_SOCKET -1 +#define SO_REUSEADDR 0x0004 +#define SO_NONBLOCK 0x1016 +#define SO_MYADDR 0x1013 +#define SO_RCVTIMEO 0x1006 + +#define SOL_SOCKET -1 +#define MSG_DONTWAIT 32 + +#define htonl(x) x +#define htons(x) x +#define ntohl(x) x +#define ntohs(x) x + + +struct in_addr { + unsigned int s_addr; +}; +struct sockaddr_in { + short sin_family; + unsigned short sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +struct sockaddr +{ + unsigned short sa_family; + char sa_data[14]; +}; + + +void InitSocketFunctionPointers(void); +void InitAcquireSocket(void); + +extern void (*socket_lib_init)(void); +extern int (*socket)(int domain, int type, int protocol); +extern int (*socketclose)(int s); +extern int (*connect)(int s, void *addr, int addrlen); +extern int (*bind)(s32 s,struct sockaddr *name,s32 namelen); +extern int (*listen)(s32 s,u32 backlog); +extern int (*accept)(s32 s,struct sockaddr *addr,s32 *addrlen); +extern int (*send)(int s, const void *buffer, int size, int flags); +extern int (*recv)(int s, void *buffer, int size, int flags); +extern int (*recvfrom)(int sockfd, void *buf, int len, int flags,struct sockaddr *src_addr, int *addrlen); + +extern int (*sendto)(int s, const void *buffer, int size, int flags, const struct sockaddr *dest, int dest_len); +extern int (*setsockopt)(int s, int level, int optname, void *optval, int optlen); + +extern int (* NSSLWrite)(int connection, const void* buf, int len,int * written); +extern int (* NSSLRead)(int connection, const void* buf, int len,int * read); +extern int (* NSSLCreateConnection)(int context, const char* host, int hotlen,int options,int sock,int block); + +extern char * (*inet_ntoa)(struct in_addr in); +extern int (*inet_aton)(const char *cp, struct in_addr *inp); + +#ifdef __cplusplus +} +#endif + +#endif // __SOCKET_FUNCTIONS_H_ diff --git a/src/dynamic_libs/sys_functions.c b/src/dynamic_libs/sys_functions.c new file mode 100644 index 0000000..c054549 --- /dev/null +++ b/src/dynamic_libs/sys_functions.c @@ -0,0 +1,49 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "os_functions.h" + + unsigned int sysapp_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(int, _SYSLaunchTitleByPathFromLauncher, const char* path, int len, int zero); +EXPORT_DECL(int, SYSRelaunchTitle, int argc, char** argv); +EXPORT_DECL(int, SYSLaunchMenu, void); +EXPORT_DECL(int, SYSCheckTitleExists, u64 titleId); +EXPORT_DECL(int, SYSLaunchTitle, u64 titleId); + +void InitAcquireSys(void) +{ + OSDynLoad_Acquire("sysapp.rpl", &sysapp_handle); +} + +void InitSysFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + InitAcquireSys(); + + OS_FIND_EXPORT(sysapp_handle, _SYSLaunchTitleByPathFromLauncher); + OS_FIND_EXPORT(sysapp_handle, SYSRelaunchTitle); + OS_FIND_EXPORT(sysapp_handle, SYSLaunchMenu); + OS_FIND_EXPORT(sysapp_handle, SYSCheckTitleExists); + OS_FIND_EXPORT(sysapp_handle, SYSLaunchTitle); +} diff --git a/src/dynamic_libs/sys_functions.h b/src/dynamic_libs/sys_functions.h new file mode 100644 index 0000000..08ca21b --- /dev/null +++ b/src/dynamic_libs/sys_functions.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __SYS_FUNCTIONS_H_ +#define __SYS_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned int sysapp_handle; + +void InitSysFunctionPointers(void); +void InitAcquireSys(void); + +extern int(*_SYSLaunchTitleByPathFromLauncher)(const char* path, int len, int zero); +extern int (* SYSRelaunchTitle)(int argc, char** argv); +extern int (* SYSLaunchMenu)(void); +extern int (* SYSCheckTitleExists)(u64 titleId); +extern int (* SYSLaunchTitle)(u64 titleId); + + +#ifdef __cplusplus +} +#endif + +#endif // __SYS_FUNCTIONS_H_ diff --git a/src/dynamic_libs/syshid_functions.c b/src/dynamic_libs/syshid_functions.c new file mode 100644 index 0000000..996d39d --- /dev/null +++ b/src/dynamic_libs/syshid_functions.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "os_functions.h" +#include "syshid_functions.h" + +unsigned int syshid_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(int, HIDSetup,void); +EXPORT_DECL(int, HIDTeardown,void); + +EXPORT_DECL(int, HIDAddClient,HIDClient *p_client, HIDAttachCallback attach_callback); +EXPORT_DECL(int, HIDDelClient,HIDClient *p_client); + +EXPORT_DECL(int, HIDGetDescriptor,unsigned int handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); +EXPORT_DECL(int, HIDSetDescriptor,unsigned int handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); + +EXPORT_DECL(int, HIDSetProtocol,unsigned int handle,u8 interface_index,u8 protocol, HIDCallback hc, void *p_user); +EXPORT_DECL(int, HIDGetProtocol,unsigned int handle,u8 interface_index,u8 * protocol, HIDCallback hc, void *p_user); + +EXPORT_DECL(int, HIDGetReport,u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +EXPORT_DECL(int, HIDSetReport,u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); + +EXPORT_DECL(int, HIDSetIdle,unsigned int handle, u8 interface_index,u8 duration, HIDCallback hc, void *p_user); + +EXPORT_DECL(int, HIDRead,unsigned int handle, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); +EXPORT_DECL(int, HIDWrite,unsigned int handle, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); + +void InitAcquireSysHID(void) +{ + OSDynLoad_Acquire("nsyshid.rpl", &syshid_handle); +} + +void InitSysHIDFunctionPointers(void) +{ + InitAcquireSysHID(); + + if(syshid_handle == 0){ + return; + } + + unsigned int funcPointer = 0; + + //! assigning those is not mandatory and it does not always work to load them + OS_FIND_EXPORT(syshid_handle, HIDSetup); + OS_FIND_EXPORT(syshid_handle, HIDTeardown); + OS_FIND_EXPORT(syshid_handle, HIDAddClient); + OS_FIND_EXPORT(syshid_handle, HIDDelClient); + OS_FIND_EXPORT(syshid_handle, HIDGetDescriptor); + OS_FIND_EXPORT(syshid_handle, HIDSetDescriptor); + OS_FIND_EXPORT(syshid_handle, HIDRead); + OS_FIND_EXPORT(syshid_handle, HIDWrite); + OS_FIND_EXPORT(syshid_handle, HIDSetProtocol); + OS_FIND_EXPORT(syshid_handle, HIDGetProtocol); + OS_FIND_EXPORT(syshid_handle, HIDSetIdle); + OS_FIND_EXPORT(syshid_handle, HIDGetReport); + OS_FIND_EXPORT(syshid_handle, HIDSetReport); +} diff --git a/src/dynamic_libs/syshid_functions.h b/src/dynamic_libs/syshid_functions.h new file mode 100644 index 0000000..08213b4 --- /dev/null +++ b/src/dynamic_libs/syshid_functions.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __SYSHID_FUNCTIONS_H_ +#define __SYSHID_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned int syshid_handle; + +typedef struct +{ + unsigned int handle; + unsigned int physical_device_inst; + unsigned short vid; + unsigned short pid; + unsigned char interface_index; + unsigned char sub_class; + unsigned char protocol; + + unsigned short max_packet_size_rx; + unsigned short max_packet_size_tx; + +} HIDDevice; + +typedef struct _HIDClient HIDClient; + +#define HID_DEVICE_DETACH 0 +#define HID_DEVICE_ATTACH 1 + +typedef int (*HIDAttachCallback)(HIDClient *p_hc,HIDDevice *p_hd,unsigned int attach); + +struct _HIDClient +{ + HIDClient *next; + HIDAttachCallback attach_cb; +}; + +typedef void (*HIDCallback)(unsigned int handle,int error,unsigned char *p_buffer,unsigned int bytes_transferred,void *p_user); + +void InitSysHIDFunctionPointers(void); +void InitAcquireSysHID(void); + +extern int(*HIDSetup)(void); +extern int(*HIDTeardown)(void); + +extern int(*HIDAddClient)(HIDClient *p_client, HIDAttachCallback attach_callback); +extern int(*HIDDelClient)(HIDClient *p_client); + +extern int(*HIDGetDescriptor)(unsigned int handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); +extern int(*HIDSetDescriptor)(unsigned int handle,u8 descriptor_type,u8 descriptor_index, u16 language_id, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); + +extern int(*HIDGetReport)(u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); +extern int(*HIDSetReport)(u32 handle, u8 report_type, u8 report_id, u8 *p_buffer, u32 buffer_length, HIDCallback hc, void *p_user); + +extern int(*HIDSetIdle)(unsigned int handle, u8 interface_index,u8 duration, HIDCallback hc, void *p_user); + +extern int(* HIDSetProtocol)(unsigned int handle,u8 interface_index,u8 protocol, HIDCallback hc, void *p_user); +extern int(* HIDGetProtocol)(unsigned int handle,u8 interface_index,u8 * protocol, HIDCallback hc, void *p_user); + +extern int(*HIDRead)(unsigned int handle, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); +extern int(*HIDWrite)(unsigned int handle, unsigned char *p_buffer, unsigned int buffer_length, HIDCallback hc, void *p_user); + +#ifdef __cplusplus +} +#endif + +#endif // __SYSHID_FUNCTIONS_H_ diff --git a/src/dynamic_libs/vpad_functions.c b/src/dynamic_libs/vpad_functions.c new file mode 100644 index 0000000..201cf34 --- /dev/null +++ b/src/dynamic_libs/vpad_functions.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "os_functions.h" +#include "vpad_functions.h" + +unsigned int vpad_handle __attribute__((section(".data"))) = 0; +unsigned int vpadbase_handle __attribute__((section(".data"))) = 0; + +EXPORT_DECL(void, VPADInit, void); +EXPORT_DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error); +EXPORT_DECL(int, VPADGetLcdMode, int padnum, int *lcdmode); +EXPORT_DECL(int, VPADSetLcdMode, int padnum, int lcdmode); +EXPORT_DECL(int, VPADBASEGetMotorOnRemainingCount, int padnum); +EXPORT_DECL(int, VPADBASESetMotorOnRemainingCount, int padnum, int counter); + +void InitAcquireVPad(void) +{ + OSDynLoad_Acquire("vpad.rpl", &vpad_handle); + OSDynLoad_Acquire("vpadbase.rpl", &vpadbase_handle); +} + +void InitVPadFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + + InitAcquireVPad(); + + OS_FIND_EXPORT(vpad_handle, VPADInit); + OS_FIND_EXPORT(vpad_handle, VPADRead); + OS_FIND_EXPORT(vpad_handle, VPADGetLcdMode); + OS_FIND_EXPORT(vpad_handle, VPADSetLcdMode); + OS_FIND_EXPORT(vpadbase_handle, VPADBASEGetMotorOnRemainingCount); + OS_FIND_EXPORT(vpadbase_handle, VPADBASESetMotorOnRemainingCount); +} diff --git a/src/dynamic_libs/vpad_functions.h b/src/dynamic_libs/vpad_functions.h new file mode 100644 index 0000000..4fafda2 --- /dev/null +++ b/src/dynamic_libs/vpad_functions.h @@ -0,0 +1,114 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __VPAD_FUNCTIONS_H_ +#define __VPAD_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned int vpad_handle; +extern unsigned int vpadbase_handle; + +#include + +#define VPAD_BUTTON_A 0x8000 +#define VPAD_BUTTON_B 0x4000 +#define VPAD_BUTTON_X 0x2000 +#define VPAD_BUTTON_Y 0x1000 +#define VPAD_BUTTON_LEFT 0x0800 +#define VPAD_BUTTON_RIGHT 0x0400 +#define VPAD_BUTTON_UP 0x0200 +#define VPAD_BUTTON_DOWN 0x0100 +#define VPAD_BUTTON_ZL 0x0080 +#define VPAD_BUTTON_ZR 0x0040 +#define VPAD_BUTTON_L 0x0020 +#define VPAD_BUTTON_R 0x0010 +#define VPAD_BUTTON_PLUS 0x0008 +#define VPAD_BUTTON_MINUS 0x0004 +#define VPAD_BUTTON_HOME 0x0002 +#define VPAD_BUTTON_SYNC 0x0001 +#define VPAD_BUTTON_STICK_R 0x00020000 +#define VPAD_BUTTON_STICK_L 0x00040000 +#define VPAD_BUTTON_TV 0x00010000 + +#define VPAD_STICK_R_EMULATION_LEFT 0x04000000 +#define VPAD_STICK_R_EMULATION_RIGHT 0x02000000 +#define VPAD_STICK_R_EMULATION_UP 0x01000000 +#define VPAD_STICK_R_EMULATION_DOWN 0x00800000 + +#define VPAD_STICK_L_EMULATION_LEFT 0x40000000 +#define VPAD_STICK_L_EMULATION_RIGHT 0x20000000 +#define VPAD_STICK_L_EMULATION_UP 0x10000000 +#define VPAD_STICK_L_EMULATION_DOWN 0x08000000 + +//! Own definitions +#define VPAD_BUTTON_TOUCH 0x00080000 +#define VPAD_MASK_EMULATED_STICKS 0x7F800000 +#define VPAD_MASK_BUTTONS ~VPAD_MASK_EMULATED_STICKS + +typedef struct +{ + f32 x,y; +} Vec2D; + +typedef struct +{ + u16 x, y; /* Touch coordinates */ + u16 touched; /* 1 = Touched, 0 = Not touched */ + u16 invalid; /* 0 = All valid, 1 = X invalid, 2 = Y invalid, 3 = Both invalid? */ +} VPADTPData; + +typedef struct +{ + u32 btns_h; /* Held buttons */ + u32 btns_d; /* Buttons that are pressed at that instant */ + u32 btns_r; /* Released buttons */ + Vec2D lstick, rstick; /* Each contains 4-byte X and Y components */ + char unknown1c[0x52 - 0x1c]; /* Contains accelerometer and gyroscope data somewhere */ + VPADTPData tpdata; /* Normal touchscreen data */ + VPADTPData tpdata1; /* Modified touchscreen data 1 */ + VPADTPData tpdata2; /* Modified touchscreen data 2 */ + char unknown6a[0xa0 - 0x6a]; + uint8_t volume; + uint8_t battery; /* 0 to 6 */ + uint8_t unk_volume; /* One less than volume */ + char unknowna4[0xac - 0xa4]; +} VPADData; + +void InitVPadFunctionPointers(void); +void InitAcquireVPad(void); + +extern int (* VPADRead)(int chan, VPADData *buffer, u32 buffer_size, s32 *error); +extern int (* VPADGetLcdMode)(int padnum, int *lcdmode); +extern int (* VPADSetLcdMode)(int padnum, int lcdmode); +extern void (* VPADInit)(void); +extern int (* VPADBASEGetMotorOnRemainingCount)(int lcdmode); +extern int (* VPADBASESetMotorOnRemainingCount)(int lcdmode,int counter); + +#ifdef __cplusplus +} +#endif + +#endif // __VPAD_FUNCTIONS_H_ diff --git a/src/entry.c b/src/entry.c new file mode 100644 index 0000000..759cee0 --- /dev/null +++ b/src/entry.c @@ -0,0 +1,14 @@ +#include +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/sys_functions.h" +#include "common/common.h" +#include "utils/utils.h" +#include "main.h" + +int __entry_menu(int argc, char **argv) +{ + //! ******************************************************************* + //! * Jump to our application * + //! ******************************************************************* + return Menu_Main(); +} diff --git a/src/fs/CFile.cpp b/src/fs/CFile.cpp new file mode 100644 index 0000000..b26cbf5 --- /dev/null +++ b/src/fs/CFile.cpp @@ -0,0 +1,198 @@ +#include +#include +#include "CFile.hpp" + + +CFile::CFile() +{ + iFd = -1; + mem_file = NULL; + filesize = 0; + pos = 0; +} + +CFile::CFile(const std::string & filepath, eOpenTypes mode) +{ + iFd = -1; + this->open(filepath, mode); +} + +CFile::CFile(const u8 * mem, int size) +{ + iFd = -1; + this->open(mem, size); +} + +CFile::~CFile() +{ + this->close(); +} + +int CFile::open(const std::string & filepath, eOpenTypes mode) +{ + this->close(); + + s32 openMode = 0; + + switch(mode) + { + default: + case ReadOnly: + openMode = O_RDONLY; + break; + case WriteOnly: + openMode = O_WRONLY; + break; + case ReadWrite: + openMode = O_RDWR; + break; + case Append: + openMode = O_APPEND | O_WRONLY; + break; + } + + //! Using fopen works only on the first launch as expected + //! on the second launch it causes issues because we don't overwrite + //! the .data sections which is needed for a normal application to re-init + //! this will be added with launching as RPX + iFd = ::open(filepath.c_str(), openMode); + if(iFd < 0) + return iFd; + + + filesize = ::lseek(iFd, 0, SEEK_END); + ::lseek(iFd, 0, SEEK_SET); + + return 0; +} + +int CFile::open(const u8 * mem, int size) +{ + this->close(); + + mem_file = mem; + filesize = size; + + return 0; +} + +void CFile::close() +{ + if(iFd >= 0) + ::close(iFd); + + iFd = -1; + mem_file = NULL; + filesize = 0; + pos = 0; +} + +int CFile::read(u8 * ptr, size_t size) +{ + if(iFd >= 0) + { + int ret = ::read(iFd, ptr,size); + if(ret > 0) + pos += ret; + return ret; + } + + int readsize = size; + + if(readsize > (s64) (filesize-pos)) + readsize = filesize-pos; + + if(readsize <= 0) + return readsize; + + if(mem_file != NULL) + { + memcpy(ptr, mem_file+pos, readsize); + pos += readsize; + return readsize; + } + + return -1; +} + +int CFile::write(const u8 * ptr, size_t size) +{ + if(iFd >= 0) + { + size_t done = 0; + while(done < size) + { + int ret = ::write(iFd, ptr, size - done); + if(ret <= 0) + return ret; + + ptr += ret; + done += ret; + pos += ret; + } + return done; + } + + return -1; +} + +int CFile::seek(long int offset, int origin) +{ + int ret = 0; + s64 newPos = pos; + + if(origin == SEEK_SET) + { + newPos = offset; + } + else if(origin == SEEK_CUR) + { + newPos += offset; + } + else if(origin == SEEK_END) + { + newPos = filesize+offset; + } + + if(newPos < 0) + { + pos = 0; + } + else { + pos = newPos; + } + + if(iFd >= 0) + ret = ::lseek(iFd, pos, SEEK_SET); + + if(mem_file != NULL) + { + if(pos > filesize) + { + pos = filesize; + } + } + + return ret; +} + +int CFile::fwrite(const char *format, ...) +{ + int result = -1; + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + result = this->write((u8 *)tmp, strlen(tmp)); + } + va_end(va); + + if(tmp) + free(tmp); + + return result; +} + + diff --git a/src/fs/CFile.hpp b/src/fs/CFile.hpp new file mode 100644 index 0000000..a95d3cd --- /dev/null +++ b/src/fs/CFile.hpp @@ -0,0 +1,57 @@ +#ifndef CFILE_HPP_ +#define CFILE_HPP_ + +#include +#include +#include +#include +#include +#include + +class CFile +{ + public: + enum eOpenTypes + { + ReadOnly, + WriteOnly, + ReadWrite, + Append + }; + + CFile(); + CFile(const std::string & filepath, eOpenTypes mode); + CFile(const u8 * memory, int memsize); + virtual ~CFile(); + + int open(const std::string & filepath, eOpenTypes mode); + int open(const u8 * memory, int memsize); + + bool isOpen() const { + if(iFd >= 0) + return true; + + if(mem_file) + return true; + + return false; + } + + void close(); + + int read(u8 * ptr, size_t size); + int write(const u8 * ptr, size_t size); + int fwrite(const char *format, ...); + int seek(long int offset, int origin); + u64 tell() { return pos; }; + u64 size() { return filesize; }; + void rewind() { this->seek(0, SEEK_SET); }; + + protected: + int iFd; + const u8 * mem_file; + u64 filesize; + u64 pos; +}; + +#endif diff --git a/src/fs/DirList.cpp b/src/fs/DirList.cpp new file mode 100644 index 0000000..147deaf --- /dev/null +++ b/src/fs/DirList.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * DirList Class + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include "DirList.h" +#include "utils/StringTools.h" + +DirList::DirList() +{ + Flags = 0; + Filter = 0; +} + +DirList::DirList(const std::string & path, const char *filter, u32 flags) +{ + this->LoadPath(path, filter, flags); + this->SortList(); +} + +DirList::~DirList() +{ + ClearList(); +} + +bool DirList::LoadPath(const std::string & folder, const char *filter, u32 flags) +{ + if(folder.empty()) return false; + + Flags = flags; + Filter = filter; + + std::string folderpath(folder); + u32 length = folderpath.size(); + + //! clear path of double slashes + RemoveDoubleSlashs(folderpath); + + //! remove last slash if exists + if(length > 0 && folderpath[length-1] == '/') + folderpath.erase(length-1); + + return InternalLoadPath(folderpath); +} + +bool DirList::InternalLoadPath(std::string &folderpath) +{ + if(folderpath.size() < 3) + return false; + + struct dirent *dirent = NULL; + DIR *dir = NULL; + + dir = opendir(folderpath.c_str()); + if (dir == NULL) + return false; + + while ((dirent = readdir(dir)) != 0) + { + bool isDir = dirent->d_type & DT_DIR; + const char *filename = dirent->d_name; + + if(isDir) + { + if(strcmp(filename,".") == 0 || strcmp(filename,"..") == 0) + continue; + + if(Flags & CheckSubfolders) + { + int length = folderpath.size(); + if(length > 2 && folderpath[length-1] != '/') + folderpath += '/'; + folderpath += filename; + InternalLoadPath(folderpath); + folderpath.erase(length); + } + + if(!(Flags & Dirs)) + continue; + } + else if(!(Flags & Files)) + { + continue; + } + + if(Filter) + { + char * fileext = strrchr(filename, '.'); + if(!fileext) + continue; + + if(strtokcmp(fileext, Filter, ",") == 0) + AddEntrie(folderpath, filename, isDir); + } + else + { + AddEntrie(folderpath, filename, isDir); + } + } + closedir(dir); + + return true; +} + +void DirList::AddEntrie(const std::string &filepath, const char * filename, bool isDir) +{ + if(!filename) + return; + + int pos = FileInfo.size(); + + FileInfo.resize(pos+1); + + FileInfo[pos].FilePath = (char *) malloc(filepath.size()+strlen(filename)+2); + if(!FileInfo[pos].FilePath) + { + FileInfo.resize(pos); + return; + } + + sprintf(FileInfo[pos].FilePath, "%s/%s", filepath.c_str(), filename); + FileInfo[pos].isDir = isDir; +} + +void DirList::ClearList() +{ + for(u32 i = 0; i < FileInfo.size(); ++i) + { + if(FileInfo[i].FilePath) + free(FileInfo[i].FilePath); + } + + FileInfo.clear(); + std::vector().swap(FileInfo); +} + +const char * DirList::GetFilename(int ind) const +{ + if (!valid(ind)) + return ""; + + return FullpathToFilename(FileInfo[ind].FilePath); +} + +static bool SortCallback(const DirEntry & f1, const DirEntry & f2) +{ + if(f1.isDir && !(f2.isDir)) return true; + if(!(f1.isDir) && f2.isDir) return false; + + if(f1.FilePath && !f2.FilePath) return true; + if(!f1.FilePath) return false; + + if(strcasecmp(f1.FilePath, f2.FilePath) > 0) + return false; + + return true; +} + +void DirList::SortList() +{ + if(FileInfo.size() > 1) + std::sort(FileInfo.begin(), FileInfo.end(), SortCallback); +} + +void DirList::SortList(bool (*SortFunc)(const DirEntry &a, const DirEntry &b)) +{ + if(FileInfo.size() > 1) + std::sort(FileInfo.begin(), FileInfo.end(), SortFunc); +} + +u64 DirList::GetFilesize(int index) const +{ + struct stat st; + const char *path = GetFilepath(index); + + if(!path || stat(path, &st) != 0) + return 0; + + return st.st_size; +} + +int DirList::GetFileIndex(const char *filename) const +{ + if(!filename) + return -1; + + for (u32 i = 0; i < FileInfo.size(); ++i) + { + if (strcasecmp(GetFilename(i), filename) == 0) + return i; + } + + return -1; +} diff --git a/src/fs/DirList.h b/src/fs/DirList.h new file mode 100644 index 0000000..2a34208 --- /dev/null +++ b/src/fs/DirList.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * DirList Class + * for WiiXplorer 2010 + ***************************************************************************/ +#ifndef ___DIRLIST_H_ +#define ___DIRLIST_H_ + +#include +#include +#include + +typedef struct +{ + char * FilePath; + bool isDir; +} DirEntry; + +class DirList +{ +public: + //!Constructor + DirList(void); + //!\param path Path from where to load the filelist of all files + //!\param filter A fileext that needs to be filtered + //!\param flags search/filter flags from the enum + DirList(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs); + //!Destructor + virtual ~DirList(); + //! Load all the files from a directory + bool LoadPath(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs); + //! Get a filename of the list + //!\param list index + const char * GetFilename(int index) const; + //! Get the a filepath of the list + //!\param list index + const char *GetFilepath(int index) const { if (!valid(index)) return ""; else return FileInfo[index].FilePath; } + //! Get the a filesize of the list + //!\param list index + u64 GetFilesize(int index) const; + //! Is index a dir or a file + //!\param list index + bool IsDir(int index) const { if(!valid(index)) return false; return FileInfo[index].isDir; }; + //! Get the filecount of the whole list + int GetFilecount() const { return FileInfo.size(); }; + //! Sort list by filepath + void SortList(); + //! Custom sort command for custom sort functions definitions + void SortList(bool (*SortFunc)(const DirEntry &a, const DirEntry &b)); + //! Get the index of the specified filename + int GetFileIndex(const char *filename) const; + //! Enum for search/filter flags + enum + { + Files = 0x01, + Dirs = 0x02, + CheckSubfolders = 0x08, + }; +protected: + // Internal parser + bool InternalLoadPath(std::string &path); + //!Add a list entrie + void AddEntrie(const std::string &filepath, const char * filename, bool isDir); + //! Clear the list + void ClearList(); + //! Check if valid pos is requested + inline bool valid(u32 pos) const { return (pos < FileInfo.size()); }; + + u32 Flags; + const char *Filter; + std::vector FileInfo; +}; + +#endif diff --git a/src/fs/fs_utils.c b/src/fs/fs_utils.c new file mode 100644 index 0000000..8c4d5c8 --- /dev/null +++ b/src/fs/fs_utils.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include "dynamic_libs/fs_defs.h" +#include "dynamic_libs/fs_functions.h" + +int MountFS(void *pClient, void *pCmd, char **mount_path) +{ + int result = -1; + + void *mountSrc = malloc(FS_MOUNT_SOURCE_SIZE); + if(!mountSrc) + return -3; + + char* mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE); + if(!mountPath) { + free(mountSrc); + return -4; + } + + memset(mountSrc, 0, FS_MOUNT_SOURCE_SIZE); + memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE); + + // Mount sdcard + if (FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, mountSrc, -1) == 0) + { + result = FSMount(pClient, pCmd, mountSrc, mountPath, FS_MAX_MOUNTPATH_SIZE, -1); + if((result == 0) && mount_path) { + *mount_path = (char*)malloc(strlen(mountPath) + 1); + if(*mount_path) + strcpy(*mount_path, mountPath); + } + } + + free(mountPath); + free(mountSrc); + return result; +} + +int UmountFS(void *pClient, void *pCmd, const char *mountPath) +{ + int result = -1; + result = FSUnmount(pClient, pCmd, mountPath, -1); + + return result; +} + +int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size) +{ + //! always initialze input + *inbuffer = NULL; + if(size) + *size = 0; + + int iFd = open(filepath, O_RDONLY); + if (iFd < 0) + return -1; + + u32 filesize = lseek(iFd, 0, SEEK_END); + lseek(iFd, 0, SEEK_SET); + + u8 *buffer = (u8 *) malloc(filesize); + if (buffer == NULL) + { + close(iFd); + return -2; + } + + u32 blocksize = 0x4000; + u32 done = 0; + int readBytes = 0; + + while(done < filesize) + { + if(done + blocksize > filesize) { + blocksize = filesize - done; + } + readBytes = read(iFd, buffer + done, blocksize); + if(readBytes <= 0) + break; + done += readBytes; + } + + close(iFd); + + if (done != filesize) + { + free(buffer); + return -3; + } + + *inbuffer = buffer; + + //! sign is optional input + if(size) + *size = filesize; + + return filesize; +} + +int CheckFile(const char * filepath) +{ + if(!filepath) + return 0; + + struct stat filestat; + + char dirnoslash[strlen(filepath)+2]; + snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath); + + while(dirnoslash[strlen(dirnoslash)-1] == '/') + dirnoslash[strlen(dirnoslash)-1] = '\0'; + + char * notRoot = strrchr(dirnoslash, '/'); + if(!notRoot) + { + strcat(dirnoslash, "/"); + } + + if (stat(dirnoslash, &filestat) == 0) + return 1; + + return 0; +} + +int CreateSubfolder(const char * fullpath) +{ + if(!fullpath) + return 0; + + int result = 0; + + char dirnoslash[strlen(fullpath)+1]; + strcpy(dirnoslash, fullpath); + + int pos = strlen(dirnoslash)-1; + while(dirnoslash[pos] == '/') + { + dirnoslash[pos] = '\0'; + pos--; + } + + if(CheckFile(dirnoslash)) + { + return 1; + } + else + { + char parentpath[strlen(dirnoslash)+2]; + strcpy(parentpath, dirnoslash); + char * ptr = strrchr(parentpath, '/'); + + if(!ptr) + { + //!Device root directory (must be with '/') + strcat(parentpath, "/"); + struct stat filestat; + if (stat(parentpath, &filestat) == 0) + return 1; + + return 0; + } + + ptr++; + ptr[0] = '\0'; + + result = CreateSubfolder(parentpath); + } + + if(!result) + return 0; + + if (mkdir(dirnoslash, 0777) == -1) + { + return 0; + } + + return 1; +} diff --git a/src/fs/fs_utils.h b/src/fs/fs_utils.h new file mode 100644 index 0000000..7022695 --- /dev/null +++ b/src/fs/fs_utils.h @@ -0,0 +1,23 @@ +#ifndef __FS_UTILS_H_ +#define __FS_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int MountFS(void *pClient, void *pCmd, char **mount_path); +int UmountFS(void *pClient, void *pCmd, const char *mountPath); + +int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size); + +//! todo: C++ class +int CreateSubfolder(const char * fullpath); +int CheckFile(const char * filepath); + +#ifdef __cplusplus +} +#endif + +#endif // __FS_UTILS_H_ diff --git a/src/fs/sd_fat_devoptab.c b/src/fs/sd_fat_devoptab.c new file mode 100644 index 0000000..f5b278b --- /dev/null +++ b/src/fs/sd_fat_devoptab.c @@ -0,0 +1,1019 @@ +/*************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "dynamic_libs/fs_functions.h" +#include "dynamic_libs/os_functions.h" +#include "fs_utils.h" + +#define FS_ALIGNMENT 0x40 +#define FS_ALIGN(x) (((x) + FS_ALIGNMENT - 1) & ~(FS_ALIGNMENT - 1)) + +typedef struct _sd_fat_private_t { + char *mount_path; + void *pClient; + void *pCmd; + void *pMutex; +} sd_fat_private_t; + +typedef struct _sd_fat_file_state_t { + sd_fat_private_t *dev; + int fd; /* File descriptor */ + int flags; /* Opening flags */ + bool read; /* True if allowed to read from file */ + bool write; /* True if allowed to write to file */ + bool append; /* True if allowed to append to file */ + u64 pos; /* Current position within the file (in bytes) */ + u64 len; /* Total length of the file (in bytes) */ + struct _sd_fat_file_state_t *prevOpenFile; /* The previous entry in a double-linked FILO list of open files */ + struct _sd_fat_file_state_t *nextOpenFile; /* The next entry in a double-linked FILO list of open files */ +} sd_fat_file_state_t; + +typedef struct _sd_fat_dir_entry_t { + sd_fat_private_t *dev; + int dirHandle; +} sd_fat_dir_entry_t; + +static sd_fat_private_t *sd_fat_get_device_data(const char *path) +{ + const devoptab_t *devoptab = NULL; + char name[128] = {0}; + int i; + + // Get the device name from the path + strncpy(name, path, 127); + strtok(name, ":/"); + + // Search the devoptab table for the specified device name + // NOTE: We do this manually due to a 'bug' in GetDeviceOpTab + // which ignores names with suffixes and causes names + // like "ntfs" and "ntfs1" to be seen as equals + for (i = 3; i < STD_MAX; i++) { + devoptab = devoptab_list[i]; + if (devoptab && devoptab->name) { + if (strcmp(name, devoptab->name) == 0) { + return (sd_fat_private_t *)devoptab->deviceData; + } + } + } + + return NULL; +} + +static char *sd_fat_real_path (const char *path, sd_fat_private_t *dev) +{ + // Sanity check + if (!path) + return NULL; + + // Move the path pointer to the start of the actual path + if (strchr(path, ':') != NULL) { + path = strchr(path, ':') + 1; + } + + int mount_len = strlen(dev->mount_path); + + char *new_name = (char*)malloc(mount_len + strlen(path) + 1); + if(new_name) { + strcpy(new_name, dev->mount_path); + strcpy(new_name + mount_len, path); + return new_name; + } + return new_name; +} + +static int sd_fat_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fileStruct; + + file->dev = dev; + // Determine which mode the file is opened for + file->flags = flags; + + const char *mode_str; + + if ((flags & 0x03) == O_RDONLY) { + file->read = true; + file->write = false; + file->append = false; + mode_str = "r"; + } else if ((flags & 0x03) == O_WRONLY) { + file->read = false; + file->write = true; + file->append = (flags & O_APPEND); + mode_str = file->append ? "a" : "w"; + } else if ((flags & 0x03) == O_RDWR) { + file->read = true; + file->write = true; + file->append = (flags & O_APPEND); + mode_str = file->append ? "a+" : "r+"; + } else { + r->_errno = EACCES; + return -1; + } + + int fd = -1; + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(path, dev); + if(!path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = FSOpenFile(dev->pClient, dev->pCmd, real_path, mode_str, &fd, -1); + + free(real_path); + + if(result == 0) + { + FSStat stats; + result = FSGetStatFile(dev->pClient, dev->pCmd, fd, &stats, -1); + if(result != 0) { + FSCloseFile(dev->pClient, dev->pCmd, fd, -1); + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + file->fd = fd; + file->pos = 0; + file->len = stats.size; + OSUnlockMutex(dev->pMutex); + return (int)file; + } + + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; +} + + +static int sd_fat_close_r (struct _reent *r, int fd) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + int result = FSCloseFile(file->dev->pClient, file->dev->pCmd, file->fd, -1); + + OSUnlockMutex(file->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static off_t sd_fat_seek_r (struct _reent *r, int fd, off_t pos, int dir) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + switch(dir) + { + case SEEK_SET: + file->pos = pos; + break; + case SEEK_CUR: + file->pos += pos; + break; + case SEEK_END: + file->pos = file->len + pos; + break; + default: + r->_errno = EINVAL; + return -1; + } + + int result = FSSetPosFile(file->dev->pClient, file->dev->pCmd, file->fd, file->pos, -1); + + OSUnlockMutex(file->dev->pMutex); + + if(result == 0) + { + return file->pos; + } + + return result; +} + +static ssize_t sd_fat_write_r (struct _reent *r, int fd, const char *ptr, size_t len) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + if(!file->write) + { + r->_errno = EACCES; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + size_t len_aligned = FS_ALIGN(len); + if(len_aligned > 0x4000) + len_aligned = 0x4000; + + unsigned char *tmpBuf = (unsigned char *)memalign(FS_ALIGNMENT, len_aligned); + if(!tmpBuf) { + r->_errno = ENOMEM; + OSUnlockMutex(file->dev->pMutex); + return 0; + } + + size_t done = 0; + + while(done < len) + { + size_t write_size = (len_aligned < (len - done)) ? len_aligned : (len - done); + memcpy(tmpBuf, ptr + done, write_size); + + int result = FSWriteFile(file->dev->pClient, file->dev->pCmd, tmpBuf, 0x01, write_size, file->fd, 0, -1); + if(result < 0) + { + r->_errno = result; + break; + } + else if(result == 0) + { + if(write_size > 0) + done = 0; + break; + } + else + { + done += result; + file->pos += result; + } + } + + free(tmpBuf); + OSUnlockMutex(file->dev->pMutex); + return done; +} + +static ssize_t sd_fat_read_r (struct _reent *r, int fd, char *ptr, size_t len) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + if(!file->read) + { + r->_errno = EACCES; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + size_t len_aligned = FS_ALIGN(len); + if(len_aligned > 0x4000) + len_aligned = 0x4000; + + unsigned char *tmpBuf = (unsigned char *)memalign(FS_ALIGNMENT, len_aligned); + if(!tmpBuf) { + r->_errno = ENOMEM; + OSUnlockMutex(file->dev->pMutex); + return 0; + } + + size_t done = 0; + + while(done < len) + { + size_t read_size = (len_aligned < (len - done)) ? len_aligned : (len - done); + + int result = FSReadFile(file->dev->pClient, file->dev->pCmd, tmpBuf, 0x01, read_size, file->fd, 0, -1); + if(result < 0) + { + r->_errno = result; + done = 0; + break; + } + else if(result == 0) + { + //! TODO: error on read_size > 0 + break; + } + else + { + memcpy(ptr + done, tmpBuf, read_size); + done += result; + file->pos += result; + } + } + + free(tmpBuf); + OSUnlockMutex(file->dev->pMutex); + return done; +} + + +static int sd_fat_fstat_r (struct _reent *r, int fd, struct stat *st) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + // Zero out the stat buffer + memset(st, 0, sizeof(struct stat)); + + FSStat stats; + int result = FSGetStatFile(file->dev->pClient, file->dev->pCmd, file->fd, &stats, -1); + if(result != 0) { + r->_errno = result; + OSUnlockMutex(file->dev->pMutex); + return -1; + } + + st->st_mode = S_IFREG; + st->st_size = stats.size; + st->st_blocks = (stats.size + 511) >> 9; + st->st_nlink = 1; + + // Fill in the generic entry stats + st->st_dev = stats.ent_id; + st->st_uid = stats.owner_id; + st->st_gid = stats.group_id; + st->st_ino = stats.ent_id; + st->st_atime = stats.mtime; + st->st_ctime = stats.ctime; + st->st_mtime = stats.mtime; + OSUnlockMutex(file->dev->pMutex); + return 0; +} + +static int sd_fat_ftruncate_r (struct _reent *r, int fd, off_t len) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + int result = FSTruncateFile(file->dev->pClient, file->dev->pCmd, file->fd, -1); + + OSUnlockMutex(file->dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_fsync_r (struct _reent *r, int fd) +{ + sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + int result = FSFlushFile(file->dev->pClient, file->dev->pCmd, file->fd, -1); + + OSUnlockMutex(file->dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_stat_r (struct _reent *r, const char *path, struct stat *st) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + // Zero out the stat buffer + memset(st, 0, sizeof(struct stat)); + + char *real_path = sd_fat_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + FSStat stats; + + int result = FSGetStat(dev->pClient, dev->pCmd, real_path, &stats, -1); + + free(real_path); + + if(result < 0) { + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + + // mark root also as directory + st->st_mode = ((stats.flag & 0x80000000) || (strlen(dev->mount_path) + 1 == strlen(real_path)))? S_IFDIR : S_IFREG; + st->st_nlink = 1; + st->st_size = stats.size; + st->st_blocks = (stats.size + 511) >> 9; + // Fill in the generic entry stats + st->st_dev = stats.ent_id; + st->st_uid = stats.owner_id; + st->st_gid = stats.group_id; + st->st_ino = stats.ent_id; + st->st_atime = stats.mtime; + st->st_ctime = stats.ctime; + st->st_mtime = stats.mtime; + + OSUnlockMutex(dev->pMutex); + + return 0; +} + +static int sd_fat_link_r (struct _reent *r, const char *existing, const char *newLink) +{ + r->_errno = ENOTSUP; + return -1; +} + +static int sd_fat_unlink_r (struct _reent *r, const char *name) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(name); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(name, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + + int result = FSRemove(dev->pClient, dev->pCmd, real_path, -1); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_chdir_r (struct _reent *r, const char *name) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(name); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(name, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = FSChangeDir(dev->pClient, dev->pCmd, real_path, -1); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_rename_r (struct _reent *r, const char *oldName, const char *newName) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(oldName); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_oldpath = sd_fat_real_path(oldName, dev); + if(!real_oldpath) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + char *real_newpath = sd_fat_real_path(newName, dev); + if(!real_newpath) { + r->_errno = ENOMEM; + free(real_oldpath); + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = FSRename(dev->pClient, dev->pCmd, real_oldpath, real_newpath, -1); + + free(real_oldpath); + free(real_newpath); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; + +} + +static int sd_fat_mkdir_r (struct _reent *r, const char *path, int mode) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = FSMakeDir(dev->pClient, dev->pCmd, real_path, -1); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int sd_fat_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + // Zero out the stat buffer + memset(buf, 0, sizeof(struct statvfs)); + + char *real_path = sd_fat_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + u64 size; + + int result = FSGetFreeSpaceSize(dev->pClient, dev->pCmd, real_path, &size, -1); + + free(real_path); + + if(result < 0) { + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + + // File system block size + buf->f_bsize = 512; + + // Fundamental file system block size + buf->f_frsize = 512; + + // Total number of blocks on file system in units of f_frsize + buf->f_blocks = size >> 9; // this is unknown + + // Free blocks available for all and for non-privileged processes + buf->f_bfree = buf->f_bavail = size >> 9; + + // Number of inodes at this point in time + buf->f_files = 0xffffffff; + + // Free inodes available for all and for non-privileged processes + buf->f_ffree = 0xffffffff; + + // File system id + buf->f_fsid = (int)dev; + + // Bit mask of f_flag values. + buf->f_flag = 0; + + // Maximum length of filenames + buf->f_namemax = 255; + + OSUnlockMutex(dev->pMutex); + + return 0; +} + +static DIR_ITER *sd_fat_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path) +{ + sd_fat_private_t *dev = sd_fat_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return NULL; + } + + sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; + + OSLockMutex(dev->pMutex); + + char *real_path = sd_fat_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return NULL; + } + + int dirHandle; + + int result = FSOpenDir(dev->pClient, dev->pCmd, real_path, &dirHandle, -1); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return NULL; + } + + dirIter->dev = dev; + dirIter->dirHandle = dirHandle; + + return dirState; +} + +static int sd_fat_dirclose_r (struct _reent *r, DIR_ITER *dirState) +{ + sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + int result = FSCloseDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, -1); + + OSUnlockMutex(dirIter->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static int sd_fat_dirreset_r (struct _reent *r, DIR_ITER *dirState) +{ + sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + int result = FSRewindDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, -1); + + OSUnlockMutex(dirIter->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static int sd_fat_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) +{ + sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + FSDirEntry * dir_entry = malloc(sizeof(FSDirEntry)); + + int result = FSReadDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, dir_entry, -1); + if(result < 0) + { + free(dir_entry); + r->_errno = result; + OSUnlockMutex(dirIter->dev->pMutex); + return -1; + } + + // Fetch the current entry + strcpy(filename, dir_entry->name); + + if(st) + { + memset(st, 0, sizeof(struct stat)); + st->st_mode = (dir_entry->stat.flag & 0x80000000) ? S_IFDIR : S_IFREG; + st->st_nlink = 1; + st->st_size = dir_entry->stat.size; + st->st_blocks = (dir_entry->stat.size + 511) >> 9; + st->st_dev = dir_entry->stat.ent_id; + st->st_uid = dir_entry->stat.owner_id; + st->st_gid = dir_entry->stat.group_id; + st->st_ino = dir_entry->stat.ent_id; + st->st_atime = dir_entry->stat.mtime; + st->st_ctime = dir_entry->stat.ctime; + st->st_mtime = dir_entry->stat.mtime; + } + + free(dir_entry); + OSUnlockMutex(dirIter->dev->pMutex); + return 0; +} + +// NTFS device driver devoptab +static const devoptab_t devops_sd_fat = { + NULL, /* Device name */ + sizeof (sd_fat_file_state_t), + sd_fat_open_r, + sd_fat_close_r, + sd_fat_write_r, + sd_fat_read_r, + sd_fat_seek_r, + sd_fat_fstat_r, + sd_fat_stat_r, + sd_fat_link_r, + sd_fat_unlink_r, + sd_fat_chdir_r, + sd_fat_rename_r, + sd_fat_mkdir_r, + sizeof (sd_fat_dir_entry_t), + sd_fat_diropen_r, + sd_fat_dirreset_r, + sd_fat_dirnext_r, + sd_fat_dirclose_r, + sd_fat_statvfs_r, + sd_fat_ftruncate_r, + sd_fat_fsync_r, + NULL, /* sd_fat_chmod_r */ + NULL, /* sd_fat_fchmod_r */ + NULL /* Device data */ +}; + +static int sd_fat_add_device (const char *name, const char *mount_path, void *pClient, void *pCmd) +{ + devoptab_t *dev = NULL; + char *devname = NULL; + char *devpath = NULL; + int i; + + // Sanity check + if (!name) { + errno = EINVAL; + return -1; + } + + // Allocate a devoptab for this device + dev = (devoptab_t *) malloc(sizeof(devoptab_t) + strlen(name) + 1); + if (!dev) { + errno = ENOMEM; + return -1; + } + + // Use the space allocated at the end of the devoptab for storing the device name + devname = (char*)(dev + 1); + strcpy(devname, name); + + // create private data + sd_fat_private_t *priv = (sd_fat_private_t *)malloc(sizeof(sd_fat_private_t) + strlen(mount_path) + 1); + if(!priv) { + free(dev); + errno = ENOMEM; + return -1; + } + + devpath = (char*)(priv+1); + strcpy(devpath, mount_path); + + // setup private data + priv->mount_path = devpath; + priv->pClient = pClient; + priv->pCmd = pCmd; + priv->pMutex = malloc(OS_MUTEX_SIZE); + + if(!priv->pMutex) { + free(dev); + free(priv); + errno = ENOMEM; + return -1; + } + + OSInitMutex(priv->pMutex); + + // Setup the devoptab + memcpy(dev, &devops_sd_fat, sizeof(devoptab_t)); + dev->name = devname; + dev->deviceData = priv; + + // Add the device to the devoptab table (if there is a free slot) + for (i = 3; i < STD_MAX; i++) { + if (devoptab_list[i] == devoptab_list[0]) { + devoptab_list[i] = dev; + return 0; + } + } + + // failure, free all memory + free(priv); + free(dev); + + // If we reach here then there are no free slots in the devoptab table for this device + errno = EADDRNOTAVAIL; + return -1; +} + +static int sd_fat_remove_device (const char *path, void **pClient, void **pCmd, char **mountPath) +{ + const devoptab_t *devoptab = NULL; + char name[128] = {0}; + int i; + + // Get the device name from the path + strncpy(name, path, 127); + strtok(name, ":/"); + + // Find and remove the specified device from the devoptab table + // NOTE: We do this manually due to a 'bug' in RemoveDevice + // which ignores names with suffixes and causes names + // like "ntfs" and "ntfs1" to be seen as equals + for (i = 3; i < STD_MAX; i++) { + devoptab = devoptab_list[i]; + if (devoptab && devoptab->name) { + if (strcmp(name, devoptab->name) == 0) { + devoptab_list[i] = devoptab_list[0]; + + if(devoptab->deviceData) + { + sd_fat_private_t *priv = (sd_fat_private_t *)devoptab->deviceData; + *pClient = priv->pClient; + *pCmd = priv->pCmd; + *mountPath = (char*) malloc(strlen(priv->mount_path)+1); + if(*mountPath) + strcpy(*mountPath, priv->mount_path); + if(priv->pMutex) + free(priv->pMutex); + free(devoptab->deviceData); + } + + free((devoptab_t*)devoptab); + return 0; + } + } + } + + return -1; +} + +int mount_sd_fat(const char *path) +{ + int result = -1; + + // get command and client + void* pClient = malloc(FS_CLIENT_SIZE); + void* pCmd = malloc(FS_CMD_BLOCK_SIZE); + + if(!pClient || !pCmd) { + // just in case free if not 0 + if(pClient) + free(pClient); + if(pCmd) + free(pCmd); + return -2; + } + + FSInit(); + FSInitCmdBlock(pCmd); + FSAddClientEx(pClient, 0, -1); + + char *mountPath = NULL; + + if(MountFS(pClient, pCmd, &mountPath) == 0) { + result = sd_fat_add_device(path, mountPath, pClient, pCmd); + free(mountPath); + } + + return result; +} + +int unmount_sd_fat(const char *path) +{ + void *pClient = 0; + void *pCmd = 0; + char *mountPath = 0; + + int result = sd_fat_remove_device(path, &pClient, &pCmd, &mountPath); + if(result == 0) + { + UmountFS(pClient, pCmd, mountPath); + FSDelClient(pClient); + free(pClient); + free(pCmd); + free(mountPath); + //FSShutdown(); + } + return result; +} diff --git a/src/fs/sd_fat_devoptab.h b/src/fs/sd_fat_devoptab.h new file mode 100644 index 0000000..8df487a --- /dev/null +++ b/src/fs/sd_fat_devoptab.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __SD_FAT_DEVOPTAB_H_ +#define __SD_FAT_DEVOPTAB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int mount_sd_fat(const char *path); +int unmount_sd_fat(const char *path); + +#ifdef __cplusplus +} +#endif + +#endif // __SD_FAT_DEVOPTAB_H_ diff --git a/src/game/Background.cpp b/src/game/Background.cpp new file mode 100644 index 0000000..63330c0 --- /dev/null +++ b/src/game/Background.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "Background.h" +#include "gui/GuiTrigger.h" +#include "gui/GuiController.h" + +/** + * Constructor for the GuiButton class. + */ + +Background::Background(char *picture, float scroll_speed) +{ + loc_x=0.0f; + + bgImg = Resources::GetImageData(picture); + + bg = new GuiImage(bgImg); + bgs = new GuiImage(bgImg); + + bg->setPosition(0, 0); + bgs->setPosition(-1280, 0); + + speed=scroll_speed; +} + +/** + * Destructor for the GuiButton class. + */ +Background::~Background() +{ + speed=0.0f; + loc_x=0.0f; + delete(bgImg); + delete(bg); + delete(bgs); +} + +void Background::setScrollSpeed(float scroll_speed) +{ + speed=scroll_speed; +} + +/** + * Draw the button on screen + */ +void Background::draw(CVideo *v) +{ + if(speed>0.0f) { + loc_x-=speed; + if(loc_x<0.0f) loc_x=1280.0f; + + bg->setPosition((int)loc_x, 0); + bgs->setPosition((int)loc_x-1280, 0); + } + + if(!this->isVisible()) + return; + + // draw images + bg->draw(v); + bgs->draw(v); +} + +void Background::update(GuiController * c) +{ + +} diff --git a/src/game/Background.h b/src/game/Background.h new file mode 100644 index 0000000..76d6548 --- /dev/null +++ b/src/game/Background.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef BACKGROUND_H_ +#define BACKGROUND_H_ + +#include "gui/GuiElement.h" +#include "gui/GuiText.h" +#include "gui/GuiController.h" +#include "gui/GuiImage.h" +#include "gui/GuiSound.h" +#include "gui/GuiTrigger.h" + +//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional) +class Background : public GuiElement +{ + public: + Background(char *picture, float scroll_speed); + virtual ~Background(); + void setScrollSpeed(float scroll_speed); + void draw(CVideo *video); + void update(GuiController * c); + protected: + GuiImageData* bgImg; + GuiImage * bg; + GuiImage * bgs; + float speed; + float loc_x; +}; + +#endif diff --git a/src/game/Pipe.cpp b/src/game/Pipe.cpp new file mode 100644 index 0000000..d3fa08f --- /dev/null +++ b/src/game/Pipe.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "Pipe.h" +#include "gui/GuiTrigger.h" +#include "gui/GuiController.h" + +/** + * Constructor for the GuiButton class. + */ + +Pipe::Pipe(float x) +{ + srand(OSGetTime()); + loc_y=rand() % 250 - 125; + loc_x = x; + pipeBottomImg = Resources::GetImageData("pipe_down.png"); + pipeTopImg = Resources::GetImageData("pipe_up.png"); + pipebottom = new GuiImage(pipeBottomImg); + pipetop = new GuiImage(pipeTopImg); + + pipebottom->setAlignment(ALIGN_CENTER | ALIGN_CENTER); + pipetop->setAlignment(ALIGN_CENTER | ALIGN_CENTER); + + pipebottom->setPosition((int)loc_x,-410-loc_y); + pipetop->setPosition((int)loc_x,410-loc_y); + + scroll_state=false; +} + +/** + * Destructor for the GuiButton class. + */ +Pipe::~Pipe() +{ + loc_x=0.0f; + loc_y=0.0f; + scroll_state=0; + delete(pipetop); + delete(pipebottom); + delete(pipeTopImg); + delete(pipeBottomImg); +} + +void Pipe::setPosX(float x) +{ + loc_x=x; + pipebottom->setPosition((int)loc_x,-410-loc_y); + pipetop->setPosition((int)loc_x,410-loc_y); +} + +void Pipe::setScroll(bool state) +{ + scroll_state=state; +} + +int Pipe::checkCollision(GuiImage* check) +{ + if((pipetop->getLeft()-pipetop->getWidth()/4.0f)<(check->getLeft()+check->getWidth()/2.0f) && (pipetop->getLeft()+pipetop->getWidth()/2)>(check->getLeft()-check->getWidth()/2.0f)) { //How can that thing work? No, really... + poss_collision=1; + if((check->getTop()+check->getHeight()/2.0f)>(pipetop->getTop()-720.0f) || ((check->getTop()-check->getHeight()/2.0f))getTop()) { + poss_collision=0; //we already collided + return 1; + } + } else if (poss_collision==1) { //We just surpassed the problem + poss_collision=0; + return -1; //Add point + } + return 0; +} + + +/** + * Draw the button on screen + */ +void Pipe::draw(CVideo *v) +{ + if(scroll_state==true) { + loc_x-=1.5f; + if (loc_x<-640.0f) { + loc_x=700.0f; + loc_y=rand() % 250 - 125; + } + pipebottom->setPosition((int)loc_x,-410-loc_y); + pipetop->setPosition((int)loc_x,410-loc_y); + } + + if(!this->isVisible()) + return; + + // draw images + pipebottom->draw(v); + pipetop->draw(v); +} + +void Pipe::update(GuiController * c) +{ + +} diff --git a/src/game/Pipe.h b/src/game/Pipe.h new file mode 100644 index 0000000..47288d2 --- /dev/null +++ b/src/game/Pipe.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef PIPE_H_ +#define PIPE_H_ + +#include "gui/GuiElement.h" +#include "gui/GuiText.h" +#include "gui/GuiController.h" +#include "gui/GuiImage.h" +#include "gui/GuiSound.h" +#include "gui/GuiTrigger.h" + +//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional) +class Pipe : public GuiElement +{ + public: + Pipe(float x); + virtual ~Pipe(); + void setPosX(float x); + void setScroll(bool state); + int checkCollision(GuiImage* check); + void draw(CVideo *video); + void update(GuiController * c); + protected: + GuiImageData* pipeBottomImg; + GuiImageData* pipeTopImg; + GuiImage * pipebottom; + GuiImage * pipetop; + float loc_x; + int loc_y; + int poss_collision=0; + bool scroll_state; +}; + +#endif diff --git a/src/game/ScoreImage.cpp b/src/game/ScoreImage.cpp new file mode 100644 index 0000000..9a7359b --- /dev/null +++ b/src/game/ScoreImage.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "ScoreImage.h" +#include "gui/GuiTrigger.h" +#include "gui/GuiController.h" + +/** + * Constructor for the GuiButton class. + */ + +ScoreImage::ScoreImage(int x, int y) +{ + digitsImagesData[0] = Resources::GetImageData("font_big_0.png"); + digitsImagesData[1] = Resources::GetImageData("font_big_1.png"); + digitsImagesData[2] = Resources::GetImageData("font_big_2.png"); + digitsImagesData[3] = Resources::GetImageData("font_big_3.png"); + digitsImagesData[4] = Resources::GetImageData("font_big_4.png"); + digitsImagesData[5] = Resources::GetImageData("font_big_5.png"); + digitsImagesData[6] = Resources::GetImageData("font_big_6.png"); + digitsImagesData[7] = Resources::GetImageData("font_big_7.png"); + digitsImagesData[8] = Resources::GetImageData("font_big_8.png"); + digitsImagesData[9] = Resources::GetImageData("font_big_9.png"); + digitsImagesData[10] = Resources::GetImageData("font_big_null.png"); + + for (int i=0;i<3;i++) { + digitsImages[i] = new GuiImage(digitsImagesData[10]); + digitsImages[i]->setAlignment(ALIGN_CENTER | ALIGN_CENTER); + digitsImages[i]->setPosition(x+(i*36),y); + } + + digitsImages[2]->setImageData(digitsImagesData[0]); +} + +/** + * Destructor for the GuiButton class. + */ +ScoreImage::~ScoreImage() +{ + //for (int i=0;i<11;i++) delete(digitsImagesData[i]); +} + +void ScoreImage::setScore(int score) +{ + //Yeah, that's hacky and there are unusefull functions :P + if (score>999) score=999; //That's unlikey but... + for(int a=0;a<3;a++) digits[a]=10; //Initialize digits to 10 (=don't draw) + + digits[0]=(int)(score/pow(10, 0))%10; + if (score>9) digits[1]=(int)(score/pow(10, 1))%10; + if (score>99) digits[2]=(int)(score/pow(10, 2))%10; + + for(int a=0; a<3; a++) digitsImages[a]->setImageData(digitsImagesData[digits[2-a]]); +} + + +/** + * Draw the button on screen + */ +void ScoreImage::draw(CVideo *v) +{ + if(!this->isVisible()) + return; + + // draw images + digitsImages[0]->draw(v); + digitsImages[1]->draw(v); + digitsImages[2]->draw(v); +} + +void ScoreImage::update(GuiController * c) +{ + +} diff --git a/src/game/ScoreImage.h b/src/game/ScoreImage.h new file mode 100644 index 0000000..0d50cb6 --- /dev/null +++ b/src/game/ScoreImage.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef SCORE_IMG_H_ +#define SCORE_IMG_H_ + +#include "gui/GuiElement.h" +#include "gui/GuiText.h" +#include "gui/GuiController.h" +#include "gui/GuiImage.h" +#include "gui/GuiSound.h" +#include "gui/GuiTrigger.h" + +//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional) +class ScoreImage : public GuiElement +{ + public: + ScoreImage(int x, int y); + virtual ~ScoreImage(); + void setScore(int score); + void draw(CVideo *video); + void update(GuiController * c); + protected: + GuiImageData* digitsImagesData[11]; //Our 10 numers + 1 null digit :P + GuiImage * digitsImages[3]; + int digits[3]; +}; + +#endif diff --git a/src/game/SplashScreen.cpp b/src/game/SplashScreen.cpp new file mode 100644 index 0000000..77e02a1 --- /dev/null +++ b/src/game/SplashScreen.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "SplashScreen.h" +#include "gui/GuiTrigger.h" +#include "gui/GuiController.h" + +/** + * Constructor for the GuiButton class. + */ + +SplashScreen::SplashScreen(GuiImageData * img) +{ + img_real = new GuiImage(img); + img_real->setAlignment(ALIGN_CENTER | ALIGN_CENTER); + img_real->setPosition(0, 0); +} + +/** + * Destructor for the GuiButton class. + */ +SplashScreen::~SplashScreen() +{ + state=0; + delete(img_real); +} + +void SplashScreen::setSplashImageData(GuiImageData * img) +{ + img_real->setImageData(img); +} + +void SplashScreen::FadeExit() +{ + trasparency=1.0f; + state=1; + img_real->setAlpha(trasparency); +} +void SplashScreen::FadeEnter() +{ + trasparency=0.0f; + state=2; + img_real->setAlpha(trasparency); +} + + +/** + * Draw the button on screen + */ +void SplashScreen::draw(CVideo *v) +{ + if(state!=0) { + switch(state) { + case 1: + if (trasparency>0.0f) { + trasparency=trasparency-0.05f; + img_real->setAlpha(trasparency); + } else state=0; + break; + case 2: + if (trasparency<1.0f) { + trasparency=trasparency+0.05f; + img_real->setAlpha(trasparency); + } else state=0; + break; + } + } + + if(!this->isVisible()) + return; + + // draw images + img_real->draw(v); +} + +void SplashScreen::update(GuiController * c) +{ + +} diff --git a/src/game/SplashScreen.h b/src/game/SplashScreen.h new file mode 100644 index 0000000..b510b24 --- /dev/null +++ b/src/game/SplashScreen.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef SPLASHSCREEN_H_ +#define SPLASHSCREEN_H_ + +#include "gui/GuiElement.h" +#include "gui/GuiText.h" +#include "gui/GuiController.h" +#include "gui/GuiImage.h" +#include "gui/GuiSound.h" +#include "gui/GuiTrigger.h" + +//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional) +class SplashScreen : public GuiElement +{ + public: + SplashScreen(GuiImageData * img); + virtual ~SplashScreen(); + void setSplashImageData(GuiImageData * img); + void FadeExit(); + void FadeEnter(); + void draw(CVideo *video); + void update(GuiController * c); + protected: + GuiImage * img_real; + int state; + float trasparency=1.0f; + int tmp_xpos; +}; + +#endif diff --git a/src/gui/FreeTypeGX.cpp b/src/gui/FreeTypeGX.cpp new file mode 100644 index 0000000..6111153 --- /dev/null +++ b/src/gui/FreeTypeGX.cpp @@ -0,0 +1,608 @@ +/* + * FreeTypeGX is a wrapper class for libFreeType which renders a compiled + * FreeType parsable font into a GX texture for Wii homebrew development. + * Copyright (C) 2008 Armin Tamzarian + * Modified by Dimok, 2015 for WiiU GX2 + * + * This file is part of FreeTypeGX. + * + * FreeTypeGX is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FreeTypeGX 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FreeTypeGX. If not, see . + */ + +#include "FreeTypeGX.h" +#include "video/CVideo.h" +#include "video/shaders/Texture2DShader.h" +#include "utils/logger.h" + +using namespace std; + +#define ALIGN4(x) (((x) + 3) & ~3) + +/** + * Default constructor for the FreeTypeGX class for WiiXplorer. + */ +FreeTypeGX::FreeTypeGX(const uint8_t* fontBuffer, FT_Long bufferSize, bool lastFace) +{ + int faceIndex = 0; + ftPointSize = 0; + GX2InitSampler(&ftSampler, GX2_TEX_CLAMP_CLAMP_BORDER, GX2_TEX_XY_FILTER_BILINEAR); + + FT_Init_FreeType(&ftLibrary); + if(lastFace) + { + FT_New_Memory_Face(ftLibrary, (FT_Byte *)fontBuffer, bufferSize, -1, &ftFace); + faceIndex = ftFace->num_faces - 1; // Use the last face + FT_Done_Face(ftFace); + ftFace = NULL; + } + FT_New_Memory_Face(ftLibrary, (FT_Byte *) fontBuffer, bufferSize, faceIndex, &ftFace); + + ftKerningEnabled = FT_HAS_KERNING(ftFace); +} + +/** + * Default destructor for the FreeTypeGX class. + */ +FreeTypeGX::~FreeTypeGX() +{ + unloadFont(); + FT_Done_Face(ftFace); + FT_Done_FreeType(ftLibrary); +} + +/** + * Convert a short char string to a wide char string. + * + * This routine converts a supplied short character string into a wide character string. + * Note that it is the user's responsibility to clear the returned buffer once it is no longer needed. + * + * @param strChar Character string to be converted. + * @return Wide character representation of supplied character string. + */ + +wchar_t* FreeTypeGX::charToWideChar(const char* strChar) +{ + if (!strChar) return NULL; + + wchar_t *strWChar = new (std::nothrow) wchar_t[strlen(strChar) + 1]; + if (!strWChar) return NULL; + + int bt = mbstowcs(strWChar, strChar, strlen(strChar)); + if (bt > 0) + { + strWChar[bt] = 0; + return strWChar; + } + + wchar_t *tempDest = strWChar; + while ((*tempDest++ = *strChar++)) + ; + + return strWChar; +} + +char *FreeTypeGX::wideCharToUTF8(const wchar_t* strChar) +{ + if(!strChar) { + return NULL; + } + + size_t len = 0; + wchar_t wc; + + for (size_t i = 0; strChar[i]; ++i) + { + wc = strChar[i]; + if (wc < 0x80) + ++len; + else if (wc < 0x800) + len += 2; + else if (wc < 0x10000) + len += 3; + else + len += 4; + } + + char *pOut = new (std::nothrow) char[len]; + if(!pOut) + return NULL; + + size_t n = 0; + + for (size_t i = 0; strChar[i]; ++i) + { + wc = strChar[i]; + if (wc < 0x80) + pOut[n++] = (char)wc; + else if (wc < 0x800) + { + pOut[n++] = (char)((wc >> 6) | 0xC0); + pOut[n++] = (char)((wc & 0x3F) | 0x80); + } + else if (wc < 0x10000) + { + pOut[n++] = (char)((wc >> 12) | 0xE0); + pOut[n++] = (char)(((wc >> 6) & 0x3F) | 0x80); + pOut[n++] = (char)((wc & 0x3F) | 0x80); + } + else + { + pOut[n++] = (char)(((wc >> 18) & 0x07) | 0xF0); + pOut[n++] = (char)(((wc >> 12) & 0x3F) | 0x80); + pOut[n++] = (char)(((wc >> 6) & 0x3F) | 0x80); + pOut[n++] = (char)((wc & 0x3F) | 0x80); + } + } + return pOut; +} + +/** + * Clears all loaded font glyph data. + * + * This routine clears all members of the font map structure and frees all allocated memory back to the system. + */ +void FreeTypeGX::unloadFont() +{ + map::iterator itr; + map::iterator itr2; + + for (itr = fontData.begin(); itr != fontData.end(); itr++) + { + for (itr2 = itr->second.ftgxCharMap.begin(); itr2 != itr->second.ftgxCharMap.end(); itr2++) + { + if(itr2->second.texture) + { + if(itr2->second.texture->surface.image_data) + free(itr2->second.texture->surface.image_data); + + delete itr2->second.texture; + itr2->second.texture = NULL; + } + } + } + + fontData.clear(); +} + +/** + * Caches the given font glyph in the instance font texture buffer. + * + * This routine renders and stores the requested glyph's bitmap and relevant information into its own quickly addressible + * structure within an instance-specific map. + * + * @param charCode The requested glyph's character code. + * @return A pointer to the allocated font structure. + */ +ftgxCharData * FreeTypeGX::cacheGlyphData(wchar_t charCode, int16_t pixelSize) +{ + map::iterator itr = fontData.find(pixelSize); + if (itr != fontData.end()) + { + map::iterator itr2 = itr->second.ftgxCharMap.find(charCode); + if (itr2 != itr->second.ftgxCharMap.end()) + { + return &itr2->second; + } + } + //!Cache ascender and decender as well + ftGX2Data *ftData = &fontData[pixelSize]; + + FT_UInt gIndex; + uint16_t textureWidth = 0, textureHeight = 0; + if (ftPointSize != pixelSize) + { + ftPointSize = pixelSize; + FT_Set_Pixel_Sizes(ftFace, 0, ftPointSize); + ftData->ftgxAlign.ascender = (int16_t) ftFace->size->metrics.ascender >> 6; + ftData->ftgxAlign.descender = (int16_t) ftFace->size->metrics.descender >> 6; + ftData->ftgxAlign.max = 0; + ftData->ftgxAlign.min = 0; + } + + gIndex = FT_Get_Char_Index(ftFace, (FT_ULong) charCode); + if (gIndex != 0 && FT_Load_Glyph(ftFace, gIndex, FT_LOAD_DEFAULT | FT_LOAD_RENDER) == 0) + { + if (ftFace->glyph->format == FT_GLYPH_FORMAT_BITMAP) + { + FT_Bitmap *glyphBitmap = &ftFace->glyph->bitmap; + + textureWidth = ALIGN4(glyphBitmap->width); + textureHeight = ALIGN4(glyphBitmap->rows); + if(textureWidth == 0) + textureWidth = 4; + if(textureHeight == 0) + textureHeight = 4; + + ftgxCharData *charData = &ftData->ftgxCharMap[charCode]; + charData->renderOffsetX = (int16_t) ftFace->glyph->bitmap_left; + charData->glyphAdvanceX = (uint16_t) (ftFace->glyph->advance.x >> 6); + charData->glyphAdvanceY = (uint16_t) (ftFace->glyph->advance.y >> 6); + charData->glyphIndex = (uint32_t) gIndex; + charData->renderOffsetY = (int16_t) ftFace->glyph->bitmap_top; + charData->renderOffsetMax = (int16_t) ftFace->glyph->bitmap_top; + charData->renderOffsetMin = (int16_t) glyphBitmap->rows - ftFace->glyph->bitmap_top; + + //! Initialize texture + charData->texture = new GX2Texture; + GX2InitTexture(charData->texture, textureWidth, textureHeight, 1, 0, GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_LINEAR_ALIGNED); + + loadGlyphData(glyphBitmap, charData); + + return charData; + } + } + return NULL; +} + +/** + * Locates each character in this wrapper's configured font face and proccess them. + * + * This routine locates each character in the configured font face and renders the glyph's bitmap. + * Each bitmap and relevant information is loaded into its own quickly addressible structure within an instance-specific map. + */ +uint16_t FreeTypeGX::cacheGlyphDataComplete(int16_t pixelSize) +{ + uint32_t i = 0; + FT_UInt gIndex; + + FT_ULong charCode = FT_Get_First_Char(ftFace, &gIndex); + while (gIndex != 0) + { + if (cacheGlyphData(charCode, pixelSize) != NULL) ++i; + charCode = FT_Get_Next_Char(ftFace, charCode, &gIndex); + } + return (uint16_t) (i); +} + +/** + * Loads the rendered bitmap into the relevant structure's data buffer. + * + * This routine does a simple byte-wise copy of the glyph's rendered 8-bit grayscale bitmap into the structure's buffer. + * Each byte is converted from the bitmap's intensity value into the a uint32_t RGBA value. + * + * @param bmp A pointer to the most recently rendered glyph's bitmap. + * @param charData A pointer to an allocated ftgxCharData structure whose data represent that of the last rendered glyph. + */ + +void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) +{ + charData->texture->surface.image_data = (uint8_t *) memalign(charData->texture->surface.align, charData->texture->surface.image_size); + if(!charData->texture->surface.image_data) + return; + + memset(charData->texture->surface.image_data, 0x00, charData->texture->surface.image_size); + + uint8_t *src = (uint8_t *)bmp->buffer; + uint16_t *dst = (uint16_t *)charData->texture->surface.image_data; + int32_t x, y; + + for(y = 0; y < bmp->rows; y++) + { + for(x = 0; x < bmp->width; x++) + { + uint8_t intensity = src[y * bmp->width + x] >> 3; + dst[y * charData->texture->surface.pitch + x] = intensity ? ((intensity << 11) | (intensity << 6) | (intensity << 1) | 1) : 0; + } + } + GX2Invalidate(GX2_INVALIDATE_CPU_TEXTURE, charData->texture->surface.image_data, charData->texture->surface.image_size); +} + +/** + * Determines the x offset of the rendered string. + * + * This routine calculates the x offset of the rendered string based off of a supplied positional format parameter. + * + * @param width Current pixel width of the string. + * @param format Positional format of the string. + */ +int16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format) +{ + if (format & FTGX_JUSTIFY_LEFT) + return 0; + else if (format & FTGX_JUSTIFY_CENTER) + return -(width >> 1); + else if (format & FTGX_JUSTIFY_RIGHT) return -width; + return 0; +} + +/** + * Determines the y offset of the rendered string. + * + * This routine calculates the y offset of the rendered string based off of a supplied positional format parameter. + * + * @param offset Current pixel offset data of the string. + * @param format Positional format of the string. + */ +int16_t FreeTypeGX::getStyleOffsetHeight(int16_t format, uint16_t pixelSize) +{ + std::map::iterator itr = fontData.find(pixelSize); + if (itr == fontData.end()) return 0; + + switch (format & FTGX_ALIGN_MASK) + { + case FTGX_ALIGN_TOP: + return itr->second.ftgxAlign.descender; + + case FTGX_ALIGN_MIDDLE: + default: + return (itr->second.ftgxAlign.ascender + itr->second.ftgxAlign.descender + 1) >> 1; + + case FTGX_ALIGN_BOTTOM: + return itr->second.ftgxAlign.ascender; + + case FTGX_ALIGN_BASELINE: + return 0; + + case FTGX_ALIGN_GLYPH_TOP: + return itr->second.ftgxAlign.max; + + case FTGX_ALIGN_GLYPH_MIDDLE: + return (itr->second.ftgxAlign.max + itr->second.ftgxAlign.min + 1) >> 1; + + case FTGX_ALIGN_GLYPH_BOTTOM: + return itr->second.ftgxAlign.min; + } + return 0; +} + +/** + * Processes the supplied text string and prints the results at the specified coordinates. + * + * This routine processes each character of the supplied text string, loads the relevant preprocessed bitmap buffer, + * a texture from said buffer, and loads the resultant texture into the EFB. + * + * @param x Screen X coordinate at which to output the text. + * @param y Screen Y coordinate at which to output the text. Note that this value corresponds to the text string origin and not the top or bottom of the glyphs. + * @param text NULL terminated string to output. + * @param color Optional color to apply to the text characters. If not specified default value is ftgxWhite: (GXColor){0xff, 0xff, 0xff, 0xff} + * @param textStyle Flags which specify any styling which should be applied to the rendered string. + * @return The number of characters printed. + */ + +uint16_t FreeTypeGX::drawText(CVideo *video, int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, const glm::vec4 & color, uint16_t textStyle, uint16_t textWidth, const float &textBlur, const float & colorBlurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale) +{ + if (!text) + return 0; + + uint16_t fullTextWidth = (textWidth > 0) ? textWidth : getWidth(text, pixelSize); + uint16_t x_pos = x, printed = 0; + uint16_t x_offset = 0, y_offset = 0; + FT_Vector pairDelta; + + if (textStyle & FTGX_JUSTIFY_MASK) + { + x_offset = getStyleOffsetWidth(fullTextWidth, textStyle); + } + if (textStyle & FTGX_ALIGN_MASK) + { + y_offset = getStyleOffsetHeight(textStyle, pixelSize); + } + + int i = 0; + while (text[i]) + { + ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize); + + if (glyphData != NULL) + { + if (ftKerningEnabled && i > 0) + { + FT_Get_Kerning(ftFace, fontData[pixelSize].ftgxCharMap[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); + x_pos += (pairDelta.x >> 6); + + } + copyTextureToFramebuffer(video, glyphData->texture,x_pos + glyphData->renderOffsetX + x_offset, y + glyphData->renderOffsetY - y_offset, z, color, textBlur, colorBlurIntensity, blurColor,internalRenderingScale); + + x_pos += glyphData->glyphAdvanceX; + ++printed; + } + ++i; + } + + return printed; +} + + +/** + * Processes the supplied string and return the width of the string in pixels. + * + * This routine processes each character of the supplied text string and calculates the width of the entire string. + * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function. + * + * @param text NULL terminated string to calculate. + * @return The width of the text string in pixels. + */ +uint16_t FreeTypeGX::getWidth(const wchar_t *text, int16_t pixelSize) +{ + if (!text) return 0; + + uint16_t strWidth = 0; + FT_Vector pairDelta; + + int i = 0; + while (text[i]) + { + ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize); + + if (glyphData != NULL) + { + if (ftKerningEnabled && (i > 0)) + { + FT_Get_Kerning(ftFace, fontData[pixelSize].ftgxCharMap[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); + strWidth += pairDelta.x >> 6; + } + + strWidth += glyphData->glyphAdvanceX; + } + ++i; + } + return strWidth; +} + +/** + * Single char width + */ +uint16_t FreeTypeGX::getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar) +{ + uint16_t strWidth = 0; + ftgxCharData * glyphData = cacheGlyphData(wChar, pixelSize); + + if (glyphData != NULL) + { + if (ftKerningEnabled && prevChar != 0x0000) + { + FT_Vector pairDelta; + FT_Get_Kerning(ftFace, fontData[pixelSize].ftgxCharMap[prevChar].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); + strWidth += pairDelta.x >> 6; + } + strWidth += glyphData->glyphAdvanceX; + } + + return strWidth; +} + +/** + * Processes the supplied string and return the height of the string in pixels. + * + * This routine processes each character of the supplied text string and calculates the height of the entire string. + * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function. + * + * @param text NULL terminated string to calculate. + * @return The height of the text string in pixels. + */ +uint16_t FreeTypeGX::getHeight(const wchar_t *text, int16_t pixelSize) +{ + getOffset(text, pixelSize); + return fontData[pixelSize].ftgxAlign.max - fontData[pixelSize].ftgxAlign.min; +} + +/** + * Get the maximum offset above and minimum offset below the font origin line. + * + * This function calculates the maximum pixel height above the font origin line and the minimum + * pixel height below the font origin line and returns the values in an addressible structure. + * + * @param text NULL terminated string to calculate. + * @param offset returns the max and min values above and below the font origin line + * + */ +void FreeTypeGX::getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit) +{ + if (fontData.find(pixelSize) != fontData.end()) + return; + + int16_t strMax = 0, strMin = 9999; + uint16_t currWidth = 0; + + int i = 0; + + while (text[i]) + { + if (widthLimit > 0 && currWidth >= widthLimit) break; + + ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize); + + if (glyphData != NULL) + { + strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax; + strMin = glyphData->renderOffsetMin < strMin ? glyphData->renderOffsetMin : strMin; + currWidth += glyphData->glyphAdvanceX; + } + + ++i; + } + + if (ftPointSize != pixelSize) + { + ftPointSize = pixelSize; + FT_Set_Pixel_Sizes(ftFace, 0, ftPointSize); + } + + fontData[pixelSize].ftgxAlign.ascender = ftFace->size->metrics.ascender >> 6; + fontData[pixelSize].ftgxAlign.descender = ftFace->size->metrics.descender >> 6; + fontData[pixelSize].ftgxAlign.max = strMax; + fontData[pixelSize].ftgxAlign.min = strMin; +} + +/** + * Copies the supplied texture quad to the EFB. + * + * This routine uses the in-built GX quad builder functions to define the texture bounds and location on the EFB target. + * + * @param texObj A pointer to the glyph's initialized texture object. + * @param texWidth The pixel width of the texture object. + * @param texHeight The pixel height of the texture object. + * @param screenX The screen X coordinate at which to output the rendered texture. + * @param screenY The screen Y coordinate at which to output the rendered texture. + * @param color Color to apply to the texture. + */ +void FreeTypeGX::copyTextureToFramebuffer(CVideo *pVideo, GX2Texture *texture, int16_t x, int16_t y, int16_t z, const glm::vec4 & color, const float & defaultBlur, const float & blurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale) +{ + static const f32 imageAngle = 0.0f; + static const f32 blurScale = (2.0f/ (internalRenderingScale)); + + f32 offsetLeft = blurScale * ((f32)x + 0.5f * (f32)texture->surface.width) * (f32)pVideo->getWidthScaleFactor(); + f32 offsetTop = blurScale * ((f32)y - 0.5f * (f32)texture->surface.height) * (f32)pVideo->getHeightScaleFactor(); + + f32 widthScale = blurScale * (f32)texture->surface.width * pVideo->getWidthScaleFactor(); + f32 heightScale = blurScale * (f32)texture->surface.height * pVideo->getHeightScaleFactor(); + + glm::vec3 positionOffsets( offsetLeft, offsetTop, (f32)z ); + + //! blur doubles due to blur we have to scale the texture + glm::vec3 scaleFactor( widthScale, heightScale, 1.0f ); + + glm::vec3 blurDirection; + blurDirection[2] = 1.0f; + + Texture2DShader::instance()->setShaders(); + Texture2DShader::instance()->setAttributeBuffer(); + Texture2DShader::instance()->setAngle(imageAngle); + Texture2DShader::instance()->setOffset(positionOffsets); + Texture2DShader::instance()->setScale(scaleFactor); + Texture2DShader::instance()->setTextureAndSampler(texture, &ftSampler); + + if(blurIntensity > 0.0f) + { + //! glow blur color + Texture2DShader::instance()->setColorIntensity(blurColor); + + //! glow blur horizontal + blurDirection[0] = blurIntensity; + blurDirection[1] = 0.0f; + Texture2DShader::instance()->setBlurring(blurDirection); + Texture2DShader::instance()->draw(); + + //! glow blur vertical + blurDirection[0] = 0.0f; + blurDirection[1] = blurIntensity; + Texture2DShader::instance()->setBlurring(blurDirection); + Texture2DShader::instance()->draw(); + } + + //! set text color + Texture2DShader::instance()->setColorIntensity(color); + + //! blur horizontal + blurDirection[0] = defaultBlur; + blurDirection[1] = 0.0f; + Texture2DShader::instance()->setBlurring(blurDirection); + Texture2DShader::instance()->draw(); + + //! blur vertical + blurDirection[0] = 0.0f; + blurDirection[1] = defaultBlur; + Texture2DShader::instance()->setBlurring(blurDirection); + Texture2DShader::instance()->draw(); +} diff --git a/src/gui/FreeTypeGX.h b/src/gui/FreeTypeGX.h new file mode 100644 index 0000000..cd430b4 --- /dev/null +++ b/src/gui/FreeTypeGX.h @@ -0,0 +1,155 @@ +/* + * FreeTypeGX is a wrapper class for libFreeType which renders a compiled + * FreeType parsable font into a GX texture for Wii homebrew development. + * Copyright (C) 2008 Armin Tamzarian + * Modified by Dimok, 2015 for WiiU GX2 + * + * This file is part of FreeTypeGX. + * + * FreeTypeGX is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FreeTypeGX 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FreeTypeGX. If not, see . + */ + +#ifndef FREETYPEGX_H_ +#define FREETYPEGX_H_ + +#include +#include +#include +#include FT_FREETYPE_H +#include FT_BITMAP_H + +#include +#include +#include +#include + +#include +#include + +#include "dynamic_libs/gx2_functions.h" + +/*! \struct ftgxCharData_ + * + * Font face character glyph relevant data structure. + */ +typedef struct ftgxCharData_ +{ + int16_t renderOffsetX; /**< Texture X axis bearing offset. */ + uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */ + uint16_t glyphAdvanceY; /**< Character glyph Y coordinate advance in pixels. */ + uint32_t glyphIndex; /**< Charachter glyph index in the font face. */ + + int16_t renderOffsetY; /**< Texture Y axis bearing offset. */ + int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */ + int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */ + + GX2Texture * texture; +} ftgxCharData; + +/*! \struct ftgxDataOffset_ + * + * Offset structure which hold both a maximum and minimum value. + */ +typedef struct ftgxDataOffset_ +{ + int16_t ascender; /**< Maximum data offset. */ + int16_t descender; /**< Minimum data offset. */ + int16_t max; /**< Maximum data offset. */ + int16_t min; /**< Minimum data offset. */ +} ftgxDataOffset; + +typedef struct ftgxCharData_ ftgxCharData; +typedef struct ftgxDataOffset_ ftgxDataOffset; +#define _TEXT(t) L ## t /**< Unicode helper macro. */ + +#define FTGX_NULL 0x0000 +#define FTGX_JUSTIFY_LEFT 0x0001 +#define FTGX_JUSTIFY_CENTER 0x0002 +#define FTGX_JUSTIFY_RIGHT 0x0004 +#define FTGX_JUSTIFY_MASK 0x000f + +#define FTGX_ALIGN_TOP 0x0010 +#define FTGX_ALIGN_MIDDLE 0x0020 +#define FTGX_ALIGN_BOTTOM 0x0040 +#define FTGX_ALIGN_BASELINE 0x0080 +#define FTGX_ALIGN_GLYPH_TOP 0x0100 +#define FTGX_ALIGN_GLYPH_MIDDLE 0x0200 +#define FTGX_ALIGN_GLYPH_BOTTOM 0x0400 +#define FTGX_ALIGN_MASK 0x0ff0 + +#define FTGX_STYLE_UNDERLINE 0x1000 +#define FTGX_STYLE_STRIKE 0x2000 +#define FTGX_STYLE_MASK 0xf000 + +/**< Constant color value used only to sanitize Doxygen documentation. */ +static const GX2ColorF32 ftgxWhite = (GX2ColorF32){ 1.0f, 1.0f, 1.0f, 1.0f }; + + +//! forward declaration +class CVideo; + +/*! \class FreeTypeGX + * \brief Wrapper class for the libFreeType library with GX rendering. + * \author Armin Tamzarian + * \version 0.2.4 + * + * FreeTypeGX acts as a wrapper class for the libFreeType library. It supports precaching of transformed glyph data into + * a specified texture format. Rendering of the data to the EFB is accomplished through the application of high performance + * GX texture functions resulting in high throughput of string rendering. + */ +class FreeTypeGX +{ + private: + FT_Library ftLibrary; /**< FreeType FT_Library instance. */ + FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */ + int16_t ftPointSize; /**< Current set size of the rendered font. */ + bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */ + uint8_t vertexIndex; /**< Vertex format descriptor index. */ + GX2Sampler ftSampler; + + typedef struct _ftGX2Data + { + ftgxDataOffset ftgxAlign; + std::map ftgxCharMap; + } ftGX2Data; + + std::map fontData; /**< Map which holds the glyph data structures for the corresponding characters in one size. */ + + int16_t getStyleOffsetWidth(uint16_t width, uint16_t format); + int16_t getStyleOffsetHeight(int16_t format, uint16_t pixelSize); + + void unloadFont(); + ftgxCharData *cacheGlyphData(wchar_t charCode, int16_t pixelSize); + uint16_t cacheGlyphDataComplete(int16_t pixelSize); + void loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData); + + void copyTextureToFramebuffer(CVideo * pVideo, GX2Texture *tex, int16_t screenX, int16_t screenY, int16_t screenZ, const glm::vec4 & color, const float &textBlur, const float &colorBlurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale); + + public: + FreeTypeGX(const uint8_t* fontBuffer, FT_Long bufferSize, bool lastFace = false); + ~FreeTypeGX(); + + uint16_t drawText(CVideo * pVideo, int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, const glm::vec4 & color, + uint16_t textStyling, uint16_t textWidth, const float &textBlur, const float &colorBlurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale); + + uint16_t getWidth(const wchar_t *text, int16_t pixelSize); + uint16_t getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar = 0x0000); + uint16_t getHeight(const wchar_t *text, int16_t pixelSize); + void getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit = 0); + + static wchar_t* charToWideChar(const char* p); + static char* wideCharToUTF8(const wchar_t* strChar); +}; + +#endif /* FREETYPEGX_H_ */ diff --git a/src/gui/GameBgImage.cpp b/src/gui/GameBgImage.cpp new file mode 100644 index 0000000..6497f4f --- /dev/null +++ b/src/gui/GameBgImage.cpp @@ -0,0 +1,42 @@ +#include "GameBgImage.h" +#include "video/CVideo.h" +#include "video/shaders/Shader3D.h" + +GameBgImage::GameBgImage(const std::string & filename, GuiImageData *preloadImage) + : GuiImageAsync(filename, preloadImage) +{ + identity = glm::mat4(1.0f); + alphaFadeOut = glm::vec4(1.0f, 0.075f, 5.305f, 2.0f); +} + +GameBgImage::~GameBgImage() +{ +} + +void GameBgImage::draw(CVideo *pVideo) +{ + if(!getImageData() || !getImageData()->getTexture()) + return; + + //! first setup 2D GUI positions + f32 currPosX = getCenterX(); + f32 currPosY = getCenterY(); + f32 currPosZ = getDepth(); + f32 currScaleX = getScaleX() * (f32)getWidth() * pVideo->getWidthScaleFactor(); + f32 currScaleY = getScaleY() * (f32)getHeight() * pVideo->getHeightScaleFactor(); + f32 currScaleZ = getScaleZ() * (f32)getWidth() * pVideo->getDepthScaleFactor(); + + glm::mat4 m_modelView = glm::translate(identity, glm::vec3(currPosX,currPosY, currPosZ)); + m_modelView = glm::scale(m_modelView, glm::vec3(currScaleX, currScaleY, currScaleZ)); + + Shader3D::instance()->setShaders(); + Shader3D::instance()->setProjectionMtx(identity); + Shader3D::instance()->setViewMtx(identity); + Shader3D::instance()->setModelViewMtx(m_modelView); + Shader3D::instance()->setTextureAndSampler(getImageData()->getTexture(), getImageData()->getSampler()); + Shader3D::instance()->setAlphaFadeOut(alphaFadeOut); + Shader3D::instance()->setDistanceFadeOut(0.0f); + Shader3D::instance()->setColorIntensity(glm::vec4(1.0f, 1.0f, 1.0f, getAlpha())); + Shader3D::instance()->setAttributeBuffer(); + Shader3D::instance()->draw(); +} diff --git a/src/gui/GameBgImage.h b/src/gui/GameBgImage.h new file mode 100644 index 0000000..a78b715 --- /dev/null +++ b/src/gui/GameBgImage.h @@ -0,0 +1,23 @@ +#ifndef _GAME_BG_IMAGE_H_ +#define _GAME_BG_IMAGE_H_ + +#include "GuiImageAsync.h" +#include "video/shaders/Shader3D.h" + +class GameBgImage : public GuiImageAsync +{ +public: + GameBgImage(const std::string & filename, GuiImageData *preloadImage); + virtual ~GameBgImage(); + + void setAlphaFadeOut(const glm::vec4 & a) { + alphaFadeOut = a; + } + + void draw(CVideo *pVideo); +private: + glm::mat4 identity; + glm::vec4 alphaFadeOut; +}; + +#endif // _GAME_BG_IMAGE_H_ diff --git a/src/gui/GameIcon.cpp b/src/gui/GameIcon.cpp new file mode 100644 index 0000000..2e1aa73 --- /dev/null +++ b/src/gui/GameIcon.cpp @@ -0,0 +1,321 @@ +#include "GameIcon.h" +#include "GameIconModel.h" +#include "Application.h" +#include "video/CVideo.h" +#include "video/shaders/Shader3D.h" +#include "video/shaders/ShaderFractalColor.h" + +static const f32 cfIconMirrorScale = 1.15f; +static const f32 cfIconMirrorAlpha = 0.45f; + +GameIcon::GameIcon(const std::string & filename, GuiImageData *preloadImage) + : GuiImageAsync(filename, preloadImage) +{ + bSelected = false; + bRenderStroke = true; + bRenderReflection = false; + bIconLast = false; + strokeFractalEnable = 1; + strokeBlurBorder = 0.0f; + distanceFadeout = 0.0f; + rotationX = 0.0f; + reflectionAlpha = 0.4f; + strokeWidth = 2.35f; + colorIntensity = glm::vec4(1.0f); + colorIntensityMirror = colorIntensity; + alphaFadeOutNorm = glm::vec4(0.0f); + alphaFadeOutRefl = glm::vec4(-1.0f, 0.0f, 0.9f, 1.0f); + selectionBlurOuterColorIntensity = glm::vec4(0.09411764f * 1.15f, 0.56862745f * 1.15f, 0.96862745098f * 1.15f, 1.0f); + selectionBlurOuterSize = 1.65f; + selectionBlurOuterBorderSize = 0.5f; + selectionBlurInnerColorIntensity = glm::vec4(0.46666667f, 0.90588235f, 1.0f, 1.0f); + selectionBlurInnerSize = 1.45f; + selectionBlurInnerBorderSize = 0.95f; + + vtxCount = sizeof(cfGameIconPosVtxs) / (Shader3D::cuVertexAttrSize); + + //! texture and vertex coordinates + posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, sizeof(cfGameIconPosVtxs)); + texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, sizeof(cfGameIconTexCoords)); + + if(posVtxs) + { + memcpy((f32*)posVtxs, cfGameIconPosVtxs, sizeof(cfGameIconPosVtxs)); + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, (f32*)posVtxs, sizeof(cfGameIconPosVtxs)); + } + if(texCoords) + { + memcpy((f32*)texCoords, cfGameIconTexCoords, sizeof(cfGameIconTexCoords)); + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, (f32*)texCoords, sizeof(cfGameIconTexCoords)); + } + + //! create vertexes for the mirror frame + texCoordsMirror = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, sizeof(cfGameIconTexCoords)); + + if(texCoordsMirror) + { + for(u32 i = 0; i < vtxCount; i++) + { + texCoordsMirror[i*2 + 0] = texCoords[i*2 + 0] * cfIconMirrorScale - ((cfIconMirrorScale - 1.0f) - (cfIconMirrorScale - 1.0f) * 0.5f); + texCoordsMirror[i*2 + 1] = texCoords[i*2 + 1] * cfIconMirrorScale - ((cfIconMirrorScale - 1.0f) - (cfIconMirrorScale - 1.0f) * 0.5f); + } + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoordsMirror, sizeof(cfGameIconTexCoords)); + } + + //! setup stroke of the icon + strokePosVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, sizeof(cfGameIconStrokeVtxs)); + if(strokePosVtxs) + { + memcpy(strokePosVtxs, cfGameIconStrokeVtxs, sizeof(cfGameIconStrokeVtxs)); + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, strokePosVtxs, sizeof(cfGameIconStrokeVtxs)); + } + strokeTexCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, cuGameIconStrokeVtxCount * Shader::cuTexCoordAttrSize); + if(strokeTexCoords) + { + for(size_t i = 0, n = 0; i < cuGameIconStrokeVtxCount; n += 2, i += 3) + { + strokeTexCoords[n] = (1.0f + strokePosVtxs[i]) * 0.5f; + strokeTexCoords[n+1] = 1.0f - (1.0f + strokePosVtxs[i+1]) * 0.5f; + } + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, strokeTexCoords, cuGameIconStrokeVtxCount * Shader::cuTexCoordAttrSize); + } + strokeColorVtxs = (u8*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, cuGameIconStrokeVtxCount * Shader::cuColorAttrSize); + if(strokeColorVtxs) + { + for(size_t i = 0; i < (cuGameIconStrokeVtxCount * Shader::cuColorAttrSize); i++) + strokeColorVtxs[i] = 0xff; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, strokeColorVtxs, cuGameIconStrokeVtxCount * Shader::cuColorAttrSize); + } +} + +GameIcon::~GameIcon() +{ + //! remove image so it can not be drawn anymore from this point on + imageData = NULL; + + //! main image vertexes + if(posVtxs) + { + free((void*)posVtxs); + posVtxs = NULL; + } + if(texCoords) + { + free((void*)texCoords); + texCoords = NULL; + } + //! mirror image vertexes + if(texCoordsMirror) + { + free(texCoordsMirror); + texCoordsMirror = NULL; + } + //! stroke image vertexes + if(strokePosVtxs) + { + free(strokePosVtxs); + strokePosVtxs = NULL; + } + if(strokeTexCoords) + { + free(strokeTexCoords); + strokeTexCoords = NULL; + } + if(strokeColorVtxs) + { + free(strokeColorVtxs); + strokeColorVtxs = NULL; + } +} + +bool GameIcon::checkRayIntersection(const glm::vec3 & rayOrigin, const glm::vec3 & rayDirFrac) +{ + //! since we always face the camera we can just check the AABB intersection + //! otherwise an OOB intersection would be required + + f32 currPosX = getCenterX() * Application::instance()->getVideo()->getWidthScaleFactor() * 2.0f; + f32 currPosY = getCenterY() * Application::instance()->getVideo()->getHeightScaleFactor() * 2.0f; + f32 currPosZ = getDepth() * Application::instance()->getVideo()->getDepthScaleFactor() * 2.0f; + f32 currScaleX = getScaleX() * (f32)getWidth() * Application::instance()->getVideo()->getWidthScaleFactor(); + f32 currScaleY = getScaleY() * (f32)getHeight() * Application::instance()->getVideo()->getHeightScaleFactor(); + f32 currScaleZ = getScaleZ() * (f32)getWidth() * Application::instance()->getVideo()->getDepthScaleFactor(); + //! lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner + glm::vec3 lb(currPosX - currScaleX, currPosY - currScaleY, currPosZ - currScaleZ); + glm::vec3 rt(currPosX + currScaleX, currPosY + currScaleY, currPosZ + currScaleZ); + + float t1 = (lb.x - rayOrigin.x) * rayDirFrac.x; + float t2 = (rt.x - rayOrigin.x) * rayDirFrac.x; + float t3 = (lb.y - rayOrigin.y) * rayDirFrac.y; + float t4 = (rt.y - rayOrigin.y) * rayDirFrac.y; + float t5 = (lb.z - rayOrigin.z) * rayDirFrac.z; + float t6 = (rt.z - rayOrigin.z) * rayDirFrac.z; + + float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); + float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); + + //! if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us + if (tmax < 0) + { + //t = tmax; + return false; + } + + //! if tmin > tmax, ray doesn't intersect AABB + if (tmin > tmax) + { + //t = tmax; + return false; + } + + //t = tmin; + return true; +} + +void GameIcon::draw(CVideo *pVideo, const glm::mat4 & projectionMtx, const glm::mat4 & viewMtx, const glm::mat4 & modelView) +{ + //! first setup 2D GUI positions + f32 currPosX = getCenterX() * pVideo->getWidthScaleFactor() * 2.0f; + f32 currPosY = getCenterY() * pVideo->getHeightScaleFactor() * 2.0f; + f32 currPosZ = getDepth() * pVideo->getDepthScaleFactor() * 2.0f; + f32 currScaleX = getScaleX() * (f32)getWidth() * pVideo->getWidthScaleFactor(); + f32 currScaleY = getScaleY() * (f32)getHeight() * pVideo->getHeightScaleFactor(); + f32 currScaleZ = getScaleZ() * (f32)getWidth() * pVideo->getDepthScaleFactor(); + f32 strokeScaleX = pVideo->getWidthScaleFactor() * strokeWidth * 0.25f + cfIconMirrorScale; + f32 strokeScaleY = pVideo->getHeightScaleFactor() * strokeWidth * 0.25f + cfIconMirrorScale; + + for(int iDraw = 0; iDraw < 2; iDraw++) + { + glm::vec4 * alphaFadeOut; + glm::mat4 m_iconView; + glm::mat4 m_mirrorView; + glm::mat4 m_strokeView; + + if(iDraw == RENDER_REFLECTION) + { + //! Reflection render + if(!bRenderReflection) + continue; + m_iconView = glm::translate(modelView, glm::vec3(currPosX, -currScaleY * 2.0f - currPosY, currPosZ + cosf(DegToRad(rotationX)) * currScaleZ * 2.0f)); + m_iconView = glm::rotate(m_iconView, DegToRad(rotationX), glm::vec3(1.0f, 0.0f, 0.0f)); + m_iconView = glm::scale(m_iconView, glm::vec3(currScaleX, -currScaleY, currScaleZ)); + + colorIntensity[3] = reflectionAlpha * getAlpha(); + selectionBlurOuterColorIntensity[3] = colorIntensity[3] * 0.7f; + selectionBlurInnerColorIntensity[3] = colorIntensity[3] * 0.7f; + alphaFadeOut = &alphaFadeOutRefl; + + GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, GX2_ENABLE, GX2_DISABLE); + } + else + { + //! Normal render + m_iconView = glm::translate(modelView, glm::vec3(currPosX,currPosY, currPosZ)); + m_iconView = glm::rotate(m_iconView, DegToRad(rotationX), glm::vec3(1.0f, 0.0f, 0.0f)); + m_iconView = glm::scale(m_iconView, glm::vec3(currScaleX, currScaleY, currScaleZ)); + + colorIntensity[3] = getAlpha(); + selectionBlurOuterColorIntensity[3] = colorIntensity[3]; + selectionBlurInnerColorIntensity[3] = colorIntensity[3]; + alphaFadeOut = &alphaFadeOutNorm; + } + + m_mirrorView = glm::scale(m_iconView, glm::vec3(cfIconMirrorScale, cfIconMirrorScale, cfIconMirrorScale)); + + colorIntensityMirror[3] = cfIconMirrorAlpha * colorIntensity[3]; + + if(!bIconLast) + { + Shader3D::instance()->setShaders(); + Shader3D::instance()->setProjectionMtx(projectionMtx); + Shader3D::instance()->setViewMtx(viewMtx); + Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler()); + Shader3D::instance()->setAlphaFadeOut(*alphaFadeOut); + Shader3D::instance()->setDistanceFadeOut(distanceFadeout); + + //! render the real symbol + Shader3D::instance()->setModelViewMtx(m_iconView); + Shader3D::instance()->setColorIntensity(colorIntensity); + Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoords); + Shader3D::instance()->draw(GX2_PRIMITIVE_QUADS, vtxCount); + } + + if(bSelected) + { + strokeFractalEnable = 0; + + GX2SetDepthOnlyControl(GX2_ENABLE, GX2_DISABLE, GX2_COMPARE_LEQUAL); + m_strokeView = glm::scale(m_iconView, glm::vec3(selectionBlurOuterSize, selectionBlurOuterSize, 0.0f)); + ShaderFractalColor::instance()->setShaders(); + ShaderFractalColor::instance()->setProjectionMtx(projectionMtx); + ShaderFractalColor::instance()->setViewMtx(viewMtx); + ShaderFractalColor::instance()->setModelViewMtx(m_strokeView); + ShaderFractalColor::instance()->setFractalColor(strokeFractalEnable); + ShaderFractalColor::instance()->setBlurBorder(selectionBlurOuterBorderSize); + ShaderFractalColor::instance()->setColorIntensity(selectionBlurOuterColorIntensity); + ShaderFractalColor::instance()->setAlphaFadeOut(*alphaFadeOut); + ShaderFractalColor::instance()->setAttributeBuffer(); + ShaderFractalColor::instance()->draw(); + + m_strokeView = glm::scale(m_iconView, glm::vec3(selectionBlurInnerSize, selectionBlurInnerSize, 0.0f)); + ShaderFractalColor::instance()->setBlurBorder(selectionBlurInnerBorderSize); + ShaderFractalColor::instance()->setColorIntensity(selectionBlurInnerColorIntensity); + ShaderFractalColor::instance()->draw(); + GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL); + } + + if(iDraw == RENDER_NORMAL && bRenderStroke) + { + strokeFractalEnable = 1; + //! now render the icon stroke + //! make the stroke a little bigger than the mirror, just by the line width on each side + m_strokeView = glm::scale(m_iconView, glm::vec3(strokeScaleX, strokeScaleY, cfIconMirrorScale)); + + ShaderFractalColor::instance()->setShaders(); + ShaderFractalColor::instance()->setLineWidth(strokeWidth); + ShaderFractalColor::instance()->setProjectionMtx(projectionMtx); + ShaderFractalColor::instance()->setViewMtx(viewMtx); + ShaderFractalColor::instance()->setModelViewMtx(m_strokeView); + ShaderFractalColor::instance()->setFractalColor(strokeFractalEnable); + ShaderFractalColor::instance()->setBlurBorder(strokeBlurBorder); + ShaderFractalColor::instance()->setColorIntensity(colorIntensity); + ShaderFractalColor::instance()->setAlphaFadeOut(*alphaFadeOut); + ShaderFractalColor::instance()->setAttributeBuffer(cuGameIconStrokeVtxCount, strokePosVtxs, strokeTexCoords, strokeColorVtxs); + ShaderFractalColor::instance()->draw(GX2_PRIMITIVE_LINE_STRIP, cuGameIconStrokeVtxCount); + + } + + //! render the background mirror frame + Shader3D::instance()->setShaders(); + Shader3D::instance()->setProjectionMtx(projectionMtx); + Shader3D::instance()->setViewMtx(viewMtx); + Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler()); + Shader3D::instance()->setAlphaFadeOut(*alphaFadeOut); + Shader3D::instance()->setDistanceFadeOut(distanceFadeout); + Shader3D::instance()->setModelViewMtx(m_mirrorView); + Shader3D::instance()->setColorIntensity(colorIntensityMirror); + Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoordsMirror); + Shader3D::instance()->draw(GX2_PRIMITIVE_QUADS, vtxCount); + + if(bIconLast) + { + Shader3D::instance()->setShaders(); + Shader3D::instance()->setProjectionMtx(projectionMtx); + Shader3D::instance()->setViewMtx(viewMtx); + Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler()); + Shader3D::instance()->setAlphaFadeOut(*alphaFadeOut); + Shader3D::instance()->setDistanceFadeOut(distanceFadeout); + + //! render the real symbol + Shader3D::instance()->setModelViewMtx(m_iconView); + Shader3D::instance()->setColorIntensity(colorIntensity); + Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoords); + Shader3D::instance()->draw(GX2_PRIMITIVE_QUADS, vtxCount); + } + + //! return back normal culling + if(iDraw == RENDER_REFLECTION) + { + GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, GX2_DISABLE, GX2_ENABLE); + } + } +} diff --git a/src/gui/GameIcon.h b/src/gui/GameIcon.h new file mode 100644 index 0000000..238060c --- /dev/null +++ b/src/gui/GameIcon.h @@ -0,0 +1,85 @@ +#ifndef _GAME_ICON_H_ +#define _GAME_ICON_H_ + +#include "GuiImageAsync.h" +#include "video/shaders/Shader3D.h" + +class GameIcon : public GuiImageAsync +{ +public: + GameIcon(const std::string & filename, GuiImageData *preloadImage); + virtual ~GameIcon(); + + void setRotationX(f32 r) { + rotationX = r; + } + void setColorIntensity(const glm::vec4 & color) { + colorIntensity = color; + colorIntensityMirror = colorIntensity; + selectionBlurOuterColorIntensity = color * glm::vec4(0.09411764f * 1.15f, 0.56862745f * 1.15f, 0.96862745098f * 1.15f, 1.0f); + selectionBlurInnerColorIntensity = color * glm::vec4(0.46666667f, 0.90588235f, 1.0f, 1.0f); + } + const glm::vec4 & getColorIntensity() const { + return colorIntensity; + } + void setAlphaFadeOutNorm(const glm::vec4 & a) { + alphaFadeOutNorm = a; + } + void setAlphaFadeOutRefl(const glm::vec4 & a) { + alphaFadeOutRefl = a; + } + void setRenderReflection(bool enable) { + bRenderReflection = enable; + } + void setSelected(bool enable) { + bSelected = enable; + } + void setStrokeRender(bool enable) { + bRenderStroke = enable; + } + void setRenderIconLast(bool enable) { + bIconLast = enable; + } + void draw(CVideo *pVideo) { + static const glm::mat4 identity(1.0f); + draw(pVideo, identity, identity, identity); + } + void draw(CVideo *pVideo, const glm::mat4 & projection, const glm::mat4 & view, const glm::mat4 & modelView); + + bool checkRayIntersection(const glm::vec3 & rayOrigin, const glm::vec3 & rayDirFrac); +private: + enum eRenderState + { + RENDER_REFLECTION, + RENDER_NORMAL + }; + + bool bSelected; + bool bRenderStroke; + bool bRenderReflection; + bool bIconLast; + glm::vec4 colorIntensity; + glm::vec4 colorIntensityMirror; + glm::vec4 alphaFadeOutNorm; + glm::vec4 alphaFadeOutRefl; + + f32 reflectionAlpha; + f32 strokeWidth; + f32 rotationX; + f32 rgbReduction; + f32 distanceFadeout; + f32 *texCoordsMirror; + f32 *strokePosVtxs; + f32 *strokeTexCoords; + u8 *strokeColorVtxs; + int strokeFractalEnable; + f32 strokeBlurBorder; + glm::vec4 selectionBlurOuterColorIntensity; + f32 selectionBlurOuterSize; + f32 selectionBlurOuterBorderSize; + glm::vec4 selectionBlurInnerColorIntensity; + f32 selectionBlurInnerSize; + f32 selectionBlurInnerBorderSize; +}; + +#endif // _GAME_ICON_H_ diff --git a/src/gui/GameIconModel.h b/src/gui/GameIconModel.h new file mode 100644 index 0000000..97621ea --- /dev/null +++ b/src/gui/GameIconModel.h @@ -0,0 +1,760 @@ +#ifndef ICON_MODEL_H_ +#define ICON_MODEL_H_ + +static const float cfGameIconPosVtxs[] = { +-0.844501f,-0.861263f,0.050154f,-0.802664f,-0.8797f,0.054004f,-0.809968f,-0.828995f,0.061777f,-0.864233f,-0.822169f,0.054004f, +-0.802664f,-0.8797f,0.054004f,-0.726455f,-0.89991f,0.058224f,-0.730326f,-0.842312f,0.067487f,-0.809968f,-0.828995f,0.061777f, +-0.809968f,-0.828995f,0.061777f,-0.730326f,-0.842312f,0.067487f,-0.738488f,-0.760488f,0.074426f,-0.824221f,-0.752861f,0.067487f, +-0.864233f,-0.822169f,0.054004f,-0.809968f,-0.828995f,0.061777f,-0.824221f,-0.752861f,0.067487f,-0.885862f,-0.749245f,0.058224f, +-0.726455f,-0.89991f,0.058224f,-0.612405f,-0.916988f,0.061789f,-0.614352f,-0.854962f,0.071886f,-0.730326f,-0.842312f,0.067487f, +-0.612405f,-0.916988f,0.061789f,-0.392243f,-0.928623f,0.064218f,-0.39312f,-0.8642f,0.074693f,-0.614352f,-0.854962f,0.071886f, +-0.614352f,-0.854962f,0.071886f,-0.39312f,-0.8642f,0.074693f,-0.395094f,-0.775509f,0.082561f,-0.618732f,-0.768902f,0.079479f, +-0.730326f,-0.842312f,0.067487f,-0.614352f,-0.854962f,0.071886f,-0.618732f,-0.768902f,0.079479f,-0.738488f,-0.760488f,0.074426f, +-0.738488f,-0.760488f,0.074426f,-0.618732f,-0.768902f,0.079479f,-0.624085f,-0.648442f,0.084918f,-0.747494f,-0.64344f,0.079479f, +-0.618732f,-0.768902f,0.079479f,-0.395094f,-0.775509f,0.082561f,-0.397505f,-0.652534f,0.088189f,-0.624085f,-0.648442f,0.084918f, +-0.624085f,-0.648442f,0.084918f,-0.397505f,-0.652534f,0.088189f,-0.399478f,-0.422739f,0.09157f,-0.628465f,-0.420911f,0.088189f, +-0.747494f,-0.64344f,0.079479f,-0.624085f,-0.648442f,0.084918f,-0.628465f,-0.420911f,0.088189f,-0.754564f,-0.418675f,0.082561f, +-0.885862f,-0.749245f,0.058224f,-0.824221f,-0.752861f,0.067487f,-0.837759f,-0.639347f,0.071886f,-0.90414f,-0.637528f,0.061789f, +-0.824221f,-0.752861f,0.067487f,-0.738488f,-0.760488f,0.074426f,-0.747494f,-0.64344f,0.079479f,-0.837759f,-0.639347f,0.071886f, +-0.837759f,-0.639347f,0.071886f,-0.747494f,-0.64344f,0.079479f,-0.754564f,-0.418675f,0.082561f,-0.847646f,-0.416846f,0.074693f, +-0.90414f,-0.637528f,0.061789f,-0.837759f,-0.639347f,0.071886f,-0.847646f,-0.416846f,0.074693f,-0.916591f,-0.416033f,0.064218f, +-0.399478f,-0.422739f,0.09157f,-0.397505f,-0.652534f,0.088189f,0.002274f,-0.653898f,0.089279f,0.002265f,-0.423349f,0.092698f, +-0.397505f,-0.652534f,0.088189f,-0.395094f,-0.775509f,0.082561f,0.002284f,-0.777711f,0.083588f,0.002274f,-0.653898f,0.089279f, +0.002274f,-0.653898f,0.089279f,0.002284f,-0.777711f,0.083588f,0.399509f,-0.775509f,0.082561f,0.401892f,-0.652534f,0.088189f, +0.002265f,-0.423349f,0.092698f,0.002274f,-0.653898f,0.089279f,0.401892f,-0.652534f,0.088189f,0.403842f,-0.422739f,0.09157f, +-0.395094f,-0.775509f,0.082561f,-0.39312f,-0.8642f,0.074693f,0.002293f,-0.867279f,0.075629f,0.002284f,-0.777711f,0.083588f, +-0.39312f,-0.8642f,0.074693f,-0.392243f,-0.928623f,0.064218f,0.002297f,-0.932501f,0.065028f,0.002293f,-0.867279f,0.075629f, +0.002293f,-0.867279f,0.075629f,0.002297f,-0.932501f,0.065028f,0.396693f,-0.928623f,0.064218f,0.397559f,-0.8642f,0.074693f, +0.002284f,-0.777711f,0.083588f,0.002293f,-0.867279f,0.075629f,0.397559f,-0.8642f,0.074693f,0.399509f,-0.775509f,0.082561f, +-0.399478f,-0.422739f,0.09157f,0.002265f,-0.423349f,0.092698f,0.002263f,-0.013572f,0.093837f,-0.400136f,-0.013589f,0.092698f, +0.002265f,-0.423349f,0.092698f,0.403842f,-0.422739f,0.09157f,0.404492f,-0.013589f,0.092698f,0.002263f,-0.013572f,0.093837f, +0.002263f,-0.013572f,0.093837f,0.404492f,-0.013589f,0.092698f,0.403842f,0.396564f,0.09157f,0.002265f,0.397221f,0.092698f, +-0.400136f,-0.013589f,0.092698f,0.002263f,-0.013572f,0.093837f,0.002265f,0.397221f,0.092698f,-0.399478f,0.396564f,0.09157f, +-0.754564f,0.392188f,0.082561f,-0.847646f,0.390218f,0.074693f,-0.850941f,-0.013754f,0.075629f,-0.756921f,-0.013703f,0.083588f, +-0.847646f,0.390218f,0.074693f,-0.916591f,0.389343f,0.064218f,-0.920742f,-0.013776f,0.065028f,-0.850941f,-0.013754f,0.075629f, +-0.850941f,-0.013754f,0.075629f,-0.920742f,-0.013776f,0.065028f,-0.916591f,-0.416033f,0.064218f,-0.847646f,-0.416846f,0.074693f, +-0.756921f,-0.013703f,0.083588f,-0.850941f,-0.013754f,0.075629f,-0.847646f,-0.416846f,0.074693f,-0.754564f,-0.418675f,0.082561f, +-0.754564f,0.392188f,0.082561f,-0.756921f,-0.013703f,0.083588f,-0.629925f,-0.01364f,0.089279f,-0.628465f,0.394595f,0.088189f, +-0.756921f,-0.013703f,0.083588f,-0.754564f,-0.418675f,0.082561f,-0.628465f,-0.420911f,0.088189f,-0.629925f,-0.01364f,0.089279f, +-0.629925f,-0.01364f,0.089279f,-0.628465f,-0.420911f,0.088189f,-0.399478f,-0.422739f,0.09157f,-0.400136f,-0.013589f,0.092698f, +-0.628465f,0.394595f,0.088189f,-0.629925f,-0.01364f,0.089279f,-0.400136f,-0.013589f,0.092698f,-0.399478f,0.396564f,0.09157f, +-0.844501f,0.846382f,0.050154f,-0.802664f,0.865969f,0.054004f,-0.814648f,0.914535f,0.037876f,-0.871108f,0.872793f,0.036675f, +-0.802664f,0.865969f,0.054004f,-0.726455f,0.887439f,0.058224f,-0.733131f,0.94538f,0.040237f,-0.814648f,0.914535f,0.037876f, +-0.814648f,0.914535f,0.037876f,-0.733131f,0.94538f,0.040237f,-0.74278f,0.982563f,0.019733f,-0.830745f,0.945555f,0.018815f, +-0.871108f,0.872793f,0.036675f,-0.814648f,0.914535f,0.037876f,-0.830745f,0.945555f,0.018815f,-0.894756f,0.896267f,0.018385f, +-0.726455f,0.887439f,0.058224f,-0.612405f,0.905582f,0.061789f,-0.615909f,0.968735f,0.042517f,-0.733131f,0.94538f,0.040237f, +-0.612405f,0.905582f,0.061789f,-0.392243f,0.917941f,0.064218f,-0.393822f,0.983443f,0.044197f,-0.615909f,0.968735f,0.042517f, +-0.615909f,0.968735f,0.042517f,-0.393822f,0.983443f,0.044197f,-0.396235f,1.025424f,0.021594f,-0.621266f,1.009264f,0.020771f, +-0.733131f,0.94538f,0.040237f,-0.615909f,0.968735f,0.042517f,-0.621266f,1.009264f,0.020771f,-0.74278f,0.982563f,0.019733f, +-0.621266f,1.009264f,0.020771f,-0.396235f,1.025424f,0.021594f,-0.398382f,1.047552f,0.0f,-0.626031f,1.030658f,0.0f, +-0.74278f,0.982563f,0.019733f,-0.621266f,1.009264f,0.020771f,-0.626031f,1.030658f,0.0f,-0.750636f,1.002556f,0.0f, +-0.830745f,0.945555f,0.018815f,-0.74278f,0.982563f,0.019733f,-0.750636f,1.002556f,0.0f,-0.842153f,0.963302f,0.0f, +-0.894756f,0.896267f,0.018385f,-0.830745f,0.945555f,0.018815f,-0.842153f,0.963302f,0.0f,-0.909674f,0.911075f,0.0f, +-0.398382f,1.047552f,0.0f,-0.396235f,1.025424f,0.021594f,0.002279f,1.030811f,0.021869f,0.00227f,1.053183f,0.0f, +0.002279f,1.030811f,0.021869f,-0.396235f,1.025424f,0.021594f,-0.393822f,0.983443f,0.044197f,0.00229f,0.988345f,0.044757f, +0.400637f,1.025424f,0.021594f,0.002279f,1.030811f,0.021869f,0.00229f,0.988345f,0.044757f,0.398253f,0.983443f,0.044197f, +0.00227f,1.053183f,0.0f,0.002279f,1.030811f,0.021869f,0.400637f,1.025424f,0.021594f,0.402758f,1.047552f,0.0f, +-0.393822f,0.983443f,0.044197f,-0.392243f,0.917941f,0.064218f,0.002297f,0.922061f,0.065028f,0.00229f,0.988345f,0.044757f, +0.00229f,0.988345f,0.044757f,0.002297f,0.922061f,0.065028f,0.396693f,0.917941f,0.064218f,0.398253f,0.983443f,0.044197f, +0.396693f,-0.928623f,0.064218f,0.002297f,-0.932501f,0.065028f,0.00229f,-0.994896f,0.044757f,0.398253f,-0.990281f,0.044197f, +0.002297f,-0.932501f,0.065028f,-0.392243f,-0.928623f,0.064218f,-0.393822f,-0.990281f,0.044197f,0.00229f,-0.994896f,0.044757f, +0.00229f,-0.994896f,0.044757f,-0.393822f,-0.990281f,0.044197f,-0.396235f,-1.0298f,0.021594f,0.002279f,-1.034871f,0.021869f, +0.398253f,-0.990281f,0.044197f,0.00229f,-0.994896f,0.044757f,0.002279f,-1.034871f,0.021869f,0.400637f,-1.0298f,0.021594f, +-0.396235f,-1.0298f,0.021594f,-0.398382f,-1.050629f,0.0f,0.00227f,-1.05593f,0.0f,0.002279f,-1.034871f,0.021869f, +0.002279f,-1.034871f,0.021869f,0.00227f,-1.05593f,0.0f,0.402758f,-1.050629f,0.0f,0.400637f,-1.0298f,0.021594f, +-0.909674f,-0.922159f,0.0f,-0.842153f,-0.971323f,0.0f,-0.830745f,-0.954616f,0.018815f,-0.894756f,-0.90822f,0.018385f, +-0.842153f,-0.971323f,0.0f,-0.750636f,-1.008273f,0.0f,-0.74278f,-0.989453f,0.019733f,-0.830745f,-0.954616f,0.018815f, +-0.830745f,-0.954616f,0.018815f,-0.74278f,-0.989453f,0.019733f,-0.733131f,-0.954452f,0.040237f,-0.814648f,-0.925416f,0.037876f, +-0.894756f,-0.90822f,0.018385f,-0.830745f,-0.954616f,0.018815f,-0.814648f,-0.925416f,0.037876f,-0.871108f,-0.886124f,0.036675f, +-0.750636f,-1.008273f,0.0f,-0.626031f,-1.034726f,0.0f,-0.621266f,-1.014588f,0.020771f,-0.74278f,-0.989453f,0.019733f, +-0.626031f,-1.034726f,0.0f,-0.398382f,-1.050629f,0.0f,-0.396235f,-1.0298f,0.021594f,-0.621266f,-1.014588f,0.020771f, +-0.621266f,-1.014588f,0.020771f,-0.396235f,-1.0298f,0.021594f,-0.393822f,-0.990281f,0.044197f,-0.615909f,-0.976437f,0.042517f, +-0.74278f,-0.989453f,0.019733f,-0.621266f,-1.014588f,0.020771f,-0.615909f,-0.976437f,0.042517f,-0.733131f,-0.954452f,0.040237f, +-0.615909f,-0.976437f,0.042517f,-0.393822f,-0.990281f,0.044197f,-0.392243f,-0.928623f,0.064218f,-0.612405f,-0.916988f,0.061789f, +-0.733131f,-0.954452f,0.040237f,-0.615909f,-0.976437f,0.042517f,-0.612405f,-0.916988f,0.061789f,-0.726455f,-0.89991f,0.058224f, +-0.814648f,-0.925416f,0.037876f,-0.733131f,-0.954452f,0.040237f,-0.726455f,-0.89991f,0.058224f,-0.802664f,-0.8797f,0.054004f, +-0.871108f,-0.886124f,0.036675f,-0.814648f,-0.925416f,0.037876f,-0.802664f,-0.8797f,0.054004f,-0.844501f,-0.861263f,0.050154f, +0.846982f,-0.861263f,0.050154f,0.87333f,-0.886124f,0.036675f,0.914973f,-0.833367f,0.037876f,0.866523f,-0.822169f,0.054004f, +0.914973f,-0.833367f,0.037876f,0.87333f,-0.886124f,0.036675f,0.896749f,-0.90822f,0.018385f,0.94592f,-0.848408f,0.018815f, +0.945745f,-0.755482f,0.040237f,0.914973f,-0.833367f,0.037876f,0.94592f,-0.848408f,0.018815f,0.982841f,-0.764498f,0.019733f, +0.866523f,-0.822169f,0.054004f,0.914973f,-0.833367f,0.037876f,0.945745f,-0.755482f,0.040237f,0.887941f,-0.749245f,0.058224f, +0.896749f,-0.90822f,0.018385f,0.911522f,-0.922159f,0.0f,0.963626f,-0.859068f,0.0f,0.94592f,-0.848408f,0.018815f, +0.94592f,-0.848408f,0.018815f,0.963626f,-0.859068f,0.0f,1.002787f,-0.771839f,0.0f,0.982841f,-0.764498f,0.019733f, +0.945745f,-0.755482f,0.040237f,0.982841f,-0.764498f,0.019733f,1.009478f,-0.645808f,0.020771f,0.969045f,-0.640802f,0.042517f, +0.982841f,-0.764498f,0.019733f,1.002787f,-0.771839f,0.0f,1.030822f,-0.650261f,0.0f,1.009478f,-0.645808f,0.020771f, +1.009478f,-0.645808f,0.020771f,1.030822f,-0.650261f,0.0f,1.047675f,-0.421723f,0.0f,1.025601f,-0.419734f,0.021594f, +1.009478f,-0.645808f,0.020771f,1.025601f,-0.419734f,0.021594f,0.983719f,-0.417497f,0.044197f,0.969045f,-0.640802f,0.042517f, +0.887941f,-0.749245f,0.058224f,0.945745f,-0.755482f,0.040237f,0.969045f,-0.640802f,0.042517f,0.906041f,-0.637528f,0.061789f, +0.906041f,-0.637528f,0.061789f,0.969045f,-0.640802f,0.042517f,0.983719f,-0.417497f,0.044197f,0.918372f,-0.416033f,0.064218f, +0.918372f,-0.416033f,0.064218f,0.983719f,-0.417497f,0.044197f,0.98861f,-0.013736f,0.044757f,0.922482f,-0.013776f,0.065028f, +0.98861f,-0.013736f,0.044757f,0.983719f,-0.417497f,0.044197f,1.025601f,-0.419734f,0.021594f,1.030975f,-0.013673f,0.021869f, +0.983719f,0.390919f,0.044197f,0.98861f,-0.013736f,0.044757f,1.030975f,-0.013673f,0.021869f,1.025601f,0.393327f,0.021594f, +0.922482f,-0.013776f,0.065028f,0.98861f,-0.013736f,0.044757f,0.983719f,0.390919f,0.044197f,0.918372f,0.389343f,0.064218f, +1.025601f,-0.419734f,0.021594f,1.047675f,-0.421723f,0.0f,1.053293f,-0.013618f,0.0f,1.030975f,-0.013673f,0.021869f, +1.030975f,-0.013673f,0.021869f,1.053293f,-0.013618f,0.0f,1.047675f,0.39547f,0.0f,1.025601f,0.393327f,0.021594f, +-0.909674f,-0.922159f,0.0f,-0.894756f,-0.90822f,0.018385f,-0.944409f,-0.848408f,0.018815f,-0.962289f,-0.859068f,0.0f, +-0.944409f,-0.848408f,0.018815f,-0.894756f,-0.90822f,0.018385f,-0.871108f,-0.886124f,0.036675f,-0.913159f,-0.833367f,0.037876f, +-0.981692f,-0.764498f,0.019733f,-0.944409f,-0.848408f,0.018815f,-0.913159f,-0.833367f,0.037876f,-0.944233f,-0.755482f,0.040237f, +-0.962289f,-0.859068f,0.0f,-0.944409f,-0.848408f,0.018815f,-0.981692f,-0.764498f,0.019733f,-1.001834f,-0.771839f,0.0f, +-0.871108f,-0.886124f,0.036675f,-0.844501f,-0.861263f,0.050154f,-0.864233f,-0.822169f,0.054004f,-0.913159f,-0.833367f,0.037876f, +-0.913159f,-0.833367f,0.037876f,-0.864233f,-0.822169f,0.054004f,-0.885862f,-0.749245f,0.058224f,-0.944233f,-0.755482f,0.040237f, +-0.981692f,-0.764498f,0.019733f,-0.944233f,-0.755482f,0.040237f,-0.967761f,-0.640802f,0.042517f,-1.008591f,-0.645808f,0.020771f, +-0.944233f,-0.755482f,0.040237f,-0.885862f,-0.749245f,0.058224f,-0.90414f,-0.637528f,0.061789f,-0.967761f,-0.640802f,0.042517f, +-0.967761f,-0.640802f,0.042517f,-0.90414f,-0.637528f,0.061789f,-0.916591f,-0.416033f,0.064218f,-0.982578f,-0.417497f,0.044197f, +-0.967761f,-0.640802f,0.042517f,-0.982578f,-0.417497f,0.044197f,-1.024871f,-0.419734f,0.021594f,-1.008591f,-0.645808f,0.020771f, +-1.001834f,-0.771839f,0.0f,-0.981692f,-0.764498f,0.019733f,-1.008591f,-0.645808f,0.020771f,-1.030143f,-0.650261f,0.0f, +-1.030143f,-0.650261f,0.0f,-1.008591f,-0.645808f,0.020771f,-1.024871f,-0.419734f,0.021594f,-1.047163f,-0.421723f,0.0f, +-1.047163f,0.39547f,0.0f,-1.052836f,-0.013618f,0.0f,-1.030298f,-0.013673f,0.021869f,-1.024871f,0.393327f,0.021594f, +-1.052836f,-0.013618f,0.0f,-1.047163f,-0.421723f,0.0f,-1.024871f,-0.419734f,0.021594f,-1.030298f,-0.013673f,0.021869f, +-1.030298f,-0.013673f,0.021869f,-1.024871f,-0.419734f,0.021594f,-0.982578f,-0.417497f,0.044197f,-0.987517f,-0.013736f,0.044757f, +-1.024871f,0.393327f,0.021594f,-1.030298f,-0.013673f,0.021869f,-0.987517f,-0.013736f,0.044757f,-0.982578f,0.390919f,0.044197f, +-0.982578f,-0.417497f,0.044197f,-0.916591f,-0.416033f,0.064218f,-0.920742f,-0.013776f,0.065028f,-0.987517f,-0.013736f,0.044757f, +-0.987517f,-0.013736f,0.044757f,-0.920742f,-0.013776f,0.065028f,-0.916591f,0.389343f,0.064218f,-0.982578f,0.390919f,0.044197f, +0.396693f,0.917941f,0.064218f,0.616423f,0.905582f,0.061789f,0.619893f,0.968735f,0.042517f,0.398253f,0.983443f,0.044197f, +0.616423f,0.905582f,0.061789f,0.729904f,0.887439f,0.058224f,0.736514f,0.94538f,0.040237f,0.619893f,0.968735f,0.042517f, +0.619893f,0.968735f,0.042517f,0.736514f,0.94538f,0.040237f,0.746069f,0.982563f,0.019733f,0.625198f,1.009264f,0.020771f, +0.400637f,1.025424f,0.021594f,0.398253f,0.983443f,0.044197f,0.619893f,0.968735f,0.042517f,0.625198f,1.009264f,0.020771f, +0.729904f,0.887439f,0.058224f,0.805551f,0.865969f,0.054004f,0.817418f,0.914535f,0.037876f,0.736514f,0.94538f,0.040237f, +0.805551f,0.865969f,0.054004f,0.846982f,0.846382f,0.050154f,0.87333f,0.872793f,0.036675f,0.817418f,0.914535f,0.037876f, +0.817418f,0.914535f,0.037876f,0.87333f,0.872793f,0.036675f,0.896749f,0.896267f,0.018385f,0.833359f,0.945555f,0.018815f, +0.736514f,0.94538f,0.040237f,0.817418f,0.914535f,0.037876f,0.833359f,0.945555f,0.018815f,0.746069f,0.982563f,0.019733f, +0.833359f,0.945555f,0.018815f,0.896749f,0.896267f,0.018385f,0.911522f,0.911075f,0.0f,0.844656f,0.963302f,0.0f, +0.746069f,0.982563f,0.019733f,0.833359f,0.945555f,0.018815f,0.844656f,0.963302f,0.0f,0.753849f,1.002556f,0.0f, +0.625198f,1.009264f,0.020771f,0.746069f,0.982563f,0.019733f,0.753849f,1.002556f,0.0f,0.629917f,1.030658f,0.0f, +0.400637f,1.025424f,0.021594f,0.625198f,1.009264f,0.020771f,0.629917f,1.030658f,0.0f,0.402758f,1.047552f,0.0f, +0.396693f,-0.928623f,0.064218f,0.398253f,-0.990281f,0.044197f,0.619893f,-0.976437f,0.042517f,0.616423f,-0.916988f,0.061789f, +0.619893f,-0.976437f,0.042517f,0.398253f,-0.990281f,0.044197f,0.400637f,-1.0298f,0.021594f,0.625198f,-1.014588f,0.020771f, +0.736514f,-0.954452f,0.040237f,0.619893f,-0.976437f,0.042517f,0.625198f,-1.014588f,0.020771f,0.746069f,-0.989453f,0.019733f, +0.616423f,-0.916988f,0.061789f,0.619893f,-0.976437f,0.042517f,0.736514f,-0.954452f,0.040237f,0.729904f,-0.89991f,0.058224f, +0.400637f,-1.0298f,0.021594f,0.402758f,-1.050629f,0.0f,0.629917f,-1.034726f,0.0f,0.625198f,-1.014588f,0.020771f, +0.625198f,-1.014588f,0.020771f,0.629917f,-1.034726f,0.0f,0.753849f,-1.008273f,0.0f,0.746069f,-0.989453f,0.019733f, +0.736514f,-0.954452f,0.040237f,0.746069f,-0.989453f,0.019733f,0.833359f,-0.954616f,0.018815f,0.817418f,-0.925416f,0.037876f, +0.746069f,-0.989453f,0.019733f,0.753849f,-1.008273f,0.0f,0.844656f,-0.971323f,0.0f,0.833359f,-0.954616f,0.018815f, +0.833359f,-0.954616f,0.018815f,0.844656f,-0.971323f,0.0f,0.911522f,-0.922159f,0.0f,0.896749f,-0.90822f,0.018385f, +0.833359f,-0.954616f,0.018815f,0.896749f,-0.90822f,0.018385f,0.87333f,-0.886124f,0.036675f,0.817418f,-0.925416f,0.037876f, +0.729904f,-0.89991f,0.058224f,0.736514f,-0.954452f,0.040237f,0.817418f,-0.925416f,0.037876f,0.805551f,-0.8797f,0.054004f, +0.805551f,-0.8797f,0.054004f,0.817418f,-0.925416f,0.037876f,0.87333f,-0.886124f,0.036675f,0.846982f,-0.861263f,0.050154f, +0.403842f,-0.422739f,0.09157f,0.401892f,-0.652534f,0.088189f,0.62799f,-0.648441f,0.084918f,0.632327f,-0.420911f,0.088189f, +0.401892f,-0.652534f,0.088189f,0.399509f,-0.775509f,0.082561f,0.622688f,-0.768902f,0.079479f,0.62799f,-0.648441f,0.084918f, +0.62799f,-0.648441f,0.084918f,0.622688f,-0.768902f,0.079479f,0.741819f,-0.760488f,0.074426f,0.750737f,-0.64344f,0.079479f, +0.632327f,-0.420911f,0.088189f,0.62799f,-0.648441f,0.084918f,0.750737f,-0.64344f,0.079479f,0.757739f,-0.418675f,0.082561f, +0.399509f,-0.775509f,0.082561f,0.397559f,-0.8642f,0.074693f,0.618351f,-0.854962f,0.071886f,0.622688f,-0.768902f,0.079479f, +0.397559f,-0.8642f,0.074693f,0.396693f,-0.928623f,0.064218f,0.616423f,-0.916988f,0.061789f,0.618351f,-0.854962f,0.071886f, +0.618351f,-0.854962f,0.071886f,0.616423f,-0.916988f,0.061789f,0.729904f,-0.89991f,0.058224f,0.733736f,-0.842312f,0.067487f, +0.622688f,-0.768902f,0.079479f,0.618351f,-0.854962f,0.071886f,0.733736f,-0.842312f,0.067487f,0.741819f,-0.760488f,0.074426f, +0.741819f,-0.760488f,0.074426f,0.733736f,-0.842312f,0.067487f,0.812784f,-0.828995f,0.061777f,0.826898f,-0.752861f,0.067487f, +0.733736f,-0.842312f,0.067487f,0.729904f,-0.89991f,0.058224f,0.805551f,-0.8797f,0.054004f,0.812784f,-0.828995f,0.061777f, +0.812784f,-0.828995f,0.061777f,0.805551f,-0.8797f,0.054004f,0.846982f,-0.861263f,0.050154f,0.866523f,-0.822169f,0.054004f, +0.826898f,-0.752861f,0.067487f,0.812784f,-0.828995f,0.061777f,0.866523f,-0.822169f,0.054004f,0.887941f,-0.749245f,0.058224f, +0.757739f,-0.418675f,0.082561f,0.750737f,-0.64344f,0.079479f,0.840305f,-0.639347f,0.071886f,0.850096f,-0.416846f,0.074693f, +0.750737f,-0.64344f,0.079479f,0.741819f,-0.760488f,0.074426f,0.826898f,-0.752861f,0.067487f,0.840305f,-0.639347f,0.071886f, +0.840305f,-0.639347f,0.071886f,0.826898f,-0.752861f,0.067487f,0.887941f,-0.749245f,0.058224f,0.906041f,-0.637528f,0.061789f, +0.850096f,-0.416846f,0.074693f,0.840305f,-0.639347f,0.071886f,0.906041f,-0.637528f,0.061789f,0.918372f,-0.416033f,0.064218f, +0.403842f,0.396564f,0.09157f,0.404492f,-0.013589f,0.092698f,0.633773f,-0.01364f,0.08928f,0.632327f,0.394595f,0.088189f, +0.404492f,-0.013589f,0.092698f,0.403842f,-0.422739f,0.09157f,0.632327f,-0.420911f,0.088189f,0.633773f,-0.01364f,0.08928f, +0.633773f,-0.01364f,0.08928f,0.632327f,-0.420911f,0.088189f,0.757739f,-0.418675f,0.082561f,0.760073f,-0.013703f,0.083588f, +0.632327f,0.394595f,0.088189f,0.633773f,-0.01364f,0.08928f,0.760073f,-0.013703f,0.083588f,0.757739f,0.392188f,0.082561f, +0.757739f,-0.418675f,0.082561f,0.850096f,-0.416846f,0.074693f,0.853359f,-0.013754f,0.075629f,0.760073f,-0.013703f,0.083588f, +0.850096f,-0.416846f,0.074693f,0.918372f,-0.416033f,0.064218f,0.922482f,-0.013776f,0.065028f,0.853359f,-0.013754f,0.075629f, +0.853359f,-0.013754f,0.075629f,0.922482f,-0.013776f,0.065028f,0.918372f,0.389343f,0.064218f,0.850096f,0.390218f,0.074693f, +0.760073f,-0.013703f,0.083588f,0.853359f,-0.013754f,0.075629f,0.850096f,0.390218f,0.074693f,0.757739f,0.392188f,0.082561f, +-1.047163f,0.39547f,0.0f,-1.024871f,0.393327f,0.021594f,-1.008591f,0.622221f,0.020771f,-1.030143f,0.626951f,0.0f, +-1.008591f,0.622221f,0.020771f,-1.024871f,0.393327f,0.021594f,-0.982578f,0.390919f,0.044197f,-0.967761f,0.616903f,0.042517f, +-0.981692f,0.744767f,0.019733f,-1.008591f,0.622221f,0.020771f,-0.967761f,0.616903f,0.042517f,-0.944233f,0.735189f,0.040237f, +-1.030143f,0.626951f,0.0f,-1.008591f,0.622221f,0.020771f,-0.981692f,0.744767f,0.019733f,-1.001834f,0.752565f,0.0f, +-0.982578f,0.390919f,0.044197f,-0.916591f,0.389343f,0.064218f,-0.90414f,0.613425f,0.061789f,-0.967761f,0.616903f,0.042517f, +-0.967761f,0.616903f,0.042517f,-0.90414f,0.613425f,0.061789f,-0.885862f,0.728563f,0.058224f,-0.944233f,0.735189f,0.040237f, +-0.981692f,0.744767f,0.019733f,-0.944233f,0.735189f,0.040237f,-0.913159f,0.816749f,0.037876f,-0.944409f,0.832727f,0.018815f, +-0.944233f,0.735189f,0.040237f,-0.885862f,0.728563f,0.058224f,-0.864233f,0.804853f,0.054004f,-0.913159f,0.816749f,0.037876f, +-0.913159f,0.816749f,0.037876f,-0.864233f,0.804853f,0.054004f,-0.844501f,0.846382f,0.050154f,-0.871108f,0.872793f,0.036675f, +-0.913159f,0.816749f,0.037876f,-0.871108f,0.872793f,0.036675f,-0.894756f,0.896267f,0.018385f,-0.944409f,0.832727f,0.018815f, +-1.001834f,0.752565f,0.0f,-0.981692f,0.744767f,0.019733f,-0.944409f,0.832727f,0.018815f,-0.962289f,0.844051f,0.0f, +-0.962289f,0.844051f,0.0f,-0.944409f,0.832727f,0.018815f,-0.894756f,0.896267f,0.018385f,-0.909674f,0.911075f,0.0f, +0.918372f,0.389343f,0.064218f,0.983719f,0.390919f,0.044197f,0.969045f,0.616903f,0.042517f,0.906041f,0.613425f,0.061789f, +0.969045f,0.616903f,0.042517f,0.983719f,0.390919f,0.044197f,1.025601f,0.393327f,0.021594f,1.009478f,0.622221f,0.020771f, +0.945745f,0.735189f,0.040237f,0.969045f,0.616903f,0.042517f,1.009478f,0.622221f,0.020771f,0.982841f,0.744767f,0.019733f, +0.906041f,0.613425f,0.061789f,0.969045f,0.616903f,0.042517f,0.945745f,0.735189f,0.040237f,0.887941f,0.728563f,0.058224f, +1.025601f,0.393327f,0.021594f,1.047675f,0.39547f,0.0f,1.030822f,0.626951f,0.0f,1.009478f,0.622221f,0.020771f, +1.009478f,0.622221f,0.020771f,1.030822f,0.626951f,0.0f,1.002787f,0.752565f,0.0f,0.982841f,0.744767f,0.019733f, +0.945745f,0.735189f,0.040237f,0.982841f,0.744767f,0.019733f,0.94592f,0.832727f,0.018815f,0.914973f,0.816749f,0.037876f, +0.982841f,0.744767f,0.019733f,1.002787f,0.752565f,0.0f,0.963626f,0.844051f,0.0f,0.94592f,0.832727f,0.018815f, +0.94592f,0.832727f,0.018815f,0.963626f,0.844051f,0.0f,0.911522f,0.911075f,0.0f,0.896749f,0.896267f,0.018385f, +0.94592f,0.832727f,0.018815f,0.896749f,0.896267f,0.018385f,0.87333f,0.872793f,0.036675f,0.914973f,0.816749f,0.037876f, +0.887941f,0.728563f,0.058224f,0.945745f,0.735189f,0.040237f,0.914973f,0.816749f,0.037876f,0.866523f,0.804853f,0.054004f, +0.866523f,0.804853f,0.054004f,0.914973f,0.816749f,0.037876f,0.87333f,0.872793f,0.036675f,0.846982f,0.846382f,0.050154f, +0.396693f,0.917941f,0.064218f,0.397559f,0.849503f,0.074693f,0.618351f,0.83969f,0.071886f,0.616423f,0.905582f,0.061789f, +0.397559f,0.849503f,0.074693f,0.399509f,0.756465f,0.082561f,0.622688f,0.749446f,0.079479f,0.618351f,0.83969f,0.071886f, +0.618351f,0.83969f,0.071886f,0.622688f,0.749446f,0.079479f,0.741819f,0.740507f,0.074426f,0.733736f,0.826251f,0.067487f, +0.616423f,0.905582f,0.061789f,0.618351f,0.83969f,0.071886f,0.733736f,0.826251f,0.067487f,0.729904f,0.887439f,0.058224f, +0.399509f,0.756465f,0.082561f,0.401892f,0.629367f,0.088189f,0.62799f,0.625019f,0.084918f,0.622688f,0.749446f,0.079479f, +0.401892f,0.629367f,0.088189f,0.403842f,0.396564f,0.09157f,0.632327f,0.394595f,0.088189f,0.62799f,0.625019f,0.084918f, +0.62799f,0.625019f,0.084918f,0.632327f,0.394595f,0.088189f,0.757739f,0.392188f,0.082561f,0.750737f,0.619705f,0.079479f, +0.622688f,0.749446f,0.079479f,0.62799f,0.625019f,0.084918f,0.750737f,0.619705f,0.079479f,0.741819f,0.740507f,0.074426f, +0.741819f,0.740507f,0.074426f,0.750737f,0.619705f,0.079479f,0.840305f,0.615357f,0.071886f,0.826898f,0.732405f,0.067487f, +0.750737f,0.619705f,0.079479f,0.757739f,0.392188f,0.082561f,0.850096f,0.390218f,0.074693f,0.840305f,0.615357f,0.071886f, +0.840305f,0.615357f,0.071886f,0.850096f,0.390218f,0.074693f,0.918372f,0.389343f,0.064218f,0.906041f,0.613425f,0.061789f, +0.826898f,0.732405f,0.067487f,0.840305f,0.615357f,0.071886f,0.906041f,0.613425f,0.061789f,0.887941f,0.728563f,0.058224f, +0.729904f,0.887439f,0.058224f,0.733736f,0.826251f,0.067487f,0.812784f,0.812104f,0.061777f,0.805551f,0.865969f,0.054004f, +0.733736f,0.826251f,0.067487f,0.741819f,0.740507f,0.074426f,0.826898f,0.732405f,0.067487f,0.812784f,0.812104f,0.061777f, +0.812784f,0.812104f,0.061777f,0.826898f,0.732405f,0.067487f,0.887941f,0.728563f,0.058224f,0.866523f,0.804853f,0.054004f, +0.805551f,0.865969f,0.054004f,0.812784f,0.812104f,0.061777f,0.866523f,0.804853f,0.054004f,0.846982f,0.846382f,0.050154f, +0.399509f,0.756465f,0.082561f,0.397559f,0.849503f,0.074693f,0.002293f,0.852774f,0.075629f,0.002284f,0.758804f,0.083588f, +0.397559f,0.849503f,0.074693f,0.396693f,0.917941f,0.064218f,0.002297f,0.922061f,0.065028f,0.002293f,0.852774f,0.075629f, +0.002293f,0.852774f,0.075629f,0.002297f,0.922061f,0.065028f,-0.392243f,0.917941f,0.064218f,-0.39312f,0.849503f,0.074693f, +0.002284f,0.758804f,0.083588f,0.002293f,0.852774f,0.075629f,-0.39312f,0.849503f,0.074693f,-0.395094f,0.756465f,0.082561f, +0.399509f,0.756465f,0.082561f,0.002284f,0.758804f,0.083588f,0.002274f,0.630816f,0.089279f,0.401892f,0.629367f,0.088189f, +0.002284f,0.758804f,0.083588f,-0.395094f,0.756465f,0.082561f,-0.397505f,0.629367f,0.088189f,0.002274f,0.630816f,0.089279f, +0.002274f,0.630816f,0.089279f,-0.397505f,0.629367f,0.088189f,-0.399478f,0.396564f,0.09157f,0.002265f,0.397221f,0.092698f, +0.401892f,0.629367f,0.088189f,0.002274f,0.630816f,0.089279f,0.002265f,0.397221f,0.092698f,0.403842f,0.396564f,0.09157f, +-0.916591f,0.389343f,0.064218f,-0.847646f,0.390218f,0.074693f,-0.837759f,0.615357f,0.071886f,-0.90414f,0.613425f,0.061789f, +-0.847646f,0.390218f,0.074693f,-0.754564f,0.392188f,0.082561f,-0.747494f,0.619705f,0.079479f,-0.837759f,0.615357f,0.071886f, +-0.837759f,0.615357f,0.071886f,-0.747494f,0.619705f,0.079479f,-0.738488f,0.740507f,0.074426f,-0.824221f,0.732405f,0.067487f, +-0.90414f,0.613425f,0.061789f,-0.837759f,0.615357f,0.071886f,-0.824221f,0.732405f,0.067487f,-0.885862f,0.728563f,0.058224f, +-0.754564f,0.392188f,0.082561f,-0.628465f,0.394595f,0.088189f,-0.624085f,0.625019f,0.084918f,-0.747494f,0.619705f,0.079479f, +-0.628465f,0.394595f,0.088189f,-0.399478f,0.396564f,0.09157f,-0.397505f,0.629367f,0.088189f,-0.624085f,0.625019f,0.084918f, +-0.624085f,0.625019f,0.084918f,-0.397505f,0.629367f,0.088189f,-0.395094f,0.756465f,0.082561f,-0.618732f,0.749446f,0.079479f, +-0.747494f,0.619705f,0.079479f,-0.624085f,0.625019f,0.084918f,-0.618732f,0.749446f,0.079479f,-0.738488f,0.740507f,0.074426f, +-0.738488f,0.740507f,0.074426f,-0.618732f,0.749446f,0.079479f,-0.614352f,0.83969f,0.071886f,-0.730326f,0.826251f,0.067487f, +-0.618732f,0.749446f,0.079479f,-0.395094f,0.756465f,0.082561f,-0.39312f,0.849503f,0.074693f,-0.614352f,0.83969f,0.071886f, +-0.614352f,0.83969f,0.071886f,-0.39312f,0.849503f,0.074693f,-0.392243f,0.917941f,0.064218f,-0.612405f,0.905582f,0.061789f, +-0.730326f,0.826251f,0.067487f,-0.614352f,0.83969f,0.071886f,-0.612405f,0.905582f,0.061789f,-0.726455f,0.887439f,0.058224f, +-0.885862f,0.728563f,0.058224f,-0.824221f,0.732405f,0.067487f,-0.809968f,0.812104f,0.061777f,-0.864233f,0.804853f,0.054004f, +-0.824221f,0.732405f,0.067487f,-0.738488f,0.740507f,0.074426f,-0.730326f,0.826251f,0.067487f,-0.809968f,0.812104f,0.061777f, +-0.809968f,0.812104f,0.061777f,-0.730326f,0.826251f,0.067487f,-0.726455f,0.887439f,0.058224f,-0.802664f,0.865969f,0.054004f, +-0.864233f,0.804853f,0.054004f,-0.809968f,0.812104f,0.061777f,-0.802664f,0.865969f,0.054004f,-0.844501f,0.846382f,0.050154f, +}; + +static const float cfGameIconTexCoords[] = { +0.098918f,0.907702f,0.118783f,0.916444f,0.115314f,0.892403f,0.089549f,0.889167f, +0.118783f,0.916444f,0.154967f,0.926026f,0.153129f,0.898717f,0.115314f,0.892403f, +0.115314f,0.892403f,0.153129f,0.898717f,0.149254f,0.859921f,0.108547f,0.856305f, +0.089549f,0.889167f,0.115314f,0.892403f,0.108547f,0.856305f,0.07928f,0.854591f, +0.154967f,0.926026f,0.209119f,0.934124f,0.208194f,0.904715f,0.153129f,0.898717f, +0.209119f,0.934124f,0.313652f,0.93964f,0.313236f,0.909095f,0.208194f,0.904715f, +0.208194f,0.904715f,0.313236f,0.909095f,0.312299f,0.867044f,0.206115f,0.863911f, +0.153129f,0.898717f,0.208194f,0.904715f,0.206115f,0.863911f,0.149254f,0.859921f, +0.149254f,0.859921f,0.206115f,0.863911f,0.203573f,0.806797f,0.144978f,0.804425f, +0.206115f,0.863911f,0.312299f,0.867044f,0.311154f,0.808737f,0.203573f,0.806797f, +0.203573f,0.806797f,0.311154f,0.808737f,0.310217f,0.699784f,0.201493f,0.698917f, +0.144978f,0.804425f,0.203573f,0.806797f,0.201493f,0.698917f,0.141621f,0.697857f, +0.07928f,0.854591f,0.108547f,0.856305f,0.102119f,0.802484f,0.070602f,0.801622f, +0.108547f,0.856305f,0.149254f,0.859921f,0.144978f,0.804425f,0.102119f,0.802484f, +0.102119f,0.802484f,0.144978f,0.804425f,0.141621f,0.697857f,0.097425f,0.69699f, +0.070602f,0.801622f,0.102119f,0.802484f,0.097425f,0.69699f,0.064689f,0.696604f, +0.310217f,0.699784f,0.311154f,0.808737f,0.500971f,0.809384f,0.500967f,0.700073f, +0.311154f,0.808737f,0.312299f,0.867044f,0.500976f,0.868088f,0.500971f,0.809384f, +0.500971f,0.809384f,0.500976f,0.868088f,0.68958f,0.867044f,0.690711f,0.808737f, +0.500967f,0.700073f,0.500971f,0.809384f,0.690711f,0.808737f,0.691637f,0.699784f, +0.312299f,0.867044f,0.313236f,0.909095f,0.50098f,0.910555f,0.500976f,0.868088f, +0.313236f,0.909095f,0.313652f,0.93964f,0.500982f,0.941479f,0.50098f,0.910555f, +0.50098f,0.910555f,0.500982f,0.941479f,0.688243f,0.93964f,0.688654f,0.909095f, +0.500976f,0.868088f,0.50098f,0.910555f,0.688654f,0.909095f,0.68958f,0.867044f, +0.310217f,0.699784f,0.500967f,0.700073f,0.500965f,0.505784f,0.309905f,0.505792f, +0.500967f,0.700073f,0.691637f,0.699784f,0.691946f,0.505792f,0.500965f,0.505784f, +0.500965f,0.505784f,0.691946f,0.505792f,0.691637f,0.311325f,0.500967f,0.311013f, +0.309905f,0.505792f,0.500965f,0.505784f,0.500967f,0.311013f,0.310217f,0.311325f, +0.141621f,0.3134f,0.097425f,0.314333f,0.09586f,0.50587f,0.140502f,0.505846f, +0.097425f,0.314333f,0.064689f,0.314748f,0.062719f,0.505881f,0.09586f,0.50587f, +0.09586f,0.50587f,0.062719f,0.505881f,0.064689f,0.696604f,0.097425f,0.69699f, +0.140502f,0.505846f,0.09586f,0.50587f,0.097425f,0.69699f,0.141621f,0.697857f, +0.141621f,0.3134f,0.140502f,0.505846f,0.2008f,0.505816f,0.201493f,0.312259f, +0.140502f,0.505846f,0.141621f,0.697857f,0.201493f,0.698917f,0.2008f,0.505816f, +0.2008f,0.505816f,0.201493f,0.698917f,0.310217f,0.699784f,0.309905f,0.505792f, +0.201493f,0.312259f,0.2008f,0.505816f,0.309905f,0.505792f,0.310217f,0.311325f, +0.098918f,0.098051f,0.118783f,0.088764f,0.115314f,0.070013f,0.089549f,0.088764f, +0.118783f,0.088764f,0.154967f,0.078585f,0.153129f,0.056238f,0.115314f,0.070013f, +0.115314f,0.070013f,0.153129f,0.056238f,0.14647f,0.030613f,0.104205f,0.048635f, +0.089549f,0.088764f,0.115314f,0.070013f,0.104205f,0.048635f,0.073229f,0.072587f, +0.154967f,0.078585f,0.209119f,0.069983f,0.208194f,0.045626f,0.153129f,0.056238f, +0.209119f,0.069983f,0.313652f,0.064123f,0.313236f,0.038853f,0.208194f,0.045626f, +0.208194f,0.045626f,0.313236f,0.038853f,0.31157f,0.009921f,0.204497f,0.017695f, +0.153129f,0.056238f,0.208194f,0.045626f,0.204497f,0.017695f,0.14647f,0.030613f, +0.204497f,0.017695f,0.31157f,0.009921f,0.269666f,0.0f,0.202648f,0.01068f, +0.14647f,0.030613f,0.204497f,0.017695f,0.202648f,0.01068f,0.135631f,0.02136f, +0.104205f,0.048635f,0.14647f,0.030613f,0.135631f,0.02136f,0.100033f,0.042615f, +0.073229f,0.072587f,0.104205f,0.048635f,0.100033f,0.042615f,0.064435f,0.06387f, +0.269666f,0.0f,0.31157f,0.009921f,0.500973f,0.007329f,0.500969f,0.0f, +0.500973f,0.007329f,0.31157f,0.009921f,0.313236f,0.038853f,0.50098f,0.036595f, +0.6903f,0.009921f,0.500973f,0.007329f,0.50098f,0.036595f,0.688654f,0.038853f, +0.500969f,0.0f,0.500973f,0.007329f,0.6903f,0.009921f,0.732272f,0.0f, +0.313236f,0.038853f,0.313652f,0.064123f,0.500982f,0.062169f,0.50098f,0.036595f, +0.50098f,0.036595f,0.500982f,0.062169f,0.688243f,0.064123f,0.688654f,0.038853f, +0.688243f,0.93964f,0.500982f,0.941479f,0.50098f,0.965553f,0.688654f,0.963427f, +0.500982f,0.941479f,0.313652f,0.93964f,0.313236f,0.963427f,0.50098f,0.965553f, +0.50098f,0.965553f,0.313236f,0.963427f,0.31157f,0.990661f,0.500973f,0.993101f, +0.688654f,0.963427f,0.50098f,0.965553f,0.500973f,0.993101f,0.6903f,0.990661f, +0.31157f,0.990661f,0.269666f,1.0f,0.500969f,1.0f,0.500973f,0.993101f, +0.500973f,0.993101f,0.500969f,1.0f,0.732272f,1.0f,0.6903f,0.990661f, +0.064435f,0.939877f,0.100033f,0.959885f,0.104205f,0.954218f,0.073229f,0.931672f, +0.100033f,0.959885f,0.135631f,0.979893f,0.14647f,0.971183f,0.104205f,0.954218f, +0.104205f,0.954218f,0.14647f,0.971183f,0.153129f,0.947062f,0.115314f,0.934095f, +0.073229f,0.931672f,0.104205f,0.954218f,0.115314f,0.934095f,0.089549f,0.916444f, +0.135631f,0.979893f,0.202648f,0.989946f,0.204497f,0.983343f,0.14647f,0.971183f, +0.202648f,0.989946f,0.269666f,1.0f,0.31157f,0.990661f,0.204497f,0.983343f, +0.204497f,0.983343f,0.31157f,0.990661f,0.313236f,0.963427f,0.208194f,0.957052f, +0.14647f,0.971183f,0.204497f,0.983343f,0.208194f,0.957052f,0.153129f,0.947062f, +0.208194f,0.957052f,0.313236f,0.963427f,0.313652f,0.93964f,0.209119f,0.934124f, +0.153129f,0.947062f,0.208194f,0.957052f,0.209119f,0.934124f,0.154967f,0.926026f, +0.115314f,0.934095f,0.153129f,0.947062f,0.154967f,0.926026f,0.118783f,0.916444f, +0.089549f,0.916444f,0.115314f,0.934095f,0.118783f,0.916444f,0.098918f,0.907702f, +0.902043f,0.907702f,0.91132f,0.916444f,0.930054f,0.892403f,0.91132f,0.889167f, +0.930054f,0.892403f,0.91132f,0.916444f,0.927482f,0.931672f,0.951411f,0.902768f, +0.943816f,0.856305f,0.930054f,0.892403f,0.951411f,0.902768f,0.969416f,0.862518f, +0.91132f,0.889167f,0.930054f,0.892403f,0.943816f,0.856305f,0.92149f,0.854591f, +0.927482f,0.931672f,0.93619f,0.939877f,0.957425f,0.906662f,0.951411f,0.902768f, +0.951411f,0.902768f,0.957425f,0.906662f,0.97866f,0.873446f,0.969416f,0.862518f, +0.943816f,0.856305f,0.969416f,0.862518f,0.982322f,0.805934f,0.954418f,0.802484f, +0.969416f,0.862518f,0.97866f,0.873446f,0.98933f,0.807659f,0.982322f,0.805934f, +0.982322f,0.805934f,0.98933f,0.807659f,1.0f,0.741872f,0.990089f,0.698531f, +0.982322f,0.805934f,0.990089f,0.698531f,0.961185f,0.69699f,0.954418f,0.802484f, +0.92149f,0.854591f,0.943816f,0.856305f,0.954418f,0.802484f,0.930084f,0.801622f, +0.930084f,0.801622f,0.954418f,0.802484f,0.961185f,0.69699f,0.935938f,0.696604f, +0.935938f,0.696604f,0.961185f,0.69699f,0.96344f,0.50587f,0.93789f,0.505881f, +0.96344f,0.50587f,0.961185f,0.69699f,0.990089f,0.698531f,0.992677f,0.505827f, +0.961185f,0.314333f,0.96344f,0.50587f,0.992677f,0.505827f,0.990089f,0.312674f, +0.93789f,0.505881f,0.96344f,0.50587f,0.961185f,0.314333f,0.935938f,0.314748f, +0.990089f,0.698531f,1.0f,0.741872f,1.0f,0.505805f,0.992677f,0.505827f, +0.992677f,0.505827f,1.0f,0.505805f,1.0f,0.269739f,0.990089f,0.312674f, +0.064435f,0.939877f,0.073229f,0.931672f,0.049066f,0.902768f,0.042992f,0.906662f, +0.049066f,0.902768f,0.073229f,0.931672f,0.089549f,0.916444f,0.070633f,0.892403f, +0.030884f,0.862518f,0.049066f,0.902768f,0.070633f,0.892403f,0.056735f,0.856305f, +0.042992f,0.906662f,0.049066f,0.902768f,0.030884f,0.862518f,0.021549f,0.873446f, +0.089549f,0.916444f,0.098918f,0.907702f,0.089549f,0.889167f,0.070633f,0.892403f, +0.070633f,0.892403f,0.089549f,0.889167f,0.07928f,0.854591f,0.056735f,0.856305f, +0.030884f,0.862518f,0.056735f,0.856305f,0.046029f,0.802484f,0.017852f,0.805934f, +0.056735f,0.856305f,0.07928f,0.854591f,0.070602f,0.801622f,0.046029f,0.802484f, +0.046029f,0.802484f,0.070602f,0.801622f,0.064689f,0.696604f,0.039196f,0.69699f, +0.046029f,0.802484f,0.039196f,0.69699f,0.010008f,0.698531f,0.017852f,0.805934f, +0.021549f,0.873446f,0.030884f,0.862518f,0.017852f,0.805934f,0.010774f,0.807659f, +0.010774f,0.807659f,0.017852f,0.805934f,0.010008f,0.698531f,0.0f,0.741872f, +0.0f,0.269739f,0.0f,0.505805f,0.007394f,0.505827f,0.010008f,0.312673f, +0.0f,0.505805f,0.0f,0.741872f,0.010008f,0.698531f,0.007394f,0.505827f, +0.007394f,0.505827f,0.010008f,0.698531f,0.039196f,0.69699f,0.036918f,0.50587f, +0.010008f,0.312673f,0.007394f,0.505827f,0.036918f,0.50587f,0.039196f,0.314333f, +0.039196f,0.69699f,0.064689f,0.696604f,0.062719f,0.505881f,0.036918f,0.50587f, +0.036918f,0.50587f,0.062719f,0.505881f,0.064689f,0.314748f,0.039196f,0.314333f, +0.688243f,0.064123f,0.792572f,0.069983f,0.793487f,0.045626f,0.688654f,0.038853f, +0.792572f,0.069983f,0.846453f,0.078585f,0.848273f,0.056238f,0.793487f,0.045626f, +0.793487f,0.045626f,0.848273f,0.056238f,0.854867f,0.030613f,0.797148f,0.017695f, +0.6903f,0.009921f,0.688654f,0.038853f,0.793487f,0.045626f,0.797148f,0.017695f, +0.846453f,0.078585f,0.882371f,0.088764f,0.885805f,0.070013f,0.848273f,0.056238f, +0.882371f,0.088764f,0.902043f,0.098051f,0.91132f,0.088764f,0.885805f,0.070013f, +0.885805f,0.070013f,0.91132f,0.088764f,0.927482f,0.072587f,0.896806f,0.048635f, +0.848273f,0.056238f,0.885805f,0.070013f,0.896806f,0.048635f,0.854867f,0.030613f, +0.896806f,0.048635f,0.927482f,0.072587f,0.93619f,0.06387f,0.900938f,0.042615f, +0.854867f,0.030613f,0.896806f,0.048635f,0.900938f,0.042615f,0.865686f,0.02136f, +0.797148f,0.017695f,0.854867f,0.030613f,0.865686f,0.02136f,0.798979f,0.01068f, +0.6903f,0.009921f,0.797148f,0.017695f,0.798979f,0.01068f,0.732272f,0.0f, +0.688243f,0.93964f,0.688654f,0.963427f,0.793487f,0.957052f,0.792572f,0.934124f, +0.793487f,0.957052f,0.688654f,0.963427f,0.6903f,0.990661f,0.797148f,0.983343f, +0.848273f,0.947062f,0.793487f,0.957052f,0.797148f,0.983343f,0.854867f,0.971183f, +0.792572f,0.934124f,0.793487f,0.957052f,0.848273f,0.947062f,0.846453f,0.926026f, +0.6903f,0.990661f,0.732272f,1.0f,0.798979f,0.989946f,0.797148f,0.983343f, +0.797148f,0.983343f,0.798979f,0.989946f,0.865686f,0.979893f,0.854867f,0.971183f, +0.848273f,0.947062f,0.854867f,0.971183f,0.896806f,0.954218f,0.885805f,0.934095f, +0.854867f,0.971183f,0.865686f,0.979893f,0.900938f,0.959885f,0.896806f,0.954218f, +0.896806f,0.954218f,0.900938f,0.959885f,0.93619f,0.939877f,0.927482f,0.931672f, +0.896806f,0.954218f,0.927482f,0.931672f,0.91132f,0.916444f,0.885805f,0.934095f, +0.846453f,0.926026f,0.848273f,0.947062f,0.885805f,0.934095f,0.882371f,0.916444f, +0.882371f,0.916444f,0.885805f,0.934095f,0.91132f,0.916444f,0.902043f,0.907702f, +0.691637f,0.699784f,0.690711f,0.808737f,0.798063f,0.806796f,0.800123f,0.698917f, +0.690711f,0.808737f,0.68958f,0.867044f,0.795546f,0.863911f,0.798063f,0.806796f, +0.798063f,0.806796f,0.795546f,0.863911f,0.85211f,0.859921f,0.856345f,0.804425f, +0.800123f,0.698917f,0.798063f,0.806796f,0.856345f,0.804425f,0.859669f,0.697857f, +0.68958f,0.867044f,0.688654f,0.909095f,0.793487f,0.904715f,0.795546f,0.863911f, +0.688654f,0.909095f,0.688243f,0.93964f,0.792572f,0.934124f,0.793487f,0.904715f, +0.793487f,0.904715f,0.792572f,0.934124f,0.846453f,0.926026f,0.848273f,0.898717f, +0.795546f,0.863911f,0.793487f,0.904715f,0.848273f,0.898717f,0.85211f,0.859921f, +0.85211f,0.859921f,0.848273f,0.898717f,0.885805f,0.892403f,0.892507f,0.856305f, +0.848273f,0.898717f,0.846453f,0.926026f,0.882371f,0.916444f,0.885805f,0.892403f, +0.885805f,0.892403f,0.882371f,0.916444f,0.902043f,0.907702f,0.91132f,0.889167f, +0.892507f,0.856305f,0.885805f,0.892403f,0.91132f,0.889167f,0.92149f,0.854591f, +0.859669f,0.697857f,0.856345f,0.804425f,0.898872f,0.802484f,0.903521f,0.69699f, +0.856345f,0.804425f,0.85211f,0.859921f,0.892507f,0.856305f,0.898872f,0.802484f, +0.898872f,0.802484f,0.892507f,0.856305f,0.92149f,0.854591f,0.930084f,0.801622f, +0.903521f,0.69699f,0.898872f,0.802484f,0.930084f,0.801622f,0.935938f,0.696604f, +0.691637f,0.311325f,0.691946f,0.505792f,0.800809f,0.505816f,0.800123f,0.312259f, +0.691946f,0.505792f,0.691637f,0.699784f,0.800123f,0.698917f,0.800809f,0.505816f, +0.800809f,0.505816f,0.800123f,0.698917f,0.859669f,0.697857f,0.860777f,0.505846f, +0.800123f,0.312259f,0.800809f,0.505816f,0.860777f,0.505846f,0.859669f,0.3134f, +0.859669f,0.697857f,0.903521f,0.69699f,0.90507f,0.50587f,0.860777f,0.505846f, +0.903521f,0.69699f,0.935938f,0.696604f,0.93789f,0.505881f,0.90507f,0.50587f, +0.90507f,0.50587f,0.93789f,0.505881f,0.935938f,0.314748f,0.903521f,0.314333f, +0.860777f,0.505846f,0.90507f,0.50587f,0.903521f,0.314333f,0.859669f,0.3134f, +0.0f,0.269739f,0.010008f,0.312673f,0.017852f,0.203923f,0.010774f,0.202091f, +0.017852f,0.203923f,0.010008f,0.312673f,0.039196f,0.314333f,0.046029f,0.207588f, +0.030884f,0.14549f,0.017852f,0.203923f,0.046029f,0.207588f,0.056735f,0.152091f, +0.010774f,0.202091f,0.017852f,0.203923f,0.030884f,0.14549f,0.021549f,0.134442f, +0.039196f,0.314333f,0.064689f,0.314748f,0.070602f,0.208504f,0.046029f,0.207588f, +0.046029f,0.207588f,0.070602f,0.208504f,0.07928f,0.153913f,0.056735f,0.152091f, +0.030884f,0.14549f,0.056735f,0.152091f,0.070632f,0.114303f,0.049066f,0.103292f, +0.056735f,0.152091f,0.07928f,0.153913f,0.089549f,0.117742f,0.070632f,0.114303f, +0.070632f,0.114303f,0.089549f,0.117742f,0.098918f,0.098051f,0.089549f,0.088764f, +0.070632f,0.114303f,0.089549f,0.088764f,0.073229f,0.072587f,0.049066f,0.103292f, +0.021549f,0.134442f,0.030884f,0.14549f,0.049066f,0.103292f,0.042992f,0.099156f, +0.042992f,0.099156f,0.049066f,0.103292f,0.073229f,0.072587f,0.064435f,0.06387f, +0.935938f,0.314748f,0.961185f,0.314333f,0.954418f,0.207588f,0.930084f,0.208504f, +0.954418f,0.207588f,0.961185f,0.314333f,0.990089f,0.312674f,0.982322f,0.203923f, +0.943816f,0.152092f,0.954418f,0.207588f,0.982322f,0.203923f,0.969416f,0.145491f, +0.930084f,0.208504f,0.954418f,0.207588f,0.943816f,0.152092f,0.92149f,0.153913f, +0.990089f,0.312674f,1.0f,0.269739f,0.98933f,0.202091f,0.982322f,0.203923f, +0.982322f,0.203923f,0.98933f,0.202091f,0.97866f,0.134442f,0.969416f,0.145491f, +0.943816f,0.152092f,0.969416f,0.145491f,0.951411f,0.103292f,0.930054f,0.114304f, +0.969416f,0.145491f,0.97866f,0.134442f,0.957425f,0.099156f,0.951411f,0.103292f, +0.951411f,0.103292f,0.957425f,0.099156f,0.93619f,0.06387f,0.927482f,0.072587f, +0.951411f,0.103292f,0.927482f,0.072587f,0.91132f,0.088764f,0.930054f,0.114304f, +0.92149f,0.153913f,0.943816f,0.152092f,0.930054f,0.114304f,0.91132f,0.117742f, +0.91132f,0.117742f,0.930054f,0.114304f,0.91132f,0.088764f,0.902043f,0.098051f, +0.688243f,0.064123f,0.688654f,0.096571f,0.793487f,0.101224f,0.792572f,0.069983f, +0.688654f,0.096571f,0.68958f,0.140684f,0.795546f,0.144012f,0.793487f,0.101224f, +0.793487f,0.101224f,0.795546f,0.144012f,0.85211f,0.14825f,0.848273f,0.107596f, +0.792572f,0.069983f,0.793487f,0.101224f,0.848273f,0.107596f,0.846453f,0.078585f, +0.68958f,0.140684f,0.690711f,0.200945f,0.798063f,0.203007f,0.795546f,0.144012f, +0.690711f,0.200945f,0.691637f,0.311325f,0.800123f,0.312259f,0.798063f,0.203007f, +0.798063f,0.203007f,0.800123f,0.312259f,0.859669f,0.3134f,0.856345f,0.205526f, +0.795546f,0.144012f,0.798063f,0.203007f,0.856345f,0.205526f,0.85211f,0.14825f, +0.85211f,0.14825f,0.856345f,0.205526f,0.898872f,0.207588f,0.892507f,0.152092f, +0.856345f,0.205526f,0.859669f,0.3134f,0.903521f,0.314333f,0.898872f,0.207588f, +0.898872f,0.207588f,0.903521f,0.314333f,0.935938f,0.314748f,0.930084f,0.208504f, +0.892507f,0.152092f,0.898872f,0.207588f,0.930084f,0.208504f,0.92149f,0.153913f, +0.846453f,0.078585f,0.848273f,0.107596f,0.885805f,0.114304f,0.882371f,0.088764f, +0.848273f,0.107596f,0.85211f,0.14825f,0.892507f,0.152092f,0.885805f,0.114304f, +0.885805f,0.114304f,0.892507f,0.152092f,0.92149f,0.153913f,0.91132f,0.117742f, +0.882371f,0.088764f,0.885805f,0.114304f,0.91132f,0.117742f,0.902043f,0.098051f, +0.68958f,0.140684f,0.688654f,0.096571f,0.50098f,0.095021f,0.500976f,0.139575f, +0.688654f,0.096571f,0.688243f,0.064123f,0.500982f,0.062169f,0.50098f,0.095021f, +0.50098f,0.095021f,0.500982f,0.062169f,0.313652f,0.064123f,0.313236f,0.096571f, +0.500976f,0.139575f,0.50098f,0.095021f,0.313236f,0.096571f,0.312299f,0.140684f, +0.68958f,0.140684f,0.500976f,0.139575f,0.500971f,0.200258f,0.690711f,0.200945f, +0.500976f,0.139575f,0.312299f,0.140684f,0.311154f,0.200945f,0.500971f,0.200258f, +0.500971f,0.200258f,0.311154f,0.200945f,0.310217f,0.311325f,0.500967f,0.311013f, +0.690711f,0.200945f,0.500971f,0.200258f,0.500967f,0.311013f,0.691637f,0.311325f, +0.064689f,0.314748f,0.097425f,0.314333f,0.102119f,0.207588f,0.070602f,0.208504f, +0.097425f,0.314333f,0.141621f,0.3134f,0.144978f,0.205526f,0.102119f,0.207588f, +0.102119f,0.207588f,0.144978f,0.205526f,0.149254f,0.14825f,0.108547f,0.152092f, +0.070602f,0.208504f,0.102119f,0.207588f,0.108547f,0.152092f,0.07928f,0.153913f, +0.141621f,0.3134f,0.201493f,0.312259f,0.203573f,0.203007f,0.144978f,0.205526f, +0.201493f,0.312259f,0.310217f,0.311325f,0.311154f,0.200945f,0.203573f,0.203007f, +0.203573f,0.203007f,0.311154f,0.200945f,0.312299f,0.140684f,0.206115f,0.144012f, +0.144978f,0.205526f,0.203573f,0.203007f,0.206115f,0.144012f,0.149254f,0.14825f, +0.149254f,0.14825f,0.206115f,0.144012f,0.208194f,0.101224f,0.153129f,0.107596f, +0.206115f,0.144012f,0.312299f,0.140684f,0.313236f,0.096571f,0.208194f,0.101224f, +0.208194f,0.101224f,0.313236f,0.096571f,0.313652f,0.064123f,0.209119f,0.069983f, +0.153129f,0.107596f,0.208194f,0.101224f,0.209119f,0.069983f,0.154967f,0.078585f, +0.07928f,0.153913f,0.108547f,0.152092f,0.115314f,0.114304f,0.089549f,0.117742f, +0.108547f,0.152092f,0.149254f,0.14825f,0.153129f,0.107596f,0.115314f,0.114304f, +0.115314f,0.114304f,0.153129f,0.107596f,0.154967f,0.078585f,0.118783f,0.088764f, +0.089549f,0.117742f,0.115314f,0.114304f,0.118783f,0.088764f,0.098918f,0.098051f, +}; + +static const float cfGameIconNormals[] = { +-0.210457f,-0.226211f,0.951071f,-0.137777f,-0.231234f,0.963093f,-0.113627f,-0.120055f,0.986243f,-0.216181f,-0.146015f,0.965373f, +-0.137777f,-0.231234f,0.963093f,-0.083714f,-0.234126f,0.968595f,-0.06603f,-0.119508f,0.990635f,-0.113627f,-0.120055f,0.986243f, +-0.113627f,-0.120055f,0.986243f,-0.06603f,-0.119508f,0.990635f,-0.062379f,-0.064577f,0.995961f,-0.113032f,-0.068284f,0.991242f, +-0.216181f,-0.146015f,0.965373f,-0.113627f,-0.120055f,0.986243f,-0.113032f,-0.068284f,0.991242f,-0.219508f,-0.086774f,0.971744f, +-0.083714f,-0.234126f,0.968595f,-0.036722f,-0.235389f,0.971207f,-0.028482f,-0.119193f,0.992463f,-0.06603f,-0.119508f,0.990635f, +-0.036722f,-0.235389f,0.971207f,-0.010823f,-0.235649f,0.971778f,-0.008321f,-0.119124f,0.992845f,-0.028482f,-0.119193f,0.992463f, +-0.028482f,-0.119193f,0.992463f,-0.008321f,-0.119124f,0.992845f,-0.007465f,-0.063717f,0.99794f,-0.026099f,-0.06375f,0.997625f, +-0.06603f,-0.119508f,0.990635f,-0.028482f,-0.119193f,0.992463f,-0.026099f,-0.06375f,0.997625f,-0.062379f,-0.064577f,0.995961f, +-0.062379f,-0.064577f,0.995961f,-0.026099f,-0.06375f,0.997625f,-0.025391f,-0.025563f,0.999351f,-0.061589f,-0.026301f,0.997755f, +-0.026099f,-0.06375f,0.997625f,-0.007465f,-0.063717f,0.99794f,-0.007172f,-0.02556f,0.999648f,-0.025391f,-0.025563f,0.999351f, +-0.025391f,-0.025563f,0.999351f,-0.007172f,-0.02556f,0.999648f,-0.007161f,-0.00707f,0.999949f,-0.025395f,-0.007088f,0.999652f, +-0.061589f,-0.026301f,0.997755f,-0.025391f,-0.025563f,0.999351f,-0.025395f,-0.007088f,0.999652f,-0.061548f,-0.00739f,0.998077f, +-0.219508f,-0.086774f,0.971744f,-0.113032f,-0.068284f,0.991242f,-0.112752f,-0.028685f,0.993209f,-0.22077f,-0.037047f,0.974622f, +-0.113032f,-0.068284f,0.991242f,-0.062379f,-0.064577f,0.995961f,-0.061589f,-0.026301f,0.997755f,-0.112752f,-0.028685f,0.993209f, +-0.112752f,-0.028685f,0.993209f,-0.061589f,-0.026301f,0.997755f,-0.061548f,-0.00739f,0.998077f,-0.112673f,-0.008234f,0.993598f, +-0.22077f,-0.037047f,0.974622f,-0.112752f,-0.028685f,0.993209f,-0.112673f,-0.008234f,0.993598f,-0.221f,-0.010721f,0.975215f, +-0.007161f,-0.00707f,0.999949f,-0.007172f,-0.02556f,0.999648f,0.0f,-0.025624f,0.999672f,0.0f,-0.007089f,0.999975f, +-0.007172f,-0.02556f,0.999648f,-0.007465f,-0.063717f,0.99794f,0.0f,-0.06378f,0.997964f,0.0f,-0.025624f,0.999672f, +0.0f,-0.025624f,0.999672f,0.0f,-0.06378f,0.997964f,0.007472f,-0.063716f,0.99794f,0.007179f,-0.025559f,0.999648f, +0.0f,-0.007089f,0.999975f,0.0f,-0.025624f,0.999672f,0.007179f,-0.025559f,0.999648f,0.007169f,-0.00707f,0.999949f, +-0.007465f,-0.063717f,0.99794f,-0.008321f,-0.119124f,0.992845f,0.0f,-0.119133f,0.992878f,0.0f,-0.06378f,0.997964f, +-0.008321f,-0.119124f,0.992845f,-0.010823f,-0.235649f,0.971778f,0.0f,-0.235564f,0.971859f,0.0f,-0.119133f,0.992878f, +0.0f,-0.119133f,0.992878f,0.0f,-0.235564f,0.971859f,0.010835f,-0.23565f,0.971778f,0.008329f,-0.119124f,0.992845f, +0.0f,-0.06378f,0.997964f,0.0f,-0.119133f,0.992878f,0.008329f,-0.119124f,0.992845f,0.007472f,-0.063716f,0.99794f, +-0.007161f,-0.00707f,0.999949f,0.0f,-0.007089f,0.999975f,0.0f,0.0f,1.0f,-0.007181f,0.0f,0.999974f, +0.0f,-0.007089f,0.999975f,0.007169f,-0.00707f,0.999949f,0.007189f,0.0f,0.999974f,0.0f,0.0f,1.0f, +0.0f,0.0f,1.0f,0.007189f,0.0f,0.999974f,0.00717f,0.007027f,0.99995f,0.0f,0.007045f,0.999975f, +-0.007181f,0.0f,0.999974f,0.0f,0.0f,1.0f,0.0f,0.007045f,0.999975f,-0.007163f,0.007027f,0.99995f, +-0.061553f,0.007347f,0.998077f,-0.112675f,0.008187f,0.993598f,-0.112665f,0.0f,0.993633f,-0.061598f,0.0f,0.998101f, +-0.112675f,0.008187f,0.993598f,-0.220997f,0.010655f,0.975216f,-0.220914f,-1.0E-6f,0.975293f,-0.112665f,0.0f,0.993633f, +-0.112665f,0.0f,0.993633f,-0.220914f,-1.0E-6f,0.975293f,-0.221f,-0.010721f,0.975215f,-0.112673f,-0.008234f,0.993598f, +-0.061598f,0.0f,0.998101f,-0.112665f,0.0f,0.993633f,-0.112673f,-0.008234f,0.993598f,-0.061548f,-0.00739f,0.998077f, +-0.061553f,0.007347f,0.998077f,-0.061598f,0.0f,0.998101f,-0.025456f,0.0f,0.999676f,-0.025398f,0.007046f,0.999653f, +-0.061598f,0.0f,0.998101f,-0.061548f,-0.00739f,0.998077f,-0.025395f,-0.007088f,0.999652f,-0.025456f,0.0f,0.999676f, +-0.025456f,0.0f,0.999676f,-0.025395f,-0.007088f,0.999652f,-0.007161f,-0.00707f,0.999949f,-0.007181f,0.0f,0.999974f, +-0.025398f,0.007046f,0.999653f,-0.025456f,0.0f,0.999676f,-0.007181f,0.0f,0.999974f,-0.007163f,0.007027f,0.99995f, +-0.211482f,0.213152f,0.953856f,-0.138447f,0.218126f,0.966051f,-0.198978f,0.347214f,0.916433f,-0.296456f,0.298724f,0.907126f, +-0.138447f,0.218126f,0.966051f,-0.084089f,0.221062f,0.971628f,-0.117212f,0.361162f,0.925107f,-0.198978f,0.347214f,0.916433f, +-0.198978f,0.347214f,0.916433f,-0.117212f,0.361162f,0.925107f,-0.168084f,0.541107f,0.823985f,-0.282777f,0.494303f,0.822011f, +-0.296456f,0.298724f,0.907126f,-0.198978f,0.347214f,0.916433f,-0.282777f,0.494303f,0.822011f,-0.402197f,0.405178f,0.821017f, +-0.084089f,0.221062f,0.971628f,-0.036885f,0.222305f,0.974279f,-0.050723f,0.367918f,0.928474f,-0.117212f,0.361162f,0.925107f, +-0.036885f,0.222305f,0.974279f,-0.010867f,0.22256f,0.974858f,-0.014805f,0.369601f,0.929073f,-0.050723f,0.367918f,0.928474f, +-0.050723f,0.367918f,0.928474f,-0.014805f,0.369601f,0.929073f,-0.020782f,0.568602f,0.822351f,-0.072149f,0.563165f,0.823189f, +-0.117212f,0.361162f,0.925107f,-0.050723f,0.367918f,0.928474f,-0.072149f,0.563165f,0.823189f,-0.168084f,0.541107f,0.823985f, +-0.072149f,0.563165f,0.823189f,-0.020782f,0.568602f,0.822351f,-0.025372f,0.696348f,0.717256f,-0.088478f,0.684053f,0.724047f, +-0.168084f,0.541107f,0.823985f,-0.072149f,0.563165f,0.823189f,-0.088478f,0.684053f,0.724047f,-0.20294f,0.64707f,0.734926f, +-0.282777f,0.494303f,0.822011f,-0.168084f,0.541107f,0.823985f,-0.20294f,0.64707f,0.734926f,-0.333245f,0.577074f,0.745609f, +-0.402197f,0.405178f,0.821017f,-0.282777f,0.494303f,0.822011f,-0.333245f,0.577074f,0.745609f,-0.466013f,0.469045f,0.75022f, +-0.025372f,0.696348f,0.717256f,-0.020782f,0.568602f,0.822351f,0.0f,0.568694f,0.822549f,-2.0E-6f,0.698486f,0.715623f, +0.0f,0.568694f,0.822549f,-0.020782f,0.568602f,0.822351f,-0.014805f,0.369601f,0.929073f,0.0f,0.369504f,0.929229f, +0.020804f,0.568602f,0.82235f,0.0f,0.568694f,0.822549f,0.0f,0.369504f,0.929229f,0.01482f,0.369601f,0.929072f, +-2.0E-6f,0.698486f,0.715623f,0.0f,0.568694f,0.822549f,0.020804f,0.568602f,0.82235f,0.025388f,0.696365f,0.717239f, +-0.014805f,0.369601f,0.929073f,-0.010867f,0.22256f,0.974858f,0.0f,0.222477f,0.974938f,0.0f,0.369504f,0.929229f, +0.0f,0.369504f,0.929229f,0.0f,0.222477f,0.974938f,0.010878f,0.222561f,0.974858f,0.01482f,0.369601f,0.929072f, +0.010835f,-0.23565f,0.971778f,0.0f,-0.235564f,0.971859f,0.0f,-0.389089f,0.9212f,0.014687f,-0.38921f,0.921032f, +0.0f,-0.235564f,0.971859f,-0.010823f,-0.235649f,0.971778f,-0.014671f,-0.38921f,0.921032f,0.0f,-0.389089f,0.9212f, +0.0f,-0.389089f,0.9212f,-0.014671f,-0.38921f,0.921032f,-0.020367f,-0.591835f,0.805802f,0.0f,-0.591896f,0.806014f, +0.014687f,-0.38921f,0.921032f,0.0f,-0.389089f,0.9212f,0.0f,-0.591896f,0.806014f,0.020387f,-0.591837f,0.8058f, +-0.020367f,-0.591835f,0.805802f,-0.024675f,-0.717705f,0.69591f,-2.0E-6f,-0.719788f,0.694194f,0.0f,-0.591896f,0.806014f, +0.0f,-0.591896f,0.806014f,-2.0E-6f,-0.719788f,0.694194f,0.02469f,-0.717725f,0.695889f,0.020387f,-0.591837f,0.8058f, +-0.46128f,-0.48965f,0.739908f,-0.32814f,-0.599132f,0.730319f,-0.27855f,-0.517113f,0.809323f,-0.397988f,-0.425903f,0.812534f, +-0.32814f,-0.599132f,0.730319f,-0.198659f,-0.669215f,0.716021f,-0.165045f,-0.564346f,0.808872f,-0.27855f,-0.517113f,0.809323f, +-0.27855f,-0.517113f,0.809323f,-0.165045f,-0.564346f,0.808872f,-0.116165f,-0.380579f,0.917423f,-0.197289f,-0.366449f,0.909281f, +-0.397988f,-0.425903f,0.812534f,-0.27855f,-0.517113f,0.809323f,-0.197289f,-0.366449f,0.909281f,-0.294472f,-0.315809f,0.901971f, +-0.198659f,-0.669215f,0.716021f,-0.086339f,-0.705672f,0.703258f,-0.070739f,-0.586438f,0.806899f,-0.165045f,-0.564346f,0.808872f, +-0.086339f,-0.705672f,0.703258f,-0.024675f,-0.717705f,0.69591f,-0.020367f,-0.591835f,0.805802f,-0.070739f,-0.586438f,0.806899f, +-0.070739f,-0.586438f,0.806899f,-0.020367f,-0.591835f,0.805802f,-0.014671f,-0.38921f,0.921032f,-0.050259f,-0.387507f,0.920496f, +-0.165045f,-0.564346f,0.808872f,-0.070739f,-0.586438f,0.806899f,-0.050259f,-0.387507f,0.920496f,-0.116165f,-0.380579f,0.917423f, +-0.050259f,-0.387507f,0.920496f,-0.014671f,-0.38921f,0.921032f,-0.010823f,-0.235649f,0.971778f,-0.036722f,-0.235389f,0.971207f, +-0.116165f,-0.380579f,0.917423f,-0.050259f,-0.387507f,0.920496f,-0.036722f,-0.235389f,0.971207f,-0.083714f,-0.234126f,0.968595f, +-0.197289f,-0.366449f,0.909281f,-0.116165f,-0.380579f,0.917423f,-0.083714f,-0.234126f,0.968595f,-0.137777f,-0.231234f,0.963093f, +-0.294472f,-0.315809f,0.901971f,-0.197289f,-0.366449f,0.909281f,-0.137777f,-0.231234f,0.963093f,-0.210457f,-0.226211f,0.951071f, +0.212501f,-0.226048f,0.950655f,0.297154f,-0.315494f,0.901201f,0.347306f,-0.209845f,0.913971f,0.218237f,-0.145906f,0.964927f, +0.347306f,-0.209845f,0.913971f,0.297154f,-0.315494f,0.901201f,0.401261f,-0.425239f,0.811271f,0.493682f,-0.297695f,0.817102f, +0.362206f,-0.121013f,0.924209f,0.347306f,-0.209845f,0.913971f,0.493682f,-0.297695f,0.817102f,0.542487f,-0.173678f,0.821915f, +0.218237f,-0.145906f,0.964927f,0.347306f,-0.209845f,0.913971f,0.362206f,-0.121013f,0.924209f,0.221558f,-0.086713f,0.971284f, +0.401261f,-0.425239f,0.811271f,0.464547f,-0.488911f,0.738351f,0.57643f,-0.348399f,0.739153f,0.493682f,-0.297695f,0.817102f, +0.493682f,-0.297695f,0.817102f,0.57643f,-0.348399f,0.739153f,0.648687f,-0.208869f,0.731832f,0.542487f,-0.173678f,0.821915f, +0.362206f,-0.121013f,0.924209f,0.542487f,-0.173678f,0.821915f,0.564441f,-0.072486f,0.822285f,0.368823f,-0.050932f,0.928103f, +0.542487f,-0.173678f,0.821915f,0.648687f,-0.208869f,0.731832f,0.685633f,-0.08861f,0.722534f,0.564441f,-0.072486f,0.822285f, +0.564441f,-0.072486f,0.822285f,0.685633f,-0.08861f,0.722534f,0.697362f,-0.024953f,0.716285f,0.569527f,-0.020487f,0.821717f, +0.564441f,-0.072486f,0.822285f,0.569527f,-0.020487f,0.821717f,0.370348f,-0.014597f,0.928778f,0.368823f,-0.050932f,0.928103f, +0.221558f,-0.086713f,0.971284f,0.362206f,-0.121013f,0.924209f,0.368823f,-0.050932f,0.928103f,0.222823f,-0.037022f,0.974156f, +0.222823f,-0.037022f,0.974156f,0.368823f,-0.050932f,0.928103f,0.370348f,-0.014597f,0.928778f,0.223053f,-0.010715f,0.974747f, +0.223053f,-0.010715f,0.974747f,0.370348f,-0.014597f,0.928778f,0.37024f,-1.0E-6f,0.928936f,0.222967f,-1.0E-6f,0.974826f, +0.37024f,-1.0E-6f,0.928936f,0.370348f,-0.014597f,0.928778f,0.569527f,-0.020487f,0.821717f,0.569586f,-1.0E-6f,0.821932f, +0.37035f,0.014508f,0.928779f,0.37024f,-1.0E-6f,0.928936f,0.569586f,-1.0E-6f,0.821932f,0.569522f,0.020364f,0.821724f, +0.222967f,-1.0E-6f,0.974826f,0.37024f,-1.0E-6f,0.928936f,0.37035f,0.014508f,0.928779f,0.223051f,0.010649f,0.974749f, +0.569527f,-0.020487f,0.821717f,0.697362f,-0.024953f,0.716285f,0.699353f,1.1E-5f,0.714776f,0.569586f,-1.0E-6f,0.821932f, +0.569586f,-1.0E-6f,0.821932f,0.699353f,1.1E-5f,0.714776f,0.697248f,0.024864f,0.716398f,0.569522f,0.020364f,0.821724f, +-0.46128f,-0.48965f,0.739908f,-0.397988f,-0.425903f,0.812534f,-0.490028f,-0.298377f,0.819051f,-0.572885f,-0.349196f,0.741529f, +-0.490028f,-0.298377f,0.819051f,-0.397988f,-0.425903f,0.812534f,-0.294472f,-0.315809f,0.901971f,-0.344264f,-0.210118f,0.915059f, +-0.538747f,-0.174169f,0.824268f,-0.490028f,-0.298377f,0.819051f,-0.344264f,-0.210118f,0.915059f,-0.359131f,-0.12118f,0.925386f, +-0.572885f,-0.349196f,0.741529f,-0.490028f,-0.298377f,0.819051f,-0.538747f,-0.174169f,0.824268f,-0.645088f,-0.209547f,0.734814f, +-0.294472f,-0.315809f,0.901971f,-0.210457f,-0.226211f,0.951071f,-0.216181f,-0.146015f,0.965373f,-0.344264f,-0.210118f,0.915059f, +-0.344264f,-0.210118f,0.915059f,-0.216181f,-0.146015f,0.965373f,-0.219508f,-0.086774f,0.971744f,-0.359131f,-0.12118f,0.925386f, +-0.538747f,-0.174169f,0.824268f,-0.359131f,-0.12118f,0.925386f,-0.365721f,-0.051004f,0.929326f,-0.560687f,-0.072708f,0.82483f, +-0.359131f,-0.12118f,0.925386f,-0.219508f,-0.086774f,0.971744f,-0.22077f,-0.037047f,0.974622f,-0.365721f,-0.051004f,0.929326f, +-0.365721f,-0.051004f,0.929326f,-0.22077f,-0.037047f,0.974622f,-0.221f,-0.010721f,0.975215f,-0.367244f,-0.014617f,0.93001f, +-0.365721f,-0.051004f,0.929326f,-0.367244f,-0.014617f,0.93001f,-0.565774f,-0.020551f,0.824304f,-0.560687f,-0.072708f,0.82483f, +-0.645088f,-0.209547f,0.734814f,-0.538747f,-0.174169f,0.824268f,-0.560687f,-0.072708f,0.82483f,-0.682094f,-0.088945f,0.725836f, +-0.682094f,-0.088945f,0.725836f,-0.560687f,-0.072708f,0.82483f,-0.565774f,-0.020551f,0.824304f,-0.69385f,-0.025062f,0.719683f, +-0.693736f,0.024972f,0.719796f,-0.695847f,1.1E-5f,0.71819f,-0.565837f,-1.0E-6f,0.824517f,-0.565768f,0.020427f,0.824311f, +-0.695847f,1.1E-5f,0.71819f,-0.69385f,-0.025062f,0.719683f,-0.565774f,-0.020551f,0.824304f,-0.565837f,-1.0E-6f,0.824517f, +-0.565837f,-1.0E-6f,0.824517f,-0.565774f,-0.020551f,0.824304f,-0.367244f,-0.014617f,0.93001f,-0.36714f,-1.0E-6f,0.930166f, +-0.565768f,0.020427f,0.824311f,-0.565837f,-1.0E-6f,0.824517f,-0.36714f,-1.0E-6f,0.930166f,-0.367245f,0.014528f,0.930011f, +-0.367244f,-0.014617f,0.93001f,-0.221f,-0.010721f,0.975215f,-0.220914f,-1.0E-6f,0.975293f,-0.36714f,-1.0E-6f,0.930166f, +-0.36714f,-1.0E-6f,0.930166f,-0.220914f,-1.0E-6f,0.975293f,-0.220997f,0.010655f,0.975216f,-0.367245f,0.014528f,0.930011f, +0.010878f,0.222561f,0.974858f,0.037001f,0.222307f,0.974274f,0.050884f,0.367932f,0.92846f,0.01482f,0.369601f,0.929072f, +0.037001f,0.222307f,0.974274f,0.084603f,0.221056f,0.971585f,0.117939f,0.361173f,0.92501f,0.050884f,0.367932f,0.92846f, +0.050884f,0.367932f,0.92846f,0.117939f,0.361173f,0.92501f,0.169134f,0.541105f,0.823771f,0.072381f,0.563194f,0.823149f, +0.020804f,0.568602f,0.82235f,0.01482f,0.369601f,0.929072f,0.050884f,0.367932f,0.92846f,0.072381f,0.563194f,0.823149f, +0.084603f,0.221056f,0.971585f,0.139597f,0.218066f,0.965898f,0.200629f,0.347092f,0.91612f,0.117939f,0.361173f,0.92501f, +0.139597f,0.218066f,0.965898f,0.213531f,0.212993f,0.953435f,0.299149f,0.298419f,0.906342f,0.200629f,0.347092f,0.91612f, +0.200629f,0.347092f,0.91612f,0.299149f,0.298419f,0.906342f,0.405489f,0.404531f,0.819716f,0.285031f,0.494036f,0.821393f, +0.117939f,0.361173f,0.92501f,0.200629f,0.347092f,0.91612f,0.285031f,0.494036f,0.821393f,0.169134f,0.541105f,0.823771f, +0.285031f,0.494036f,0.821393f,0.405489f,0.404531f,0.819716f,0.4693f,0.468325f,0.748619f,0.335556f,0.576804f,0.744781f, +0.169134f,0.541105f,0.823771f,0.285031f,0.494036f,0.821393f,0.335556f,0.576804f,0.744781f,0.204073f,0.64709f,0.734595f, +0.072381f,0.563194f,0.823149f,0.169134f,0.541105f,0.823771f,0.204073f,0.64709f,0.734595f,0.088715f,0.684119f,0.723955f, +0.020804f,0.568602f,0.82235f,0.072381f,0.563194f,0.823149f,0.088715f,0.684119f,0.723955f,0.025388f,0.696365f,0.717239f, +0.010835f,-0.23565f,0.971778f,0.014687f,-0.38921f,0.921032f,0.050418f,-0.38752f,0.920482f,0.036837f,-0.235391f,0.971203f, +0.050418f,-0.38752f,0.920482f,0.014687f,-0.38921f,0.921032f,0.020387f,-0.591837f,0.8058f,0.070967f,-0.586467f,0.806858f, +0.116885f,-0.380591f,0.917327f,0.050418f,-0.38752f,0.920482f,0.070967f,-0.586467f,0.806858f,0.166076f,-0.564345f,0.808662f, +0.036837f,-0.235391f,0.971203f,0.050418f,-0.38752f,0.920482f,0.116885f,-0.380591f,0.917327f,0.084225f,-0.234121f,0.968552f, +0.020387f,-0.591837f,0.8058f,0.02469f,-0.717725f,0.695889f,0.086571f,-0.705739f,0.703163f,0.070967f,-0.586467f,0.806858f, +0.070967f,-0.586467f,0.806858f,0.086571f,-0.705739f,0.703163f,0.199773f,-0.669232f,0.715695f,0.166076f,-0.564345f,0.808662f, +0.116885f,-0.380591f,0.917327f,0.166076f,-0.564345f,0.808662f,0.280776f,-0.516844f,0.808725f,0.198928f,-0.366325f,0.908974f, +0.166076f,-0.564345f,0.808662f,0.199773f,-0.669232f,0.715695f,0.33043f,-0.598851f,0.729516f,0.280776f,-0.516844f,0.808725f, +0.280776f,-0.516844f,0.808725f,0.33043f,-0.598851f,0.729516f,0.464547f,-0.488911f,0.738351f,0.401261f,-0.425239f,0.811271f, +0.280776f,-0.516844f,0.808725f,0.401261f,-0.425239f,0.811271f,0.297154f,-0.315494f,0.901201f,0.198928f,-0.366325f,0.908974f, +0.084225f,-0.234121f,0.968552f,0.116885f,-0.380591f,0.917327f,0.198928f,-0.366325f,0.908974f,0.138923f,-0.231173f,0.962943f, +0.138923f,-0.231173f,0.962943f,0.198928f,-0.366325f,0.908974f,0.297154f,-0.315494f,0.901201f,0.212501f,-0.226048f,0.950655f, +0.007169f,-0.00707f,0.999949f,0.007179f,-0.025559f,0.999648f,0.025473f,-0.02556f,0.999349f,0.025479f,-0.007087f,0.99965f, +0.007179f,-0.025559f,0.999648f,0.007472f,-0.063716f,0.99794f,0.02618f,-0.063744f,0.997623f,0.025473f,-0.02556f,0.999349f, +0.025473f,-0.02556f,0.999349f,0.02618f,-0.063744f,0.997623f,0.062764f,-0.064559f,0.995938f,0.061979f,-0.026292f,0.997731f, +0.025479f,-0.007087f,0.99965f,0.025473f,-0.02556f,0.999349f,0.061979f,-0.026292f,0.997731f,0.061944f,-0.007387f,0.998052f, +0.007472f,-0.063716f,0.99794f,0.008329f,-0.119124f,0.992845f,0.028568f,-0.119188f,0.992461f,0.02618f,-0.063744f,0.997623f, +0.008329f,-0.119124f,0.992845f,0.010835f,-0.23565f,0.971778f,0.036837f,-0.235391f,0.971203f,0.028568f,-0.119188f,0.992461f, +0.028568f,-0.119188f,0.992461f,0.036837f,-0.235391f,0.971203f,0.084225f,-0.234121f,0.968552f,0.066426f,-0.119489f,0.990611f, +0.02618f,-0.063744f,0.997623f,0.028568f,-0.119188f,0.992461f,0.066426f,-0.119489f,0.990611f,0.062764f,-0.064559f,0.995938f, +0.062764f,-0.064559f,0.995938f,0.066426f,-0.119489f,0.990611f,0.114563f,-0.120018f,0.98614f,0.113981f,-0.068259f,0.991135f, +0.066426f,-0.119489f,0.990611f,0.084225f,-0.234121f,0.968552f,0.138923f,-0.231173f,0.962943f,0.114563f,-0.120018f,0.98614f, +0.114563f,-0.120018f,0.98614f,0.138923f,-0.231173f,0.962943f,0.212501f,-0.226048f,0.950655f,0.218237f,-0.145906f,0.964927f, +0.113981f,-0.068259f,0.991135f,0.114563f,-0.120018f,0.98614f,0.218237f,-0.145906f,0.964927f,0.221558f,-0.086713f,0.971284f, +0.061944f,-0.007387f,0.998052f,0.061979f,-0.026292f,0.997731f,0.113708f,-0.028673f,0.9931f,0.113635f,-0.008231f,0.993489f, +0.061979f,-0.026292f,0.997731f,0.062764f,-0.064559f,0.995938f,0.113981f,-0.068259f,0.991135f,0.113708f,-0.028673f,0.9931f, +0.113708f,-0.028673f,0.9931f,0.113981f,-0.068259f,0.991135f,0.221558f,-0.086713f,0.971284f,0.222823f,-0.037022f,0.974156f, +0.113635f,-0.008231f,0.993489f,0.113708f,-0.028673f,0.9931f,0.222823f,-0.037022f,0.974156f,0.223053f,-0.010715f,0.974747f, +0.00717f,0.007027f,0.99995f,0.007189f,0.0f,0.999974f,0.025542f,0.0f,0.999674f,0.025482f,0.007044f,0.999651f, +0.007189f,0.0f,0.999974f,0.007169f,-0.00707f,0.999949f,0.025479f,-0.007087f,0.99965f,0.025542f,0.0f,0.999674f, +0.025542f,0.0f,0.999674f,0.025479f,-0.007087f,0.99965f,0.061944f,-0.007387f,0.998052f,0.061996f,0.0f,0.998076f, +0.025482f,0.007044f,0.999651f,0.025542f,0.0f,0.999674f,0.061996f,0.0f,0.998076f,0.061948f,0.007344f,0.998052f, +0.061944f,-0.007387f,0.998052f,0.113635f,-0.008231f,0.993489f,0.11363f,0.0f,0.993523f,0.061996f,0.0f,0.998076f, +0.113635f,-0.008231f,0.993489f,0.223053f,-0.010715f,0.974747f,0.222967f,-1.0E-6f,0.974826f,0.11363f,0.0f,0.993523f, +0.11363f,0.0f,0.993523f,0.222967f,-1.0E-6f,0.974826f,0.223051f,0.010649f,0.974749f,0.113637f,0.008184f,0.993489f, +0.061996f,0.0f,0.998076f,0.11363f,0.0f,0.993523f,0.113637f,0.008184f,0.993489f,0.061948f,0.007344f,0.998052f, +-0.693736f,0.024972f,0.719796f,-0.565768f,0.020427f,0.824311f,-0.560511f,0.071322f,0.82507f,-0.681667f,0.087549f,0.726406f, +-0.560511f,0.071322f,0.82507f,-0.565768f,0.020427f,0.824311f,-0.367245f,0.014528f,0.930011f,-0.365644f,0.050051f,0.929408f, +-0.53875f,0.167715f,0.825603f,-0.560511f,0.071322f,0.82507f,-0.365644f,0.050051f,0.929408f,-0.359059f,0.116722f,0.925987f, +-0.681667f,0.087549f,0.726406f,-0.560511f,0.071322f,0.82507f,-0.53875f,0.167715f,0.825603f,-0.644943f,0.202621f,0.736881f, +-0.367245f,0.014528f,0.930011f,-0.220997f,0.010655f,0.975216f,-0.220758f,0.036362f,0.974651f,-0.365644f,0.050051f,0.929408f, +-0.365644f,0.050051f,0.929408f,-0.220758f,0.036362f,0.974651f,-0.219543f,0.083629f,0.972012f,-0.359059f,0.116722f,0.925987f, +-0.53875f,0.167715f,0.825603f,-0.359059f,0.116722f,0.925987f,-0.34505f,0.199733f,0.917086f,-0.491757f,0.284219f,0.82304f, +-0.359059f,0.116722f,0.925987f,-0.219543f,0.083629f,0.972012f,-0.216564f,0.138788f,0.966353f,-0.34505f,0.199733f,0.917086f, +-0.34505f,0.199733f,0.917086f,-0.216564f,0.138788f,0.966353f,-0.211482f,0.213152f,0.953856f,-0.296456f,0.298724f,0.907126f, +-0.34505f,0.199733f,0.917086f,-0.296456f,0.298724f,0.907126f,-0.402197f,0.405178f,0.821017f,-0.491757f,0.284219f,0.82304f, +-0.644943f,0.202621f,0.736881f,-0.53875f,0.167715f,0.825603f,-0.491757f,0.284219f,0.82304f,-0.574618f,0.33479f,0.746813f, +-0.574618f,0.33479f,0.746813f,-0.491757f,0.284219f,0.82304f,-0.402197f,0.405178f,0.821017f,-0.466013f,0.469045f,0.75022f, +0.223051f,0.010649f,0.974749f,0.37035f,0.014508f,0.928779f,0.368745f,0.04998f,0.928186f,0.222811f,0.036337f,0.974184f, +0.368745f,0.04998f,0.928186f,0.37035f,0.014508f,0.928779f,0.569522f,0.020364f,0.821724f,0.564266f,0.071105f,0.822525f, +0.362133f,0.116561f,0.92481f,0.368745f,0.04998f,0.928186f,0.564266f,0.071105f,0.822525f,0.54249f,0.167243f,0.823246f, +0.222811f,0.036337f,0.974184f,0.368745f,0.04998f,0.928186f,0.362133f,0.116561f,0.92481f,0.221593f,0.083571f,0.971552f, +0.569522f,0.020364f,0.821724f,0.697248f,0.024864f,0.716398f,0.685209f,0.08722f,0.723105f,0.564266f,0.071105f,0.822525f, +0.564266f,0.071105f,0.822525f,0.685209f,0.08722f,0.723105f,0.648546f,0.20196f,0.733894f,0.54249f,0.167243f,0.823246f, +0.362133f,0.116561f,0.92481f,0.54249f,0.167243f,0.823246f,0.495412f,0.283564f,0.821071f,0.348093f,0.199473f,0.915992f, +0.54249f,0.167243f,0.823246f,0.648546f,0.20196f,0.733894f,0.578173f,0.334012f,0.744414f,0.495412f,0.283564f,0.821071f, +0.495412f,0.283564f,0.821071f,0.578173f,0.334012f,0.744414f,0.4693f,0.468325f,0.748619f,0.405489f,0.404531f,0.819716f, +0.495412f,0.283564f,0.821071f,0.405489f,0.404531f,0.819716f,0.299149f,0.298419f,0.906342f,0.348093f,0.199473f,0.915992f, +0.221593f,0.083571f,0.971552f,0.362133f,0.116561f,0.92481f,0.348093f,0.199473f,0.915992f,0.218621f,0.138683f,0.965905f, +0.218621f,0.138683f,0.965905f,0.348093f,0.199473f,0.915992f,0.299149f,0.298419f,0.906342f,0.213531f,0.212993f,0.953435f, +0.010878f,0.222561f,0.974858f,0.008351f,0.113056f,0.993554f,0.028645f,0.113157f,0.993164f,0.037001f,0.222307f,0.974274f, +0.008351f,0.113056f,0.993554f,0.007491f,0.061287f,0.998092f,0.026239f,0.061352f,0.997771f,0.028645f,0.113157f,0.993164f, +0.028645f,0.113157f,0.993164f,0.026239f,0.061352f,0.997771f,0.062873f,0.062197f,0.996082f,0.066588f,0.113508f,0.991303f, +0.037001f,0.222307f,0.974274f,0.028645f,0.113157f,0.993164f,0.066588f,0.113508f,0.991303f,0.084603f,0.221056f,0.971585f, +0.007491f,0.061287f,0.998092f,0.007187f,0.025058f,0.99966f,0.025494f,0.025072f,0.999361f,0.026239f,0.061352f,0.997771f, +0.007187f,0.025058f,0.99966f,0.00717f,0.007027f,0.99995f,0.025482f,0.007044f,0.999651f,0.025494f,0.025072f,0.999361f, +0.025494f,0.025072f,0.999361f,0.025482f,0.007044f,0.999651f,0.061948f,0.007344f,0.998052f,0.062015f,0.025807f,0.997742f, +0.026239f,0.061352f,0.997771f,0.025494f,0.025072f,0.999361f,0.062015f,0.025807f,0.997742f,0.062873f,0.062197f,0.996082f, +0.062873f,0.062197f,0.996082f,0.062015f,0.025807f,0.997742f,0.113738f,0.028159f,0.993112f,0.114097f,0.065833f,0.991286f, +0.062015f,0.025807f,0.997742f,0.061948f,0.007344f,0.998052f,0.113637f,0.008184f,0.993489f,0.113738f,0.028159f,0.993112f, +0.113738f,0.028159f,0.993112f,0.113637f,0.008184f,0.993489f,0.223051f,0.010649f,0.974749f,0.222811f,0.036337f,0.974184f, +0.114097f,0.065833f,0.991286f,0.113738f,0.028159f,0.993112f,0.222811f,0.036337f,0.974184f,0.221593f,0.083571f,0.971552f, +0.084603f,0.221056f,0.971585f,0.066588f,0.113508f,0.991303f,0.114794f,0.114134f,0.986811f,0.139597f,0.218066f,0.965898f, +0.066588f,0.113508f,0.991303f,0.062873f,0.062197f,0.996082f,0.114097f,0.065833f,0.991286f,0.114794f,0.114134f,0.986811f, +0.114794f,0.114134f,0.986811f,0.114097f,0.065833f,0.991286f,0.221593f,0.083571f,0.971552f,0.218621f,0.138683f,0.965905f, +0.139597f,0.218066f,0.965898f,0.114794f,0.114134f,0.986811f,0.218621f,0.138683f,0.965905f,0.213531f,0.212993f,0.953435f, +0.007491f,0.061287f,0.998092f,0.008351f,0.113056f,0.993554f,0.0f,0.113048f,0.99359f,0.0f,0.061335f,0.998117f, +0.008351f,0.113056f,0.993554f,0.010878f,0.222561f,0.974858f,0.0f,0.222477f,0.974938f,0.0f,0.113048f,0.99359f, +0.0f,0.113048f,0.99359f,0.0f,0.222477f,0.974938f,-0.010867f,0.22256f,0.974858f,-0.008343f,0.113057f,0.993554f, +0.0f,0.061335f,0.998117f,0.0f,0.113048f,0.99359f,-0.008343f,0.113057f,0.993554f,-0.007484f,0.061287f,0.998092f, +0.007491f,0.061287f,0.998092f,0.0f,0.061335f,0.998117f,0.0f,0.025116f,0.999685f,0.007187f,0.025058f,0.99966f, +0.0f,0.061335f,0.998117f,-0.007484f,0.061287f,0.998092f,-0.00718f,0.025059f,0.99966f,0.0f,0.025116f,0.999685f, +0.0f,0.025116f,0.999685f,-0.00718f,0.025059f,0.99966f,-0.007163f,0.007027f,0.99995f,0.0f,0.007045f,0.999975f, +0.007187f,0.025058f,0.99966f,0.0f,0.025116f,0.999685f,0.0f,0.007045f,0.999975f,0.00717f,0.007027f,0.99995f, +-0.220997f,0.010655f,0.975216f,-0.112675f,0.008187f,0.993598f,-0.112781f,0.02817f,0.993221f,-0.220758f,0.036362f,0.974651f, +-0.112675f,0.008187f,0.993598f,-0.061553f,0.007347f,0.998077f,-0.061625f,0.025816f,0.997765f,-0.112781f,0.02817f,0.993221f, +-0.112781f,0.02817f,0.993221f,-0.061625f,0.025816f,0.997765f,-0.062487f,0.062214f,0.996105f,-0.113147f,0.065858f,0.991393f, +-0.220758f,0.036362f,0.974651f,-0.112781f,0.02817f,0.993221f,-0.113147f,0.065858f,0.991393f,-0.219543f,0.083629f,0.972012f, +-0.061553f,0.007347f,0.998077f,-0.025398f,0.007046f,0.999653f,-0.025412f,0.025076f,0.999363f,-0.061625f,0.025816f,0.997765f, +-0.025398f,0.007046f,0.999653f,-0.007163f,0.007027f,0.99995f,-0.00718f,0.025059f,0.99966f,-0.025412f,0.025076f,0.999363f, +-0.025412f,0.025076f,0.999363f,-0.00718f,0.025059f,0.99966f,-0.007484f,0.061287f,0.998092f,-0.026157f,0.061358f,0.997773f, +-0.061625f,0.025816f,0.997765f,-0.025412f,0.025076f,0.999363f,-0.026157f,0.061358f,0.997773f,-0.062487f,0.062214f,0.996105f, +-0.062487f,0.062214f,0.996105f,-0.026157f,0.061358f,0.997773f,-0.028558f,0.113162f,0.993166f,-0.066192f,0.113526f,0.991328f, +-0.026157f,0.061358f,0.997773f,-0.007484f,0.061287f,0.998092f,-0.008343f,0.113057f,0.993554f,-0.028558f,0.113162f,0.993166f, +-0.028558f,0.113162f,0.993166f,-0.008343f,0.113057f,0.993554f,-0.010867f,0.22256f,0.974858f,-0.036885f,0.222305f,0.974279f, +-0.066192f,0.113526f,0.991328f,-0.028558f,0.113162f,0.993166f,-0.036885f,0.222305f,0.974279f,-0.084089f,0.221062f,0.971628f, +-0.219543f,0.083629f,0.972012f,-0.113147f,0.065858f,0.991393f,-0.113857f,0.11417f,0.986915f,-0.216564f,0.138788f,0.966353f, +-0.113147f,0.065858f,0.991393f,-0.062487f,0.062214f,0.996105f,-0.066192f,0.113526f,0.991328f,-0.113857f,0.11417f,0.986915f, +-0.113857f,0.11417f,0.986915f,-0.066192f,0.113526f,0.991328f,-0.084089f,0.221062f,0.971628f,-0.138447f,0.218126f,0.966051f, +-0.216564f,0.138788f,0.966353f,-0.113857f,0.11417f,0.986915f,-0.138447f,0.218126f,0.966051f,-0.211482f,0.213152f,0.953856f, +}; + +const float cfGameIconStrokeVtxs[] = +{ +-0.376756459475,1.046143651009f,0.0f, +-0.512206375599f,1.039104461670f,0.0f, +-0.613150417805f,1.029256582260f,0.0f, +-0.688333272934f,1.016606807709f,0.0f, +-0.746499598026f,1.001162052155f,0.0f, +-0.796394228935f,0.982929229736,0.0f, +-0.839153468609,0.961680650711,0.0f, +-0.875913500786,0.93718868494,0.0f, +-0.907810747623,0.909225344658,0.0f, +-0.93598151207,0.877562940121,0.0f, +-0.960655272007,0.840993285179,0.0f, +-0.982061386108,0.79830801487,0.0f, +-1.00042927265,0.748299062252,0.0f, +-1.015988588333,0.689758002758,0.0f, +-1.028732180595,0.613717556,0.0f, +-1.038653135300,0.511210441589,0.0f, +-1.045744538307,0.373269081116,0.0f, +-1.049999356270,0.190926194191,0.0f, +-1.051417708397,-1.349482312799E-002,0.0f, +-1.049999356270,-0.217670500278,0.0f, +-1.04574441910,-0.399277359247,0.0f, +-1.038653135300,-0.535992026329,0.0f, +-1.028732180595,-0.636890649796,0.0f, +-1.015988588333,-0.711049556732,0.0f, +-1.00042927265,-0.767545044422,0.0f, +-0.982061386108,-0.815453350544,0.0f, +-0.960655212402,-0.856050789356,0.0f, +-0.93598151207,-0.890613555908,0.0f, +-0.907810747623,-0.920418143272,0.0f, +-0.875913500786,-0.946740865707,0.0f, +-0.839153468609,-0.969795942307,0.0f, +-0.796394228935,-0.989797830582,0.0f, +-0.746499598026,-1.006960868835,0.0f, +-0.688333272934,-1.021499633789,0.0f, +-0.613150477409,-1.033407211304,0.0f, +-0.512206375599,-1.042677521706,0.0f, +-0.376756429672,-1.049303770065,0.0f, +-0.19805586338,-1.053279519081,0.0f, +2.249561250210E-003,-1.054604768753,0.0f, +0.202514111996,-1.053279519081,0.0f, +0.381092041731,-1.049303770065,0.0f, +0.516337633133,-1.042677521706,0.0f, +0.617013633251,-1.033407211304,0.0f, +0.691882967949,-1.021499633789,0.0f, +0.749708354473,-1.006960868835,0.0f, +0.79925262928,-0.989797830582,0.0f, +0.841663658619,-0.969795942307,0.0f, +0.87808907032,-0.946740865707,0.0f, +0.909676492214,-0.920418143272,0.0f, +0.93757379055,-0.890613555908,0.0f, +0.962008118629,-0.856050789356,0.0f, +0.983206510544,-0.815453350544,0.0f, +1.001396179199,-0.767545044422,0.0f, +1.016804218292,-0.711049556732,0.0f, +1.029423952103,-0.636890649796,0.0f, +1.039248347282,-0.535992026329,0.0f, +1.046270728111,-0.399277359247,0.0f, +1.050484061241,-0.217670500278,0.0f, +1.051888465881,-1.349482685328E-002,0.0f, +1.050484061241,0.190926194191,0.0f, +1.046270728111,0.373269081116,0.0f, +1.039248347282,0.511210441589,0.0f, +1.029423952103,0.613717556,0.0f, +1.016804218292,0.689758002758,0.0f, +1.001396059990,0.748299002647,0.0f, +0.983206450939,0.79830801487,0.0f, +0.962008118629,0.840993225574,0.0f, +0.93757379055,0.877562940121,0.0f, +0.909676492214,0.909225344658,0.0f, +0.87808907032,0.93718868494,0.0f, +0.841663658619,0.961680650711,0.0f, +0.79925262928,0.982929229736,0.0f, +0.749708354473,1.001162052155,0.0f, +0.691882967949,1.016606807709,0.0f, +0.617013692856,1.029256582260,0.0f, +0.516337633133,1.039104580879,0.0f, +0.381092071533,1.046143770218,0.0f, +0.202514111996,1.050367355347,0.0f, +2.249561250210E-003,1.051775097847,0.0f, +-0.19805586338,1.050367236137,0.0f, +-0.376756459475,1.046143651009,0.0f +}; + +const unsigned int cuGameIconStrokeVtxCount = sizeof(cfGameIconStrokeVtxs) / (sizeof(float) * 3); + +#endif diff --git a/src/gui/GridBackground.cpp b/src/gui/GridBackground.cpp new file mode 100644 index 0000000..d027ab8 --- /dev/null +++ b/src/gui/GridBackground.cpp @@ -0,0 +1,100 @@ +#include "GridBackground.h" +#include "video/CVideo.h" +#include "video/shaders/Shader3D.h" + +static const float bgRepeat = 1000.0f; +static const float bgTexRotate = 39.0f; + +GridBackground::GridBackground(GuiImageData *img) + : GuiImage(img) +{ + colorIntensity = glm::vec4(1.0f, 1.0f, 1.0f, 0.9f); + alphaFadeOut = glm::vec4(0.0f); + distanceFadeOut = 0.15f; + + vtxCount = 4; + + //! texture and vertex coordinates + f32 *m_posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuVertexAttrSize); + f32 *m_texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuTexCoordAttrSize); + + if(m_posVtxs) + { + int i = 0; + m_posVtxs[i++] = -1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = 1.0f; + m_posVtxs[i++] = 1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = 1.0f; + m_posVtxs[i++] = 1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = -1.0f; + m_posVtxs[i++] = -1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = -1.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, m_posVtxs, vtxCount * Shader3D::cuVertexAttrSize); + } + + if(m_texCoords) + { + glm::vec2 texCoordVec[4]; + texCoordVec[0][0] = -0.5f * bgRepeat; texCoordVec[0][1] = 0.5f * bgRepeat; + texCoordVec[1][0] = 0.5f * bgRepeat; texCoordVec[1][1] = 0.5f * bgRepeat; + texCoordVec[2][0] = 0.5f * bgRepeat; texCoordVec[2][1] = -0.5f * bgRepeat; + texCoordVec[3][0] = -0.5f * bgRepeat; texCoordVec[3][1] = -0.5f * bgRepeat; + + const float cosRot = cosf(DegToRad(bgTexRotate)); + const float sinRot = sinf(DegToRad(bgTexRotate)); + + glm::mat2 texRotateMtx({ + cosRot, -sinRot, + sinRot, cosRot + }); + + for(int i = 0; i < 4; i++) { + texCoordVec[i] = texRotateMtx * texCoordVec[i]; + m_texCoords[i*2 + 0] = texCoordVec[i][0]; + m_texCoords[i*2 + 1] = texCoordVec[i][1]; + } + + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, m_texCoords, vtxCount * Shader3D::cuTexCoordAttrSize); + } + + //! assign to internal variables which are const but oh well + posVtxs = m_posVtxs; + texCoords = m_texCoords; +} + +GridBackground::~GridBackground() +{ + //! remove image so it can not be drawn anymore from this point on + imageData = NULL; + + //! main image vertexes + if(posVtxs) + { + free((void*)posVtxs); + posVtxs = NULL; + } + if(texCoords) + { + free((void*)texCoords); + texCoords = NULL; + } +} + +void GridBackground::draw(CVideo *pVideo, const glm::mat4 & modelView) +{ + //! first setup 2D GUI positions + f32 currScaleX = bgRepeat * scaleX * (f32)getWidth() * pVideo->getWidthScaleFactor(); + f32 currScaleY = 1.0f; + f32 currScaleZ = bgRepeat * scaleZ * (f32)getHeight() * pVideo->getDepthScaleFactor(); + + m_modelView = glm::scale(modelView, glm::vec3(currScaleX, currScaleY, currScaleZ)); + + colorIntensity[3] = getAlpha(); + + Shader3D::instance()->setShaders(); + Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler()); + Shader3D::instance()->setProjectionMtx(pVideo->getProjectionMtx()); + Shader3D::instance()->setViewMtx(pVideo->getViewMtx()); + Shader3D::instance()->setModelViewMtx(m_modelView); + Shader3D::instance()->setDistanceFadeOut(distanceFadeOut); + Shader3D::instance()->setAlphaFadeOut(alphaFadeOut); + Shader3D::instance()->setColorIntensity(colorIntensity); + Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoords); + Shader3D::instance()->draw(GX2_PRIMITIVE_QUADS, vtxCount); +} diff --git a/src/gui/GridBackground.h b/src/gui/GridBackground.h new file mode 100644 index 0000000..198506a --- /dev/null +++ b/src/gui/GridBackground.h @@ -0,0 +1,30 @@ +#ifndef _GRID_BACKGROUND_H_ +#define _GRID_BACKGROUND_H_ + +#include "GuiImage.h" +#include "video/shaders/Shader.h" + +class GridBackground : public GuiImage +{ +public: + GridBackground(GuiImageData *imgData); + virtual ~GridBackground(); + + void setColorIntensity(const glm::vec4 & color) { + colorIntensity = color; + } + const glm::vec4 & getColorIntensity() const { + return colorIntensity; + } + void setDistanceFadeOut(const float & a) { + distanceFadeOut = a; + } + void draw(CVideo *pVideo, const glm::mat4 & modelView); +private: + glm::mat4 m_modelView; + glm::vec4 colorIntensity; + glm::vec4 alphaFadeOut; + float distanceFadeOut; +}; + +#endif // _GRID_BACKGROUND_H_ diff --git a/src/gui/Gui.h b/src/gui/Gui.h new file mode 100644 index 0000000..fb841c5 --- /dev/null +++ b/src/gui/Gui.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef __GUI_H +#define __GUI_H + +#include "GuiElement.h" +#include "GuiImageData.h" +#include "GuiImage.h" +#include "GuiFrame.h" +#include "GuiController.h" +#include "GuiText.h" +#include "GuiSound.h" +#include "GuiButton.h" +#include "GuiTrigger.h" + +#endif diff --git a/src/gui/GuiButton.cpp b/src/gui/GuiButton.cpp new file mode 100644 index 0000000..ae05a8d --- /dev/null +++ b/src/gui/GuiButton.cpp @@ -0,0 +1,301 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "GuiButton.h" +#include "GuiTrigger.h" +#include "GuiController.h" + +/** + * Constructor for the GuiButton class. + */ + +GuiButton::GuiButton(f32 w, f32 h) +{ + width = w; + height = h; + image = NULL; + imageOver = NULL; + imageHold = NULL; + imageClick = NULL; + icon = NULL; + iconOver = NULL; + + for(int i = 0; i < 4; i++) + { + label[i] = NULL; + labelOver[i] = NULL; + labelHold[i] = NULL; + labelClick[i] = NULL; + } + for(int i = 0; i < iMaxGuiTriggers; i++) + { + trigger[i] = NULL; + } + + soundOver = NULL; + soundHold = NULL; + soundClick = NULL; + clickedTrigger = NULL; + heldTrigger = NULL; + selectable = true; + holdable = false; + clickable = true; +} + +/** + * Destructor for the GuiButton class. + */ +GuiButton::~GuiButton() +{ +} + +void GuiButton::setImage(GuiImage* img) +{ + image = img; + if(img) img->setParent(this); +} +void GuiButton::setImageOver(GuiImage* img) +{ + imageOver = img; + if(img) img->setParent(this); +} +void GuiButton::setImageHold(GuiImage* img) +{ + imageHold = img; + if(img) img->setParent(this); +} +void GuiButton::setImageClick(GuiImage* img) +{ + imageClick = img; + if(img) img->setParent(this); +} +void GuiButton::setIcon(GuiImage* img) +{ + icon = img; + if(img) img->setParent(this); +} +void GuiButton::setIconOver(GuiImage* img) +{ + iconOver = img; + if(img) img->setParent(this); +} + +void GuiButton::setLabel(GuiText* txt, int n) +{ + label[n] = txt; + if(txt) txt->setParent(this); +} +void GuiButton::setLabelOver(GuiText* txt, int n) +{ + labelOver[n] = txt; + if(txt) txt->setParent(this); +} +void GuiButton::setLabelHold(GuiText* txt, int n) +{ + labelHold[n] = txt; + if(txt) txt->setParent(this); +} +void GuiButton::setLabelClick(GuiText* txt, int n) +{ + labelClick[n] = txt; + if(txt) txt->setParent(this); +} +void GuiButton::setSoundOver(GuiSound * snd) +{ + soundOver = snd; +} +void GuiButton::setSoundHold(GuiSound * snd) +{ + soundHold = snd; +} + +void GuiButton::setSoundClick(GuiSound * snd) +{ + soundClick = snd; +} + +void GuiButton::setTrigger(GuiTrigger * t, int idx) +{ + if(idx >= 0 && idx < iMaxGuiTriggers) + { + trigger[idx] = t; + } + else + { + for(int i = 0; i < iMaxGuiTriggers; i++) + { + if(!trigger[i]) + { + trigger[i] = t; + break; + } + } + } +} + +void GuiButton::resetState(void) +{ + clickedTrigger = NULL; + heldTrigger = NULL; + GuiElement::resetState(); +} + +/** + * Draw the button on screen + */ +void GuiButton::draw(CVideo *v) +{ + if(!this->isVisible()) + return; + + // draw image + if((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && imageOver)) || + (!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && imageOver))) + imageOver->draw(v); + else if(image) + image->draw(v); + + if((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && iconOver)) || + (!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && iconOver))) + iconOver->draw(v); + else if(icon) + icon->draw(v); + + // draw text + for(int i = 0; i < 4; i++) + { + if(isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && labelOver[i]) + labelOver[i]->draw(v); + else if(label[i]) + label[i]->draw(v); + } +} + +void GuiButton::update(GuiController * c) +{ + if(!c || isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan)) + return; + else if(parentElement && (parentElement->isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan))) + return; + + if(selectable) + { + if(c->data.validPointer && this->isInside(c->data.x, c->data.y)) + { + if(!isStateSet(STATE_OVER, c->chan)) + { + setState(STATE_OVER, c->chan); + + //if(this->isRumbleActive()) + // this->rumble(t->chan); + + if(soundOver) + soundOver->Play(); + + if(effectsOver && !effects) + { + // initiate effects + effects = effectsOver; + effectAmount = effectAmountOver; + effectTarget = effectTargetOver; + } + + pointedOn(this, c); + } + } + else if(isStateSet(STATE_OVER, c->chan)) + { + this->clearState(STATE_OVER, c->chan); + pointedOff(this, c); + + if(effectTarget == effectTargetOver && effectAmount == effectAmountOver) + { + // initiate effects (in reverse) + effects = effectsOver; + effectAmount = -effectAmountOver; + effectTarget = 100; + } + } + } + + for(int i = 0; i < iMaxGuiTriggers; i++) + { + if(!trigger[i]) + continue; + + // button triggers + if(clickable) + { + + int isClicked = trigger[i]->clicked(c); + + if( !clickedTrigger && (isClicked != GuiTrigger::CLICKED_NONE) + && (trigger[i]->isClickEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chan) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) + { + if(soundClick) + soundClick->Play(); + + clickedTrigger = trigger[i]; + + if(!isStateSet(STATE_CLICKED, c->chan)){ + if(isClicked == GuiTrigger::CLICKED_TOUCH){ + setState(STATE_CLICKED_TOUCH, c->chan); + }else{ + setState(STATE_CLICKED, c->chan); + } + } + + clicked(this, c, trigger[i]); + } + else if((isStateSet(STATE_CLICKED, c->chan) || isStateSet(STATE_CLICKED_TOUCH, c->chan)) && (clickedTrigger == trigger[i]) && !isStateSet(STATE_HELD, c->chan) && !trigger[i]->held(c) && ((isClicked == GuiTrigger::CLICKED_NONE) || trigger[i]->released(c))) + { + if((isStateSet(STATE_CLICKED_TOUCH, c->chan) && this->isInside(c->data.x, c->data.y)) || (isStateSet(STATE_CLICKED, c->chan))){ + clickedTrigger = NULL; + clearState(STATE_CLICKED, c->chan); + released(this, c, trigger[i]); + } + } + } + + if(holdable) + { + bool isHeld = trigger[i]->held(c); + + if( (!heldTrigger || heldTrigger == trigger[i]) && isHeld + && (trigger[i]->isHoldEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chan) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) + { + heldTrigger = trigger[i]; + + if(!isStateSet(STATE_HELD, c->chan)) + setState(STATE_HELD, c->chan); + + held(this, c, trigger[i]); + } + else if(isStateSet(STATE_HELD, c->chan) && (heldTrigger == trigger[i]) && (!isHeld || trigger[i]->released(c))) + { + //! click is removed at this point and converted to held + if(clickedTrigger == trigger[i]) + { + clickedTrigger = NULL; + clearState(STATE_CLICKED, c->chan); + } + heldTrigger = NULL; + clearState(STATE_HELD, c->chan); + released(this, c, trigger[i]); + } + } + } +} diff --git a/src/gui/GuiButton.h b/src/gui/GuiButton.h new file mode 100644 index 0000000..0e08d42 --- /dev/null +++ b/src/gui/GuiButton.h @@ -0,0 +1,117 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef GUI_BUTTON_H_ +#define GUI_BUTTON_H_ + +#include "GuiElement.h" +#include "GuiText.h" +#include "GuiController.h" +#include "GuiImage.h" +#include "GuiSound.h" +#include "GuiTrigger.h" + +//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional) +class GuiButton : public GuiElement +{ + public: + //!Constructor + //!\param w Width + //!\param h Height + GuiButton(f32 w, f32 h); + //!Destructor + virtual ~GuiButton(); + //!Sets the button's image + //!\param i Pointer to GuiImage object + void setImage(GuiImage* i); + //!Sets the button's image on over + //!\param i Pointer to GuiImage object + void setImageOver(GuiImage* i); + + void setIcon(GuiImage* i); + void setIconOver(GuiImage* i); + //!Sets the button's image on hold + //!\param i Pointer to GuiImage object + void setImageHold(GuiImage* i); + //!Sets the button's image on click + //!\param i Pointer to GuiImage object + void setImageClick(GuiImage* i); + //!Sets the button's label + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void setLabel(GuiText* t, int n = 0); + //!Sets the button's label on over (eg: different colored text) + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void setLabelOver(GuiText* t, int n = 0); + //!Sets the button's label on hold + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void setLabelHold(GuiText* t, int n = 0); + //!Sets the button's label on click + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void setLabelClick(GuiText* t, int n = 0); + //!Sets the sound to play on over + //!\param s Pointer to GuiSound object + void setSoundOver(GuiSound * s); + //!Sets the sound to play on hold + //!\param s Pointer to GuiSound object + void setSoundHold(GuiSound * s); + //!Sets the sound to play on click + //!\param s Pointer to GuiSound object + void setSoundClick(GuiSound * s); + //!Set a new GuiTrigger for the element + //!\param i Index of trigger array to set + //!\param t Pointer to GuiTrigger + void setTrigger(GuiTrigger * t, int idx = -1); + //! + void resetState(void); + //!Constantly called to draw the GuiButton + void draw(CVideo *video); + //!Constantly called to allow the GuiButton to respond to updated input data + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + void update(GuiController * c); + + sigslot::signal2 selected; + sigslot::signal2 deSelected; + sigslot::signal2 pointedOn; + sigslot::signal2 pointedOff; + sigslot::signal3 clicked; + sigslot::signal3 held; + sigslot::signal3 released; + protected: + static const int iMaxGuiTriggers = 10; + + GuiImage * image; //!< Button image (default) + GuiImage * imageOver; //!< Button image for STATE_SELECTED + GuiImage * imageHold; //!< Button image for STATE_HELD + GuiImage * imageClick; //!< Button image for STATE_CLICKED + GuiImage * icon; + GuiImage * iconOver; + GuiText * label[4]; //!< Label(s) to display (default) + GuiText * labelOver[4]; //!< Label(s) to display for STATE_SELECTED + GuiText * labelHold[4]; //!< Label(s) to display for STATE_HELD + GuiText * labelClick[4]; //!< Label(s) to display for STATE_CLICKED + GuiSound * soundOver; //!< Sound to play for STATE_SELECTED + GuiSound * soundHold; //!< Sound to play for STATE_HELD + GuiSound * soundClick; //!< Sound to play for STATE_CLICKED + GuiTrigger * trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to + GuiTrigger * clickedTrigger; + GuiTrigger * heldTrigger; +}; + +#endif diff --git a/src/gui/GuiCheckBox.cpp b/src/gui/GuiCheckBox.cpp new file mode 100644 index 0000000..73654ea --- /dev/null +++ b/src/gui/GuiCheckBox.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#include "GuiCheckBox.h" +#include "GuiImage.h" +#include "GuiImageData.h" +/** + * Constructor for the GuiCheckBox class. + */ + +GuiCheckBox::GuiCheckBox(bool checked) + : GuiToggle(checked,50,50) + ,checkbox_imgdata(Resources::GetImageData("checkbox.png")) + ,checkbox_img(checkbox_imgdata) + ,checkbox_selected_imgdata(Resources::GetImageData("checkbox_selected.png")) + ,checkbox_selected_img(checkbox_selected_imgdata) + ,highlighted_imgdata(Resources::GetImageData("checkbox_highlighted.png")) + ,highlighted_img(highlighted_imgdata) +{ + checkbox_selected_img.setScale(height/checkbox_selected_img.getHeight()); + checkbox_img.setScale(height/checkbox_img.getHeight()); + highlighted_img.setScale(height/highlighted_img.getHeight()); + + setImage(&checkbox_img); + setIconOver(&highlighted_img); +} + +/** + * Destructor for the GuiButton class. + */ +GuiCheckBox::~GuiCheckBox() +{ + Resources::RemoveImageData(checkbox_imgdata); + Resources::RemoveImageData(checkbox_selected_imgdata); + Resources::RemoveImageData(highlighted_imgdata); +} + + +void GuiCheckBox::update(GuiController * c){ + if(bChanged){ + if(selected){ + GuiButton::setImage(&checkbox_selected_img); + }else{ + GuiButton::setImage(&checkbox_img); + } + bChanged = false; + } + GuiToggle::update(c); +} + diff --git a/src/gui/GuiCheckBox.h b/src/gui/GuiCheckBox.h new file mode 100644 index 0000000..f5683fc --- /dev/null +++ b/src/gui/GuiCheckBox.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#ifndef GUI_CHECKBOX_H_ +#define GUI_CHECKBOX_H_ + +#include "GuiToggle.h" +#include "GuiImage.h" +#include "GuiImageData.h" + +//!A simple CheckBox +class GuiCheckBox : public GuiToggle +{ + public: + //!Constructor + //!\param checked Checked + GuiCheckBox(bool checked); + //!Destructor + virtual ~GuiCheckBox(); + protected: + + GuiImageData * checkbox_imgdata; + GuiImage checkbox_img; + + GuiImageData * checkbox_selected_imgdata; + GuiImage checkbox_selected_img; + + GuiImageData * highlighted_imgdata; + GuiImage highlighted_img; + + void update(GuiController * c); +}; + +#endif diff --git a/src/gui/GuiController.h b/src/gui/GuiController.h new file mode 100644 index 0000000..c9cc443 --- /dev/null +++ b/src/gui/GuiController.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef GUI_CONTROLLER_H_ +#define GUI_CONTROLLER_H_ + +#include +#include "GuiTrigger.h" + +class GuiController +{ +public: + //!Constructor + GuiController(int channel) + : chan(channel) + { + memset(&lastData, 0, sizeof(lastData)); + memset(&data, 0, sizeof(data)); + + switch(chan) + { + default: + case GuiTrigger::CHANNEL_1: + chanIdx = 0; + break; + case GuiTrigger::CHANNEL_2: + chanIdx = 1; + break; + case GuiTrigger::CHANNEL_3: + chanIdx = 2; + break; + case GuiTrigger::CHANNEL_4: + chanIdx = 3; + break; + case GuiTrigger::CHANNEL_5: + chanIdx = 4; + break; + } + } + + //!Destructor + virtual ~GuiController() {} + + virtual bool update(int width, int height) = 0; + + typedef struct + { + unsigned int buttons_h; + unsigned int buttons_d; + unsigned int buttons_r; + bool validPointer; + bool touched; + float pointerAngle; + int x; + int y; + } PadData; + + int chan; + int chanIdx; + PadData data; + PadData lastData; + +}; + +#endif diff --git a/src/gui/GuiDragListener.cpp b/src/gui/GuiDragListener.cpp new file mode 100644 index 0000000..796d8f2 --- /dev/null +++ b/src/gui/GuiDragListener.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * based on GuiButton by dimok + * + * 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 . + ****************************************************************************/ +#include "GuiDragListener.h" +#include "GuiController.h" +#include "utils/logger.h" + +/** + * Constructor for the GuiDragListener class. + */ + +GuiDragListener::GuiDragListener(f32 w,f32 h){ + width = w; + height = h; + for(int i = 0; i < iMaxGuiTriggers; i++) + { + trigger[i] = NULL; + } +} + +/** + * Destructor for the GuiDragListener class. + */ +GuiDragListener::~GuiDragListener(){ +} + +void GuiDragListener::setTrigger(GuiTrigger * t, int idx){ + if(idx >= 0 && idx < iMaxGuiTriggers) + { + trigger[idx] = t; + } + else + { + for(int i = 0; i < iMaxGuiTriggers; i++) + { + if(!trigger[i]) + { + trigger[i] = t; + break; + } + } + } +} + +void GuiDragListener::update(GuiController * c){ + if(!c || isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan)) + return; + else if(parentElement && (parentElement->isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan))) + return; + + for(int i = 0; i < iMaxGuiTriggers; i++){ + if(!trigger[i]){ + continue; + } + + bool isHeld = trigger[i]->held(c); + + + if(isHeld && this->isInside(c->data.x, c->data.y)){ + int dx = c->data.x - c->lastData.x; + int dy = c->data.y - c->lastData.y; + + if(dx == 0 && dy == 0) continue; + + dragged(this, c, trigger[i],dx,dy); + } + } +} diff --git a/src/gui/GuiDragListener.h b/src/gui/GuiDragListener.h new file mode 100644 index 0000000..e0750e0 --- /dev/null +++ b/src/gui/GuiDragListener.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#ifndef GUI_DRAG_LISTENER_H_ +#define GUI_DRAG_LISTENER_H_ + +#include "GuiElement.h" +#include "GuiController.h" +#include "GuiTrigger.h" +#include "GuiButton.h" + +class GuiDragListener : public GuiElement +{ + public: + //!Constructor + //!\param w Width + //!\param h Height + GuiDragListener(f32 w,f32 h); + //!Destructor + virtual ~GuiDragListener(); + //!Set a new GuiTrigger for the element + //!\param i Index of trigger array to set + //!\param t Pointer to GuiTrigger + void setTrigger(GuiTrigger * t, int idx = -1); + + //!Constantly called to allow the GuiDragListener to respond to updated input data + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + void update(GuiController * c); + + sigslot::signal5 dragged; + protected: + static const int iMaxGuiTriggers = 10; + + GuiTrigger * trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to +}; + +#endif diff --git a/src/gui/GuiElement.cpp b/src/gui/GuiElement.cpp new file mode 100644 index 0000000..e79253b --- /dev/null +++ b/src/gui/GuiElement.cpp @@ -0,0 +1,343 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "GuiElement.h" + +//! TODO remove this! +static int screenwidth = 1280; +static int screenheight = 720; + +/** + * Constructor for the Object class. + */ +GuiElement::GuiElement() +{ + xoffset = 0.0f; + yoffset = 0.0f; + zoffset = 0.0f; + width = 0.0f; + height = 0.0f; + alpha = 1.0f; + scaleX = 1.0f; + scaleY = 1.0f; + scaleZ = 1.0f; + for(int i = 0; i < 4; i++) + state[i] = STATE_DEFAULT; + stateChan = -1; + parentElement = NULL; + rumble = true; + selectable = false; + clickable = false; + holdable = false; + drawOverOnlyWhenSelected = false; + visible = true; + yoffsetDyn = 0; + xoffsetDyn = 0; + alphaDyn = -1; + scaleDyn = 1; + effects = EFFECT_NONE; + effectAmount = 0; + effectTarget = 0; + effectsOver = EFFECT_NONE; + effectAmountOver = 0; + effectTargetOver = 0; + angle = 0.0f; + + // default alignment - align to top left + alignment = (ALIGN_CENTER | ALIGN_MIDDLE); +} + +/** + * Get the left position of the GuiElement. + * @see SetLeft() + * @return Left position in pixel. + */ +f32 GuiElement::getLeft() +{ + f32 pWidth = 0; + f32 pLeft = 0; + f32 pScaleX = 1.0f; + + if(parentElement) + { + pWidth = parentElement->getWidth(); + pLeft = parentElement->getLeft(); + pScaleX = parentElement->getScaleX(); + } + + pLeft += xoffsetDyn; + + f32 x = pLeft; + + //! TODO: the conversion from int to float and back to int is bad for performance, change that + if(alignment & ALIGN_CENTER) + { + x = pLeft + pWidth * 0.5f * pScaleX - width * 0.5f * getScaleX(); + } + else if(alignment & ALIGN_RIGHT) + { + x = pLeft + pWidth * pScaleX - width * getScaleX(); + } + + return x + xoffset; +} + +/** + * Get the top position of the GuiElement. + * @see SetTop() + * @return Top position in pixel. + */ +f32 GuiElement::getTop() +{ + f32 pHeight = 0; + f32 pTop = 0; + f32 pScaleY = 1.0f; + + if(parentElement) + { + pHeight = parentElement->getHeight(); + pTop = parentElement->getTop(); + pScaleY = parentElement->getScaleY(); + } + + pTop += yoffsetDyn; + + f32 y = pTop; + + //! TODO: the conversion from int to float and back to int is bad for performance, change that + if(alignment & ALIGN_MIDDLE) + { + y = pTop + pHeight * 0.5f * pScaleY - height * 0.5f * getScaleY(); + } + else if(alignment & ALIGN_BOTTOM) + { + y = pTop + pHeight * pScaleY - height * getScaleY(); + } + + return y + yoffset; +} + +void GuiElement::setEffect(int eff, int amount, int target) +{ + if(eff & EFFECT_SLIDE_IN) + { + // these calculations overcompensate a little + if(eff & EFFECT_SLIDE_TOP) + { + if(eff & EFFECT_SLIDE_FROM) + yoffsetDyn = (int) -getHeight()*scaleY; + else + yoffsetDyn = -screenheight; + } + else if(eff & EFFECT_SLIDE_LEFT) + { + if(eff & EFFECT_SLIDE_FROM) + xoffsetDyn = (int) -getWidth()*scaleX; + else + xoffsetDyn = -screenwidth; + } + else if(eff & EFFECT_SLIDE_BOTTOM) + { + if(eff & EFFECT_SLIDE_FROM) + yoffsetDyn = (int) getHeight()*scaleY; + else + yoffsetDyn = screenheight; + } + else if(eff & EFFECT_SLIDE_RIGHT) + { + if(eff & EFFECT_SLIDE_FROM) + xoffsetDyn = (int) getWidth()*scaleX; + else + xoffsetDyn = screenwidth; + } + } + if((eff & EFFECT_FADE) && amount > 0) + { + alphaDyn = 0; + } + else if((eff & EFFECT_FADE) && amount < 0) + { + alphaDyn = alpha; + } + effects |= eff; + effectAmount = amount; + effectTarget = target; +} + +//!Sets an effect to be enabled on wiimote cursor over +//!\param e Effect to enable +//!\param a Amount of the effect (usage varies on effect) +//!\param t Target amount of the effect (usage varies on effect) +void GuiElement::setEffectOnOver(int e, int a, int t) +{ + effectsOver |= e; + effectAmountOver = a; + effectTargetOver = t; +} + +void GuiElement::resetEffects() +{ + yoffsetDyn = 0; + xoffsetDyn = 0; + alphaDyn = -1; + scaleDyn = 1; + effects = EFFECT_NONE; + effectAmount = 0; + effectTarget = 0; + effectsOver = EFFECT_NONE; + effectAmountOver = 0; + effectTargetOver = 0; +} +void GuiElement::updateEffects() +{ + if(!this->isVisible() && parentElement) + return; + + if(effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT | EFFECT_SLIDE_FROM)) + { + if(effects & EFFECT_SLIDE_IN) + { + if(effects & EFFECT_SLIDE_LEFT) + { + xoffsetDyn += effectAmount; + + if(xoffsetDyn >= 0) + { + xoffsetDyn = 0; + effects = 0; + effectFinished(this); + } + } + else if(effects & EFFECT_SLIDE_RIGHT) + { + xoffsetDyn -= effectAmount; + + if(xoffsetDyn <= 0) + { + xoffsetDyn = 0; + effects = 0; + effectFinished(this); + } + } + else if(effects & EFFECT_SLIDE_TOP) + { + yoffsetDyn += effectAmount; + + if(yoffsetDyn >= 0) + { + yoffsetDyn = 0; + effects = 0; + effectFinished(this); + } + } + else if(effects & EFFECT_SLIDE_BOTTOM) + { + yoffsetDyn -= effectAmount; + + if(yoffsetDyn <= 0) + { + yoffsetDyn = 0; + effects = 0; + effectFinished(this); + } + } + } + else + { + if(effects & EFFECT_SLIDE_LEFT) + { + xoffsetDyn -= effectAmount; + + if(xoffsetDyn <= -screenwidth) { + effects = 0; // shut off effect + effectFinished(this); + } + else if((effects & EFFECT_SLIDE_FROM) && xoffsetDyn <= -getWidth()) { + effects = 0; // shut off effect + effectFinished(this); + } + } + else if(effects & EFFECT_SLIDE_RIGHT) + { + xoffsetDyn += effectAmount; + + if(xoffsetDyn >= screenwidth) { + effects = 0; // shut off effect + effectFinished(this); + } + else if((effects & EFFECT_SLIDE_FROM) && xoffsetDyn >= getWidth()*scaleX) { + effects = 0; // shut off effect + effectFinished(this); + } + } + else if(effects & EFFECT_SLIDE_TOP) + { + yoffsetDyn -= effectAmount; + + if(yoffsetDyn <= -screenheight) { + effects = 0; // shut off effect + effectFinished(this); + } + else if((effects & EFFECT_SLIDE_FROM) && yoffsetDyn <= -getHeight()) { + effects = 0; // shut off effect + effectFinished(this); + } + } + else if(effects & EFFECT_SLIDE_BOTTOM) + { + yoffsetDyn += effectAmount; + + if(yoffsetDyn >= screenheight) { + effects = 0; // shut off effect + effectFinished(this); + } + else if((effects & EFFECT_SLIDE_FROM) && yoffsetDyn >= getHeight()) { + effects = 0; // shut off effect + effectFinished(this); + } + } + } + } + else if(effects & EFFECT_FADE) + { + alphaDyn += effectAmount * (1.0f / 255.0f); + + if(effectAmount < 0 && alphaDyn <= 0) + { + alphaDyn = 0; + effects = 0; // shut off effect + effectFinished(this); + } + else if(effectAmount > 0 && alphaDyn >= alpha) + { + alphaDyn = alpha; + effects = 0; // shut off effect + effectFinished(this); + } + } + else if(effects & EFFECT_SCALE) + { + scaleDyn += effectAmount * 0.01f; + + if((effectAmount < 0 && scaleDyn <= (effectTarget * 0.01f)) + || (effectAmount > 0 && scaleDyn >= (effectTarget * 0.01f))) + { + scaleDyn = effectTarget * 0.01f; + effects = 0; // shut off effect + effectFinished(this); + } + } +} diff --git a/src/gui/GuiElement.h b/src/gui/GuiElement.h new file mode 100644 index 0000000..6ae9261 --- /dev/null +++ b/src/gui/GuiElement.h @@ -0,0 +1,529 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef GUI_ELEMENT_H_ +#define GUI_ELEMENT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sigslot.h" +#include "glm/glm.hpp" +#include "glm/gtc/matrix_transform.hpp" + +#include "dynamic_libs/gx2_types.h" +#include "resources/Resources.h" +#include "system/AsyncDeleter.h" +#include "utils/logger.h" + +enum +{ + EFFECT_NONE = 0x00, + EFFECT_SLIDE_TOP = 0x01, + EFFECT_SLIDE_BOTTOM = 0x02, + EFFECT_SLIDE_RIGHT = 0x04, + EFFECT_SLIDE_LEFT = 0x08, + EFFECT_SLIDE_IN = 0x10, + EFFECT_SLIDE_OUT = 0x20, + EFFECT_SLIDE_FROM = 0x40, + EFFECT_FADE = 0x80, + EFFECT_SCALE = 0x100, + EFFECT_COLOR_TRANSITION = 0x200 +}; + +enum +{ + ALIGN_LEFT = 0x01, + ALIGN_CENTER = 0x02, + ALIGN_RIGHT = 0x04, + ALIGN_TOP = 0x10, + ALIGN_MIDDLE = 0x20, + ALIGN_BOTTOM = 0x40, + ALIGN_TOP_LEFT = ALIGN_LEFT | ALIGN_TOP, + ALIGN_TOP_CENTER = ALIGN_CENTER | ALIGN_TOP, + ALIGN_TOP_RIGHT = ALIGN_RIGHT | ALIGN_TOP, + ALIGN_CENTERED = ALIGN_CENTER | ALIGN_MIDDLE, +}; + +//!Forward declaration +class GuiController; +class CVideo; + +//!Primary GUI class. Most other classes inherit from this class. +class GuiElement : public AsyncDeleter::Element +{ + public: + //!Constructor + GuiElement(); + //!Destructor + virtual ~GuiElement() {} + //!Set the element's parent + //!\param e Pointer to parent element + virtual void setParent(GuiElement * e) { parentElement = e; } + //!Gets the element's parent + //!\return Pointer to parent element + virtual GuiElement * getParent() { return parentElement; } + //!Gets the current leftmost coordinate of the element + //!Considers horizontal alignment, x offset, width, and parent element's GetLeft() / GetWidth() values + //!\return left coordinate + virtual f32 getLeft(); + //!Gets the current topmost coordinate of the element + //!Considers vertical alignment, y offset, height, and parent element's GetTop() / GetHeight() values + //!\return top coordinate + virtual f32 getTop(); + //!Gets the current Z coordinate of the element + //!\return Z coordinate + virtual f32 getDepth() + { + f32 zParent = 0.0f; + + if(parentElement) + zParent = parentElement->getDepth(); + + return zParent+zoffset; + } + + virtual f32 getCenterX(void) + { + f32 pCenterX = 0.0f; + + if(parentElement) + pCenterX = parentElement->getCenterX(); + + pCenterX += xoffset + xoffsetDyn; + + if(alignment & ALIGN_LEFT) + { + f32 pWidth = 0.0f; + f32 pScale = 0.0f; + + if(parentElement) + { + pWidth = parentElement->getWidth(); + pScale = parentElement->getScaleX(); + } + + pCenterX -= pWidth * 0.5f * pScale - width * 0.5f * getScaleX(); + } + else if(alignment & ALIGN_RIGHT) + { + f32 pWidth = 0.0f; + f32 pScale = 0.0f; + + if(parentElement) + { + pWidth = parentElement->getWidth(); + pScale = parentElement->getScaleX(); + } + + pCenterX += pWidth * 0.5f * pScale - width * 0.5f * getScaleX(); + } + return pCenterX; + } + + virtual f32 getCenterY(void) + { + f32 pCenterY = 0.0f; + + if(parentElement) + pCenterY = parentElement->getCenterY(); + + pCenterY += yoffset + yoffsetDyn; + + if(alignment & ALIGN_TOP) + { + f32 pHeight = 0.0f; + f32 pScale = 0.0f; + + if(parentElement) + { + pHeight = parentElement->getHeight(); + pScale = parentElement->getScaleY(); + } + + pCenterY += pHeight * 0.5f * pScale - height * 0.5f * getScaleY(); + } + else if(alignment & ALIGN_BOTTOM) + { + f32 pHeight = 0.0f; + f32 pScale = 0.0f; + + if(parentElement) + { + pHeight = parentElement->getHeight(); + pScale = parentElement->getScaleY(); + } + + pCenterY -= pHeight * 0.5f * pScale - height * 0.5f * getScaleY(); + } + return pCenterY; + } + //!Gets elements xoffset + virtual f32 getOffsetX() { return xoffset; } + //!Gets elements yoffset + virtual f32 getOffsetY() { return yoffset; } + //!Gets the current width of the element. Does not currently consider the scale + //!\return width + virtual f32 getWidth() { return width; }; + //!Gets the height of the element. Does not currently consider the scale + //!\return height + virtual f32 getHeight() { return height; } + //!Sets the size (width/height) of the element + //!\param w Width of element + //!\param h Height of element + virtual void setSize(f32 w, f32 h) + { + width = w; + height = h; + } + //!Sets the element's visibility + //!\param v Visibility (true = visible) + virtual void setVisible(bool v) + { + visible = v; + visibleChanged(this, v); + } + //!Checks whether or not the element is visible + //!\return true if visible, false otherwise + virtual bool isVisible() const { return !isStateSet(STATE_HIDDEN) && visible; }; + //!Checks whether or not the element is selectable + //!\return true if selectable, false otherwise + virtual bool isSelectable() + { + return !isStateSet(STATE_DISABLED) && selectable; + } + virtual bool isDrawOverOnlyWhenSelected() + { + return drawOverOnlyWhenSelected; + } + virtual void setdrawOverOnlyWhenSelected(bool s) { drawOverOnlyWhenSelected = s; } + //!Checks whether or not the element is clickable + //!\return true if clickable, false otherwise + virtual bool isClickable() + { + return !isStateSet(STATE_DISABLED) && clickable; + } + //!Checks whether or not the element is holdable + //!\return true if holdable, false otherwise + virtual bool isHoldable() { return !isStateSet(STATE_DISABLED) && holdable; } + //!Sets whether or not the element is selectable + //!\param s Selectable + virtual void setSelectable(bool s) { selectable = s; } + //!Sets whether or not the element is clickable + //!\param c Clickable + virtual void setClickable(bool c) { clickable = c; } + //!Sets whether or not the element is holdable + //!\param c Holdable + virtual void setHoldable(bool d) { holdable = d; } + //!Sets the element's state + //!\param s State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED) + //!\param c Controller channel (0-3, -1 = none) + virtual void setState(int s, int c = -1) + { + if(c >= 0 && c < 4) + { + state[c] |= s; + } + else + { + for(int i = 0; i < 4; i++) + state[i] |= s; + } + stateChan = c; + stateChanged(this, s, c); + } + virtual void clearState(int s, int c = -1) + { + if(c >= 0 && c < 4) + { + state[c] &= ~s; + } + else + { + for(int i = 0; i < 4; i++) + state[i] &= ~s; + } + stateChan = c; + stateChanged(this, s, c); + } + virtual bool isStateSet(int s, int c = -1) const + { + if(c >= 0 && c < 4) + { + return (state[c] & s) != 0; + } + else + { + for(int i = 0; i < 4; i++) + if((state[i] & s) != 0) + return true; + + return false; + } + } + //!Gets the element's current state + //!\return state + virtual int getState(int c = 0) { return state[c]; }; + //!Gets the controller channel that last changed the element's state + //!\return Channel number (0-3, -1 = no channel) + virtual int getStateChan() { return stateChan; }; + //!Resets the element's state to STATE_DEFAULT + virtual void resetState() + { + for(int i = 0; i < 4; i++) + state[i] = STATE_DEFAULT; + stateChan = -1; + } + //!Sets the element's alpha value + //!\param a alpha value + virtual void setAlpha(f32 a) { alpha = a; } + //!Gets the element's alpha value + //!Considers alpha, alphaDyn, and the parent element's getAlpha() value + //!\return alpha + virtual f32 getAlpha() + { + f32 a; + + if(alphaDyn >= 0) + a = alphaDyn; + else + a = alpha; + + if(parentElement) + a = (a * parentElement->getAlpha()); + + return a; + } + //!Sets the element's scale + //!\param s scale (1 is 100%) + virtual void setScale(float s) + { + scaleX = s; + scaleY = s; + scaleZ = s; + } + //!Sets the element's scale + //!\param s scale (1 is 100%) + virtual void setScaleX(float s) { scaleX = s; } + //!Sets the element's scale + //!\param s scale (1 is 100%) + virtual void setScaleY(float s) { scaleY = s; } + //!Sets the element's scale + //!\param s scale (1 is 100%) + virtual void setScaleZ(float s) { scaleZ = s; } + //!Gets the element's current scale + //!Considers scale, scaleDyn, and the parent element's getScale() value + virtual float getScale() + { + float s = 0.5f * (scaleX+scaleY) * scaleDyn; + + if(parentElement) + s *= parentElement->getScale(); + + return s; + } + //!Gets the element's current scale + //!Considers scale, scaleDyn, and the parent element's getScale() value + virtual float getScaleX() + { + float s = scaleX * scaleDyn; + + if(parentElement) + s *= parentElement->getScaleX(); + + return s; + } + //!Gets the element's current scale + //!Considers scale, scaleDyn, and the parent element's getScale() value + virtual float getScaleY() + { + float s = scaleY * scaleDyn; + + if(parentElement) + s *= parentElement->getScaleY(); + + return s; + } + //!Gets the element's current scale + //!Considers scale, scaleDyn, and the parent element's getScale() value + virtual float getScaleZ() + { + float s = scaleZ; + + if(parentElement) + s *= parentElement->getScaleZ(); + + return s; + } + //!Checks whether rumble was requested by the element + //!\return true is rumble was requested, false otherwise + virtual bool isRumbleActive() { return rumble; } + //!Sets whether or not the element is requesting a rumble event + //!\param r true if requesting rumble, false if not + virtual void setRumble(bool r) { rumble = r; } + //!Set an effect for the element + //!\param e Effect to enable + //!\param a Amount of the effect (usage varies on effect) + //!\param t Target amount of the effect (usage varies on effect) + virtual void setEffect(int e, int a, int t=0); + //!Sets an effect to be enabled on wiimote cursor over + //!\param e Effect to enable + //!\param a Amount of the effect (usage varies on effect) + //!\param t Target amount of the effect (usage varies on effect) + virtual void setEffectOnOver(int e, int a, int t=0); + //!Shortcut to SetEffectOnOver(EFFECT_SCALE, 4, 110) + virtual void setEffectGrow() { setEffectOnOver(EFFECT_SCALE, 4, 110); } + //!Reset all applied effects + virtual void resetEffects(); + //!Gets the current element effects + //!\return element effects + virtual int getEffect() const { return effects; } + //!\return true if element animation is on going + virtual bool isAnimated() const { return (parentElement != 0) && (getEffect() > 0); } + //!Checks whether the specified coordinates are within the element's boundaries + //!\param x X coordinate + //!\param y Y coordinate + //!\return true if contained within, false otherwise + virtual bool isInside(f32 x, f32 y) + { + return ( x > (this->getCenterX() - getScaleX() * getWidth() * 0.5f) + && x < (this->getCenterX() + getScaleX() * getWidth() * 0.5f) + && y > (this->getCenterY() - getScaleY() * getHeight() * 0.5f) + && y < (this->getCenterY() + getScaleY() * getHeight() * 0.5f)); + } + //!Sets the element's position + //!\param x X coordinate + //!\param y Y coordinate + virtual void setPosition(f32 x, f32 y) + { + xoffset = x; + yoffset = y; + } + //!Sets the element's position + //!\param x X coordinate + //!\param y Y coordinate + //!\param z Z coordinate + virtual void setPosition(f32 x, f32 y, f32 z) + { + xoffset = x; + yoffset = y; + zoffset = z; + } + //!Gets whether or not the element is in STATE_SELECTED + //!\return true if selected, false otherwise + virtual int getSelected() { return -1; } + //!Sets the element's alignment respective to its parent element + //!Bitwise ALIGN_LEFT | ALIGN_RIGHT | ALIGN_CENTRE, ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) + //!\param align Alignment + virtual void setAlignment(int a) { alignment = a; } + //!Gets the element's alignment + virtual int getAlignment() const { return alignment; } + //!Angle of the object + virtual void setAngle(f32 a) { angle = a; } + //!Angle of the object + virtual f32 getAngle() const { f32 r_angle = angle; if(parentElement) r_angle += parentElement->getAngle(); return r_angle; } + //!Called constantly to allow the element to respond to the current input data + //!\param t Pointer to a GuiController, containing the current input data from PAD/WPAD/VPAD + virtual void update(GuiController * t) { } + //!Called constantly to redraw the element + virtual void draw(CVideo * v) { } + //!Called constantly to process stuff in the element + virtual void process() { } + + //!Updates the element's effects (dynamic values) + //!Called by Draw(), used for animation purposes + virtual void updateEffects(); + + typedef struct _POINT { + s32 x; + s32 y; + } POINT; + + enum + { + STATE_DEFAULT = 0, + STATE_SELECTED = 0x01, + STATE_CLICKED = 0x02, + STATE_HELD = 0x04, + STATE_OVER = 0x08, + STATE_HIDDEN = 0x10, + STATE_DISABLE_INPUT = 0x20, + STATE_CLICKED_TOUCH = 0x40, + STATE_DISABLED = 0x80 + }; + + //! Switch pointer from control to screen position + POINT PtrToScreen(POINT p) + { + //! TODO for 3D + //POINT r = { p.x + getLeft(), p.y + getTop() }; + return p; + } + //! Switch pointer screen to control position + POINT PtrToControl(POINT p) + { + //! TODO for 3D + //POINT r = { p.x - getLeft(), p.y - getTop() }; + return p; + } + //! Signals + sigslot::signal2 visibleChanged; + sigslot::signal3 stateChanged; + sigslot::signal1 effectFinished; + protected: + f32 xoffset; //!< Element X offset + f32 yoffset; //!< Element Y offset + bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event + bool visible; //!< Visibility of the element. If false, Draw() is skipped + bool selectable; //!< Whether or not this element selectable (can change to SELECTED state) + bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state) + bool holdable; //!< Whether or not this element is holdable (can change to HELD state) + bool drawOverOnlyWhenSelected; //!< Whether or not this element is holdable (can change to HELD state) + f32 width; //!< Element width + f32 height; //!< Element height + f32 zoffset; //!< Element Z offset + f32 alpha; //!< Element alpha value (0-255) + f32 angle; //!< Angle of the object (0-360) + f32 scaleX; //!< Element scale (1 = 100%) + f32 scaleY; //!< Element scale (1 = 100%) + f32 scaleZ; //!< Element scale (1 = 100%) + int alignment; //!< Horizontal element alignment, respective to parent element + int state[4]; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED) + int stateChan; //!< Which controller channel is responsible for the last change in state + GuiElement * parentElement; //!< Parent element + + //! TODO: Move me to some Animator class + int xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects) + int yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects) + f32 alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects) + f32 scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects) + int effects; //!< Currently enabled effect(s). 0 when no effects are enabled + int effectAmount; //!< Effect amount. Used by different effects for different purposes + int effectTarget; //!< Effect target amount. Used by different effects for different purposes + int effectsOver; //!< Effects to enable when wiimote cursor is over this element. Copied to effects variable on over event + int effectAmountOver; //!< EffectAmount to set when wiimote cursor is over this element + int effectTargetOver; //!< EffectTarget to set when wiimote cursor is over this element +}; + +#endif diff --git a/src/gui/GuiFrame.cpp b/src/gui/GuiFrame.cpp new file mode 100644 index 0000000..ac37917 --- /dev/null +++ b/src/gui/GuiFrame.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "GuiFrame.h" + +GuiFrame::GuiFrame(GuiFrame *p) +{ + parent = p; + width = 0; + height = 0; + dim = false; + + if(parent) + parent->append(this); +} + +GuiFrame::GuiFrame(f32 w, f32 h, GuiFrame *p) +{ + parent = p; + width = w; + height = h; + dim = false; + + if(parent) + parent->append(this); +} + +GuiFrame::~GuiFrame() +{ + closing(this); + + if(parent) + parent->remove(this); +} + +void GuiFrame::append(GuiElement* e) +{ + if (e == NULL) + return; + + remove(e); + elements.push_back(e); + e->setParent(this); +} + +void GuiFrame::insert(GuiElement* e, u32 index) +{ + if (e == NULL || (index >= elements.size())) + return; + + remove(e); + elements.insert(elements.begin()+index, e); + e->setParent(this); +} + +void GuiFrame::remove(GuiElement* e) +{ + if (e == NULL) + return; + + for (u32 i = 0; i < elements.size(); ++i) + { + if(e == elements[i]) + { + elements.erase(elements.begin()+i); + break; + } + } +} + +void GuiFrame::removeAll() +{ + elements.clear(); +} + +void GuiFrame::close() +{ + //Application::instance()->pushForDelete(this); +} + +void GuiFrame::dimBackground(bool d) +{ + dim = d; +} + +GuiElement* GuiFrame::getGuiElementAt(u32 index) const +{ + if (index >= elements.size()) + return NULL; + return elements[index]; +} + +u32 GuiFrame::getSize() +{ + return elements.size(); +} + +void GuiFrame::resetState() +{ + GuiElement::resetState(); + + for (u32 i = 0; i < elements.size(); ++i) + { + elements[i]->resetState(); + } +} + +void GuiFrame::setState(int s, int c) +{ + GuiElement::setState(s, c); + + for (u32 i = 0; i < elements.size(); ++i) + { + elements[i]->setState(s, c); + } +} + +void GuiFrame::clearState(int s, int c) +{ + GuiElement::clearState(s, c); + + for (u32 i = 0; i < elements.size(); ++i) + { + elements[i]->clearState(s, c); + } +} + +void GuiFrame::setVisible(bool v) +{ + visible = v; + + for (u32 i = 0; i < elements.size(); ++i) + { + elements[i]->setVisible(v); + } +} + +int GuiFrame::getSelected() +{ + // find selected element + int found = -1; + for (u32 i = 0; i < elements.size(); ++i) + { + if(elements[i]->isStateSet(STATE_SELECTED | STATE_OVER)) + { + found = i; + break; + } + } + return found; +} + +void GuiFrame::draw(CVideo * v) +{ + if(!this->isVisible() && parentElement) + return; + + if(parentElement && dim == true) + { + //GXColor dimColor = (GXColor){0, 0, 0, 0x70}; + //Menu_DrawRectangle(0, 0, GetZPosition(), screenwidth,screenheight, &dimColor, false, true); + } + + //! render appended items next frame but allow stop of render if size is reached + u32 size = elements.size(); + + for (u32 i = 0; i < size && i < elements.size(); ++i) + { + elements[i]->draw(v); + } +} + +void GuiFrame::updateEffects() +{ + if(!this->isVisible() && parentElement) + return; + + GuiElement::updateEffects(); + + //! render appended items next frame but allow stop of render if size is reached + u32 size = elements.size(); + + for (u32 i = 0; i < size && i < elements.size(); ++i) + { + elements[i]->updateEffects(); + } +} + +void GuiFrame::process() +{ + if(!this->isVisible() && parentElement) + return; + + GuiElement::process(); + + //! render appended items next frame but allow stop of render if size is reached + u32 size = elements.size(); + + for (u32 i = 0; i < size && i < elements.size(); ++i) + { + elements[i]->process(); + } +} + +void GuiFrame::update(GuiController * c) +{ + if(isStateSet(STATE_DISABLED) && parentElement) + return; + + //! update appended items next frame + u32 size = elements.size(); + + for (u32 i = 0; i < size && i < elements.size(); ++i) + { + elements[i]->update(c); + } +} diff --git a/src/gui/GuiFrame.h b/src/gui/GuiFrame.h new file mode 100644 index 0000000..e0a5c36 --- /dev/null +++ b/src/gui/GuiFrame.h @@ -0,0 +1,98 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef GUI_FRAME_H_ +#define GUI_FRAME_H_ + +#include +#include "GuiElement.h" +#include "sigslot.h" + +//!Allows GuiElements to be grouped together into a "window" +class GuiFrame : public GuiElement +{ + public: + //!Constructor + GuiFrame(GuiFrame *parent = 0); + //!\overload + //!\param w Width of window + //!\param h Height of window + GuiFrame(f32 w, f32 h, GuiFrame *parent = 0); + //!Destructor + virtual ~GuiFrame(); + //!Appends a GuiElement to the GuiFrame + //!\param e The GuiElement to append. If it is already in the GuiFrame, it is removed first + void append(GuiElement* e); + //!Inserts a GuiElement into the GuiFrame at the specified index + //!\param e The GuiElement to insert. If it is already in the GuiFrame, it is removed first + //!\param i Index in which to insert the element + void insert(GuiElement* e, u32 i); + //!Removes the specified GuiElement from the GuiFrame + //!\param e GuiElement to be removed + void remove(GuiElement* e); + //!Removes all GuiElements + void removeAll(); + //!Bring element to front of the window + void bringToFront(GuiElement *e) { remove(e); append(e); } + //!Returns the GuiElement at the specified index + //!\param index The index of the element + //!\return A pointer to the element at the index, NULL on error (eg: out of bounds) + GuiElement* getGuiElementAt(u32 index) const; + //!Returns the size of the list of elements + //!\return The size of the current element list + u32 getSize(); + //!Sets the visibility of the window + //!\param v visibility (true = visible) + void setVisible(bool v); + //!Resets the window's state to STATE_DEFAULT + void resetState(); + //!Sets the window's state + //!\param s State + void setState(int s, int c = -1); + void clearState(int s, int c = -1); + //!Gets the index of the GuiElement inside the window that is currently selected + //!\return index of selected GuiElement + int getSelected(); + //!Dim the Window's background + void dimBackground(bool d); + //!Draws all the elements in this GuiFrame + void draw(CVideo * v); + //!Updates the window and all elements contains within + //!Allows the GuiFrame and all elements to respond to the input data specified + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + void update(GuiController * t); + //!virtual Close Window - this will put the object on the delete queue in MainWindow + virtual void close(); + //!virtual show window function + virtual void show() {} + //!virtual hide window function + virtual void hide() {} + //!virtual enter main loop function (blocking) + virtual void exec() {} + //!virtual updateEffects which is called by the main loop + virtual void updateEffects(); + //!virtual process which is called by the main loop + virtual void process(); + //! Signals + //! On Closing + sigslot::signal1 closing; + protected: + bool dim; //! Enable/disable dim of a window only + GuiFrame *parent; //!< Parent Window + std::vector elements; //!< Contains all elements within the GuiFrame +}; + +#endif diff --git a/src/gui/GuiImage.cpp b/src/gui/GuiImage.cpp new file mode 100644 index 0000000..344b770 --- /dev/null +++ b/src/gui/GuiImage.cpp @@ -0,0 +1,289 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "GuiImage.h" +#include "video/CVideo.h" +#include "video/shaders/Texture2DShader.h" +#include "video/shaders/ColorShader.h" + +static const f32 fPiDiv180 = ((f32)M_PI / 180.0f); + +GuiImage::GuiImage(GuiImageData * img) +{ + if(img && img->getTexture()) + { + width = img->getWidth(); + height = img->getHeight(); + } + + internalInit(width, height); + imageData = img; +} + +GuiImage::GuiImage(int w, int h, const GX2Color & c, int type) +{ + internalInit(w, h); + imgType = type; + colorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize; + + colorVtxs = (u8 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, colorCount * ColorShader::cuColorAttrSize); + if(colorVtxs) + { + for(u32 i = 0; i < colorCount; i++) + setImageColor(c, i); + } +} + +GuiImage::GuiImage(int w, int h, const GX2Color *c, u32 color_count, int type) +{ + internalInit(w, h); + imgType = type; + colorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize; + if(colorCount < color_count) + colorCount = color_count; + + colorVtxs = (u8 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, colorCount * ColorShader::cuColorAttrSize); + if(colorVtxs) + { + for(u32 i = 0; i < colorCount; i++) + { + // take the last as reference if not enough colors defined + int idx = (i < color_count) ? i : (color_count - 1); + setImageColor(c[idx], i); + } + } +} + +/** + * Destructor for the GuiImage class. + */ +GuiImage::~GuiImage() +{ + if(colorVtxs) { + free(colorVtxs); + colorVtxs = NULL; + } +} + +void GuiImage::internalInit(int w, int h) +{ + imageData = NULL; + width = w; + height = h; + tileHorizontal = -1; + tileVertical = -1; + imgType = IMAGE_TEXTURE; + colorVtxsDirty = false; + colorVtxs = NULL; + colorCount = 0; + posVtxs = NULL; + texCoords = NULL; + vtxCount = 4; + primitive = GX2_PRIMITIVE_QUADS; + + imageAngle = 0.0f; + blurDirection = glm::vec3(0.0f); + positionOffsets = glm::vec3(0.0f); + scaleFactor = glm::vec3(1.0f); + colorIntensity = glm::vec4(1.0f); +} + +void GuiImage::setImageData(GuiImageData * img) +{ + imageData = img; + width = 0; + height = 0; + if(img && img->getTexture()) + { + width = img->getWidth(); + height = img->getHeight(); + } + imgType = IMAGE_TEXTURE; +} + +GX2Color GuiImage::getPixel(int x, int y) +{ + if(!imageData || this->getWidth() <= 0 || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight()) + return (GX2Color){0, 0, 0, 0}; + + u32 pitch = imageData->getTexture()->surface.pitch; + u32 *imagePtr = (u32*)imageData->getTexture()->surface.image_data; + + u32 color_u32 = imagePtr[y * pitch + x]; + GX2Color color; + color.r = (color_u32 >> 24) & 0xFF; + color.g = (color_u32 >> 16) & 0xFF; + color.b = (color_u32 >> 8) & 0xFF; + color.a = (color_u32 >> 0) & 0xFF; + return color; +} + +void GuiImage::setPixel(int x, int y, const GX2Color & color) +{ + if(!imageData || this->getWidth() <= 0 || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight()) + return; + + + u32 pitch = imageData->getTexture()->surface.pitch; + u32 *imagePtr = (u32*)imageData->getTexture()->surface.image_data; + imagePtr[y * pitch + x] = (color.r << 24) | (color.g << 16) | (color.b << 8) | (color.a << 0); +} + +void GuiImage::setImageColor(const GX2Color & c, int idx) +{ + if(!colorVtxs) { + return; + } + + if(idx >= 0 && idx < (int)colorCount) + { + colorVtxs[(idx << 2) + 0] = c.r; + colorVtxs[(idx << 2) + 1] = c.g; + colorVtxs[(idx << 2) + 2] = c.b; + colorVtxs[(idx << 2) + 3] = c.a; + colorVtxsDirty = true; + } + else if(colorVtxs) + { + for(u32 i = 0; i < (ColorShader::cuColorVtxsSize / sizeof(u8)); i += 4) + { + colorVtxs[i + 0] = c.r; + colorVtxs[i + 1] = c.g; + colorVtxs[i + 2] = c.b; + colorVtxs[i + 3] = c.a; + } + colorVtxsDirty = true; + } +} + +void GuiImage::setSize(int w, int h) +{ + width = w; + height = h; +} + +void GuiImage::setPrimitiveVertex(s32 prim, const f32 *posVtx, const f32 *texCoord, u32 vtxcount) +{ + primitive = prim; + vtxCount = vtxcount; + posVtxs = posVtx; + texCoords = texCoord; + + if(imgType == IMAGE_COLOR) + { + u8 * newColorVtxs = (u8 *) memalign(0x40, ColorShader::cuColorAttrSize * vtxCount); + + for(u32 i = 0; i < vtxCount; i++) + { + int newColorIdx = (i << 2); + int colorIdx = (i < colorCount) ? (newColorIdx) : ((colorCount - 1) << 2); + + newColorVtxs[newColorIdx + 0] = colorVtxs[colorIdx + 0]; + newColorVtxs[newColorIdx + 1] = colorVtxs[colorIdx + 1]; + newColorVtxs[newColorIdx + 2] = colorVtxs[colorIdx + 2]; + newColorVtxs[newColorIdx + 3] = colorVtxs[colorIdx + 3]; + } + + free(colorVtxs); + colorVtxs = newColorVtxs; + colorCount = vtxCount; + colorVtxsDirty = true; + } +} + +void GuiImage::draw(CVideo *pVideo) +{ + if(!this->isVisible() || tileVertical == 0 || tileHorizontal == 0) + return; + + f32 currScaleX = getScaleX(); + f32 currScaleY = getScaleY(); + + positionOffsets[0] = getCenterX() * pVideo->getWidthScaleFactor() * 2.0f; + positionOffsets[1] = getCenterY() * pVideo->getHeightScaleFactor() * 2.0f; + positionOffsets[2] = getDepth() * pVideo->getDepthScaleFactor() * 2.0f; + + scaleFactor[0] = currScaleX * getWidth() * pVideo->getWidthScaleFactor(); + scaleFactor[1] = currScaleY * getHeight() * pVideo->getHeightScaleFactor(); + scaleFactor[2] = getScaleZ(); + + //! add other colors intensities parameters + colorIntensity[3] = getAlpha(); + + //! angle of the object + imageAngle = DegToRad(getAngle()); + +// if(image && tileHorizontal > 0 && tileVertical > 0) +// { +// for(int n=0; n 0) +// { +// for(int i=0; i 0) +// { +// for(int i=0; isetShaders(); + ColorShader::instance()->setAttributeBuffer(colorVtxs, posVtxs, vtxCount); + ColorShader::instance()->setAngle(imageAngle); + ColorShader::instance()->setOffset(positionOffsets); + ColorShader::instance()->setScale(scaleFactor); + ColorShader::instance()->setColorIntensity(colorIntensity); + ColorShader::instance()->draw(primitive, vtxCount); + } + else if(imageData) + { + Texture2DShader::instance()->setShaders(); + Texture2DShader::instance()->setAttributeBuffer(texCoords, posVtxs, vtxCount); + Texture2DShader::instance()->setAngle(imageAngle); + Texture2DShader::instance()->setOffset(positionOffsets); + Texture2DShader::instance()->setScale(scaleFactor); + Texture2DShader::instance()->setColorIntensity(colorIntensity); + Texture2DShader::instance()->setBlurring(blurDirection); + Texture2DShader::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler()); + Texture2DShader::instance()->draw(primitive, vtxCount); + } +} diff --git a/src/gui/GuiImage.h b/src/gui/GuiImage.h new file mode 100644 index 0000000..88f7fbe --- /dev/null +++ b/src/gui/GuiImage.h @@ -0,0 +1,110 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef GUI_IMAGE_H_ +#define GUI_IMAGE_H_ + +#include "video/shaders/Shader.h" +#include "GuiElement.h" +#include "GuiImageData.h" + +//!Display, manage, and manipulate images in the GUI +class GuiImage : public GuiElement +{ +public: + enum ImageTypes + { + IMAGE_TEXTURE, + IMAGE_COLOR + }; + + //!\overload + //!\param img Pointer to GuiImageData element + GuiImage(GuiImageData * img); + //!\overload + //!Creates an image filled with the specified color + //!\param w Image width + //!\param h Image height + //!\param c Array with 4 x image color (BL, BR, TL, TR) + GuiImage(int w, int h, const GX2Color & c, int imgType = IMAGE_COLOR); + GuiImage(int w, int h, const GX2Color * c, u32 colorCount = 1, int imgType = IMAGE_COLOR); + //!Destructor + virtual ~GuiImage(); + //!Sets the number of times to draw the image horizontally + //!\param t Number of times to draw the image + void setTileHorizontal(int t) { tileHorizontal = t; } + //!Sets the number of times to draw the image vertically + //!\param t Number of times to draw the image + void setTileVertical(int t) { tileVertical = t; } + //!Constantly called to draw the image + void draw(CVideo *pVideo); + //!Gets the image data + //!\return pointer to image data + GuiImageData * getImageData() const { return imageData; } + //!Sets up a new image using the GuiImageData object specified + //!\param img Pointer to GuiImageData object + void setImageData(GuiImageData * img); + //!Gets the pixel color at the specified coordinates of the image + //!\param x X coordinate + //!\param y Y coordinate + GX2Color getPixel(int x, int y); + //!Sets the pixel color at the specified coordinates of the image + //!\param x X coordinate + //!\param y Y coordinate + //!\param color Pixel color + void setPixel(int x, int y, const GX2Color & color); + //!Change ImageColor + void setImageColor(const GX2Color & c, int idx = -1); + //!Change ImageColor + void setSize(int w, int h); + + void setPrimitiveVertex(s32 prim, const f32 *pos, const f32 *tex, u32 count); + + void setBlurDirection(u8 dir, f32 value) + { + if(dir < 2) { + blurDirection[dir] = value; + } + } + void setColorIntensity(const glm::vec4 & col) + { + colorIntensity = col; + } +protected: + void internalInit(int w, int h); + + int imgType; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA) + GuiImageData * imageData; //!< Poiner to image data. May be shared with GuiImageData data + int tileHorizontal; //!< Number of times to draw (tile) the image horizontally + int tileVertical; //!< Number of times to draw (tile) the image vertically + + //! Internally used variables for rendering + u8 *colorVtxs; + u32 colorCount; + bool colorVtxsDirty; + glm::vec3 positionOffsets; + glm::vec3 scaleFactor; + glm::vec4 colorIntensity; + f32 imageAngle; + glm::vec3 blurDirection; + + const f32 * posVtxs; + const f32 * texCoords; + u32 vtxCount; + s32 primitive; +}; + +#endif diff --git a/src/gui/GuiImageAsync.cpp b/src/gui/GuiImageAsync.cpp new file mode 100644 index 0000000..f798997 --- /dev/null +++ b/src/gui/GuiImageAsync.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include "GuiImageAsync.h" +#include "fs/fs_utils.h" + +std::vector GuiImageAsync::imageQueue; +CThread * GuiImageAsync::pThread = NULL; +CMutex * GuiImageAsync::pMutex = NULL; +u32 GuiImageAsync::threadRefCounter = 0; +bool GuiImageAsync::bExitRequested = false; +GuiImageAsync * GuiImageAsync::pInUse = NULL; + +GuiImageAsync::GuiImageAsync(const u8 *imageBuffer, const u32 & imageBufferSize, GuiImageData * preloadImg) + : GuiImage(preloadImg) + , imgData(NULL) + , imgBuffer(imageBuffer) + , imgBufferSize(imageBufferSize) +{ + threadInit(); + threadAddImage(this); +} + +GuiImageAsync::GuiImageAsync(const std::string & file, GuiImageData * preloadImg) + : GuiImage(preloadImg) + , imgData(NULL) + , filename(file) + , imgBuffer(NULL) + , imgBufferSize(0) +{ + threadInit(); + threadAddImage(this); +} + +GuiImageAsync::~GuiImageAsync() +{ + threadRemoveImage(this); + while(pInUse == this) + usleep(1000); + + if (imgData) + delete imgData; + + //threadExit(); +} + +void GuiImageAsync::threadAddImage(GuiImageAsync *Image) +{ + pMutex->lock(); + imageQueue.push_back(Image); + pMutex->unlock(); + pThread->resumeThread(); +} + +void GuiImageAsync::threadRemoveImage(GuiImageAsync *image) +{ + pMutex->lock(); + for(u32 i = 0; i < imageQueue.size(); ++i) + { + if(imageQueue[i] == image) + { + imageQueue.erase(imageQueue.begin() + i); + break; + } + } + pMutex->unlock(); +} + +void GuiImageAsync::clearQueue() +{ + pMutex->lock(); + imageQueue.clear(); + pMutex->unlock(); +} + +void GuiImageAsync::guiImageAsyncThread(CThread *thread, void *arg) +{ + while(!bExitRequested) + { + if(imageQueue.empty() && !bExitRequested) + pThread->suspendThread(); + + if(!imageQueue.empty() && !bExitRequested) + { + pMutex->lock(); + pInUse = imageQueue.front(); + imageQueue.erase(imageQueue.begin()); + pMutex->unlock(); + + if (!pInUse) + continue; + + + if(pInUse->imgBuffer && pInUse->imgBufferSize) + { + pInUse->imgData = new GuiImageData(pInUse->imgBuffer, pInUse->imgBufferSize); + } + else + { + u8 *buffer = NULL; + u32 bufferSize = 0; + + int iResult = LoadFileToMem(pInUse->filename.c_str(), &buffer, &bufferSize); + if(iResult > 0) + { + pInUse->imgData = new GuiImageData(buffer, bufferSize, GX2_TEX_CLAMP_MIRROR); + + //! free original image buffer which is converted to texture now and not needed anymore + free(buffer); + } + } + + if(pInUse->imgData) + { + if(pInUse->imgData->getTexture()) + { + pInUse->width = pInUse->imgData->getWidth(); + pInUse->height = pInUse->imgData->getHeight(); + pInUse->imageData = pInUse->imgData; + } + else + { + delete pInUse->imgData; + pInUse->imgData = NULL; + } + } + pInUse->imageLoaded(pInUse); + pInUse = NULL; + } + } +} + +void GuiImageAsync::threadInit() +{ + if (pThread == NULL) + { + bExitRequested = false; + pMutex = new CMutex(); + pThread = CThread::create(GuiImageAsync::guiImageAsyncThread, NULL, CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 10); + pThread->resumeThread(); + } + + ++threadRefCounter; +} + +void GuiImageAsync::threadExit() +{ + if(threadRefCounter) + --threadRefCounter; + + if(/*(threadRefCounter == 0) &&*/ (pThread != NULL)) + { + bExitRequested = true; + delete pThread; + delete pMutex; + pThread = NULL; + pMutex = NULL; + } +} diff --git a/src/gui/GuiImageAsync.h b/src/gui/GuiImageAsync.h new file mode 100644 index 0000000..bf2622a --- /dev/null +++ b/src/gui/GuiImageAsync.h @@ -0,0 +1,62 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef _GUIIMAGEASYNC_H_ +#define _GUIIMAGEASYNC_H_ + +#include +#include "GuiImage.h" +#include "system/CThread.h" +#include "system/CMutex.h" +#include "dynamic_libs/os_functions.h" + +class GuiImageAsync : public GuiImage +{ + public: + GuiImageAsync(const u8 *imageBuffer, const u32 & imageBufferSize, GuiImageData * preloadImg); + GuiImageAsync(const std::string & filename, GuiImageData * preloadImg); + virtual ~GuiImageAsync(); + + static void clearQueue(); + static void removeFromQueue(GuiImageAsync * image) { + threadRemoveImage(image); + } + + //! don't forget to LOCK GUI if using this asynchron call + sigslot::signal1 imageLoaded; + static void threadExit(); + + private: + static void threadInit(); + + GuiImageData *imgData; + std::string filename; + const u8 *imgBuffer; + const u32 imgBufferSize; + + static void guiImageAsyncThread(CThread *thread, void *arg); + static void threadAddImage(GuiImageAsync* Image); + static void threadRemoveImage(GuiImageAsync* Image); + + static std::vector imageQueue; + static CThread *pThread; + static CMutex * pMutex; + static u32 threadRefCounter; + static GuiImageAsync * pInUse; + static bool bExitRequested; +}; + +#endif /*_GUIIMAGEASYNC_H_*/ diff --git a/src/gui/GuiImageData.cpp b/src/gui/GuiImageData.cpp new file mode 100644 index 0000000..7e9a790 --- /dev/null +++ b/src/gui/GuiImageData.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include +#include "GuiImageData.h" +#include "system/memory.h" +/** + * Constructor for the GuiImageData class. + */ +GuiImageData::GuiImageData() +{ + texture = NULL; + sampler = NULL; + memoryType = eMemTypeMEM2; +} + +/** + * Constructor for the GuiImageData class. + */ +GuiImageData::GuiImageData(const u8 * img, int imgSize, int textureClamp, int textureFormat) +{ + texture = NULL; + sampler = NULL; + loadImage(img, imgSize, textureClamp, textureFormat); +} + +/** + * Destructor for the GuiImageData class. + */ +GuiImageData::~GuiImageData() +{ + releaseData(); +} + +void GuiImageData::releaseData(void) +{ + if(texture) { + if(texture->surface.image_data) + { + switch(memoryType) + { + default: + case eMemTypeMEM2: + free(texture->surface.image_data); + break; + case eMemTypeMEM1: + MEM1_free(texture->surface.image_data); + break; + case eMemTypeMEMBucket: + MEMBucket_free(texture->surface.image_data); + break; + } + } + delete texture; + texture = NULL; + } + if(sampler) { + delete sampler; + sampler = NULL; + } +} + +void GuiImageData::loadImage(const u8 *img, int imgSize, int textureClamp, int textureFormat) +{ + if(!img || (imgSize < 8)) + return; + + releaseData(); + gdImagePtr gdImg = 0; + + if (img[0] == 0xFF && img[1] == 0xD8) + { + //! not needed for now therefore comment out to safe ELF size + //! if needed uncomment, adds 200 kb to the ELF size + // IMAGE_JPEG + gdImg = gdImageCreateFromJpegPtr(imgSize, (u8*) img); + } + else if (img[0] == 'B' && img[1] == 'M') + { + // IMAGE_BMP + gdImg = gdImageCreateFromBmpPtr(imgSize, (u8*) img); + } + else if (img[0] == 0x89 && img[1] == 'P' && img[2] == 'N' && img[3] == 'G') + { + // IMAGE_PNG + gdImg = gdImageCreateFromPngPtr(imgSize, (u8*) img); + } + //!This must be last since it can also intefere with outher formats + else if(img[0] == 0x00) + { + // Try loading TGA image + gdImg = gdImageCreateFromTgaPtr(imgSize, (u8*) img); + } + + if(gdImg == 0) + return; + + u32 width = (gdImageSX(gdImg)); + u32 height = (gdImageSY(gdImg)); + + //! Initialize texture + texture = new GX2Texture; + GX2InitTexture(texture, width, height, 1, 0, textureFormat, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_LINEAR_ALIGNED); + + //! if this fails something went horribly wrong + if(texture->surface.image_size == 0) { + delete texture; + texture = NULL; + gdImageDestroy(gdImg); + return; + } + + //! allocate memory for the surface + memoryType = eMemTypeMEM2; + texture->surface.image_data = memalign(texture->surface.align, texture->surface.image_size); + //! try MEM1 on failure + if(!texture->surface.image_data) { + memoryType = eMemTypeMEM1; + texture->surface.image_data = MEM1_alloc(texture->surface.image_size, texture->surface.align); + } + //! try MEM bucket on failure + if(!texture->surface.image_data) { + memoryType = eMemTypeMEMBucket; + texture->surface.image_data = MEMBucket_alloc(texture->surface.image_size, texture->surface.align); + } + //! check if memory is available for image + if(!texture->surface.image_data) { + gdImageDestroy(gdImg); + delete texture; + texture = NULL; + return; + } + //! set mip map data pointer + texture->surface.mip_data = NULL; + //! convert image to texture + switch(textureFormat) + { + default: + case GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM: + gdImageToUnormR8G8B8A8(gdImg, (u32*)texture->surface.image_data, texture->surface.width, texture->surface.height, texture->surface.pitch); + break; + case GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM: + gdImageToUnormR5G6B5(gdImg, (u16*)texture->surface.image_data, texture->surface.width, texture->surface.height, texture->surface.pitch); + break; + } + + //! free memory of image as its not needed anymore + gdImageDestroy(gdImg); + + //! invalidate the memory + GX2Invalidate(GX2_INVALIDATE_CPU_TEXTURE, texture->surface.image_data, texture->surface.image_size); + //! initialize the sampler + sampler = new GX2Sampler; + GX2InitSampler(sampler, textureClamp, GX2_TEX_XY_FILTER_BILINEAR); +} + +void GuiImageData::gdImageToUnormR8G8B8A8(gdImagePtr gdImg, u32 *imgBuffer, u32 width, u32 height, u32 pitch) +{ + for(u32 y = 0; y < height; ++y) + { + for(u32 x = 0; x < width; ++x) + { + u32 pixel = gdImageGetPixel(gdImg, x, y); + + u8 a = 254 - 2*((u8)gdImageAlpha(gdImg, pixel)); + if(a == 254) a++; + + u8 r = gdImageRed(gdImg, pixel); + u8 g = gdImageGreen(gdImg, pixel); + u8 b = gdImageBlue(gdImg, pixel); + + imgBuffer[y * pitch + x] = (r << 24) | (g << 16) | (b << 8) | (a); + } + } +} + +//! TODO: figure out why this seems to not work correct yet +void GuiImageData::gdImageToUnormR5G6B5(gdImagePtr gdImg, u16 *imgBuffer, u32 width, u32 height, u32 pitch) +{ + for(u32 y = 0; y < height; ++y) + { + for(u32 x = 0; x < width; ++x) + { + u32 pixel = gdImageGetPixel(gdImg, x, y); + + u8 r = gdImageRed(gdImg, pixel); + u8 g = gdImageGreen(gdImg, pixel); + u8 b = gdImageBlue(gdImg, pixel); + + imgBuffer[y * pitch + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); + } + } +} diff --git a/src/gui/GuiImageData.h b/src/gui/GuiImageData.h new file mode 100644 index 0000000..03bc1df --- /dev/null +++ b/src/gui/GuiImageData.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef GUI_IMAGEDATA_H_ +#define GUI_IMAGEDATA_H_ + +#include +#include +#include "dynamic_libs/gx2_functions.h" +#include "system/AsyncDeleter.h" + +class GuiImageData : public AsyncDeleter::Element +{ +public: + //!Constructor + GuiImageData(); + //!\param img Image data + //!\param imgSize The image size + GuiImageData(const u8 * img, int imgSize, int textureClamp = GX2_TEX_CLAMP_CLAMP, int textureFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM); + //!Destructor + virtual ~GuiImageData(); + //!Load image from buffer + //!\param img Image data + //!\param imgSize The image size + void loadImage(const u8 * img, int imgSize, int textureClamp = GX2_TEX_CLAMP_CLAMP, int textureFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM); + //! getter functions + const GX2Texture * getTexture() const { return texture; }; + const GX2Sampler * getSampler() const { return sampler; }; + //!Gets the image width + //!\return image width + int getWidth() const { if(texture) return texture->surface.width; else return 0; }; + //!Gets the image height + //!\return image height + int getHeight() const { if(texture) return texture->surface.height; else return 0; }; + //! release memory of the image data + void releaseData(void); +private: + void gdImageToUnormR8G8B8A8(gdImagePtr gdImg, u32 *imgBuffer, u32 width, u32 height, u32 pitch); + void gdImageToUnormR5G6B5(gdImagePtr gdImg, u16 *imgBuffer, u32 width, u32 height, u32 pitch); + + GX2Texture *texture; + GX2Sampler *sampler; + + enum eMemoryTypes + { + eMemTypeMEM2, + eMemTypeMEM1, + eMemTypeMEMBucket + }; + + u8 memoryType; +}; + +#endif diff --git a/src/gui/GuiMainWindowScreen.h b/src/gui/GuiMainWindowScreen.h new file mode 100644 index 0000000..0047b33 --- /dev/null +++ b/src/gui/GuiMainWindowScreen.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#ifndef GUI_MAIN_WINDOW_SCREEN_H_ +#define GUI_MAIN_WINDOW_SCREEN_H_ + +#include "Gui.h" +#include "sigslot.h" + +class GuiMainWindowScreen : public GuiFrame +{ +public: + GuiMainWindowScreen(int w, int h) : GuiFrame(w, h) {} + virtual ~GuiMainWindowScreen() {} +}; + +#endif /* GUI_MAIN_WINDOW_SCREEN_H_ */ diff --git a/src/gui/GuiParticleImage.cpp b/src/gui/GuiParticleImage.cpp new file mode 100644 index 0000000..e39930f --- /dev/null +++ b/src/gui/GuiParticleImage.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "GuiParticleImage.h" +#include "video/CVideo.h" +#include "video/shaders/ColorShader.h" + +#define CIRCLE_VERTEX_COUNT 36 + +static inline f32 getRandZeroToOneF32() +{ + return (rand() % 10000) * 0.0001f; +} + +static inline f32 getRandMinusOneToOneF32() +{ + return getRandZeroToOneF32() * 2.0f - 1.0f; +} + +GuiParticleImage::GuiParticleImage(int w, int h, u32 particleCount) + : GuiImage(NULL) +{ + width = w; + height = h; + imgType = IMAGE_COLOR; + + posVertexs = (f32 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuVertexAttrSize * CIRCLE_VERTEX_COUNT); + colorVertexs = (u8 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuColorAttrSize * CIRCLE_VERTEX_COUNT); + + for(u32 i = 0; i < CIRCLE_VERTEX_COUNT; i++) + { + posVertexs[i * 3 + 0] = cosf(DegToRad(i * 360.0f / CIRCLE_VERTEX_COUNT)); + posVertexs[i * 3 + 1] = sinf(DegToRad(i * 360.0f / CIRCLE_VERTEX_COUNT)); + posVertexs[i * 3 + 2] = 0.0f; + + colorVertexs[i * 4 + 0] = 0xff; + colorVertexs[i * 4 + 1] = 0xff; + colorVertexs[i * 4 + 2] = 0xff; + colorVertexs[i * 4 + 3] = 0xff; + } + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVertexs, ColorShader::cuVertexAttrSize * CIRCLE_VERTEX_COUNT); + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, colorVertexs, ColorShader::cuColorAttrSize * CIRCLE_VERTEX_COUNT); + + particles.resize(particleCount); + + for(u32 i = 0; i < particleCount; i++) + { + particles[i].position.x = getRandMinusOneToOneF32() * getWidth() * 0.5f; + particles[i].position.y = getRandMinusOneToOneF32() * getHeight() * 0.5f; + particles[i].position.z = 0.0f; + particles[i].colors = glm::vec4(1.0f, 1.0f, 1.0f, (getRandZeroToOneF32() * 0.6f) + 0.05f); + particles[i].radius = getRandZeroToOneF32() * 30.0f + 60.0f; + particles[i].speed = (getRandZeroToOneF32() * 0.4f) + 0.6f; + particles[i].direction = getRandMinusOneToOneF32(); + } +} + +GuiParticleImage::~GuiParticleImage() +{ + free(posVertexs); + free(colorVertexs); +} + +void GuiParticleImage::draw(CVideo *pVideo) +{ + if(!this->isVisible()) + return; + + + f32 currScaleX = getScaleX(); + f32 currScaleY = getScaleY(); + + positionOffsets[2] = getDepth() * pVideo->getDepthScaleFactor() * 2.0f; + + scaleFactor[2] = getScaleZ(); + + //! add other colors intensities parameters + colorIntensity[3] = getAlpha(); + + for(u32 i = 0; i < particles.size(); ++i) + { + if(particles[i].position.y > (getHeight() * 0.5f + 30.0f)) + { + particles[i].position.x = getRandMinusOneToOneF32() * getWidth() * 0.5f; + particles[i].position.y = -getHeight() * 0.5f - 30.0f; + particles[i].colors = glm::vec4(1.0f, 1.0f, 1.0f, (getRandZeroToOneF32() * 0.6f) + 0.05f); + particles[i].radius = getRandZeroToOneF32() * 30.0f + 60.0f; + particles[i].speed = (getRandZeroToOneF32() * 0.4f) + 0.6f; + particles[i].direction = getRandMinusOneToOneF32(); + } + if(particles[i].position.x < (-getWidth() * 0.5f - 50.0f)) + { + particles[i].position.x = -particles[i].position.x; + } + + + particles[i].direction += getRandMinusOneToOneF32() * 0.03f; + particles[i].position.x += particles[i].speed * particles[i].direction; + particles[i].position.y += particles[i].speed; + + positionOffsets[0] = (getCenterX() + particles[i].position.x) * pVideo->getWidthScaleFactor() * 2.0f; + positionOffsets[1] = (getCenterY() + particles[i].position.y) * pVideo->getHeightScaleFactor() * 2.0f; + + scaleFactor[0] = currScaleX * particles[i].radius * pVideo->getWidthScaleFactor(); + scaleFactor[1] = currScaleY * particles[i].radius * pVideo->getHeightScaleFactor(); + + ColorShader::instance()->setShaders(); + ColorShader::instance()->setAttributeBuffer(colorVertexs, posVertexs, CIRCLE_VERTEX_COUNT); + ColorShader::instance()->setAngle(0.0f); + ColorShader::instance()->setOffset(positionOffsets); + ColorShader::instance()->setScale(scaleFactor); + ColorShader::instance()->setColorIntensity(colorIntensity * particles[i].colors); + ColorShader::instance()->draw(GX2_PRIMITIVE_TRIANGLE_FAN, CIRCLE_VERTEX_COUNT); + } +} diff --git a/src/gui/GuiParticleImage.h b/src/gui/GuiParticleImage.h new file mode 100644 index 0000000..eb7565b --- /dev/null +++ b/src/gui/GuiParticleImage.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef _GUI_PARTICLE_IMAGE_H_ +#define _GUI_PARTICLE_IMAGE_H_ + +#include "GuiImage.h" + +class GuiParticleImage : public GuiImage, public sigslot::has_slots<> +{ +public: + GuiParticleImage(int w, int h, u32 particleCount); + virtual ~GuiParticleImage(); + + void draw(CVideo *pVideo); +private: + f32 *posVertexs; + u8 *colorVertexs; + + typedef struct + { + glm::vec3 position; + glm::vec4 colors; + f32 radius; + f32 speed; + f32 direction; + } Particle; + + std::vector particles; +}; + +#endif // _GUI_ICON_GRID_H_ diff --git a/src/gui/GuiSelectBox.cpp b/src/gui/GuiSelectBox.cpp new file mode 100644 index 0000000..827dc61 --- /dev/null +++ b/src/gui/GuiSelectBox.cpp @@ -0,0 +1,303 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#include +#include +#include "GuiSelectBox.h" +#include "GuiImage.h" +#include "GuiTrigger.h" +#include "GuiImageData.h" +#include "utils/StringTools.h" +/** + * Constructor for the GuiCheckBox class. + */ + +GuiSelectBox::GuiSelectBox(std::string caption,GuiFrame *parent) + : GuiFrame(300,300,parent) + ,selected(0) + ,captionText(caption) + ,topValueImageData(Resources::GetImageData("gameSettingsButton.png")) + ,topValueImage(topValueImageData) + ,topValueImageSelectedData(Resources::GetImageData("gameSettingsButtonSelected.png")) + ,topValueImageSelected(topValueImageSelectedData) + ,topValueButton(topValueImage.getWidth(),topValueImage.getHeight()) + ,valueImageData(Resources::GetImageData("gameSettingsButtonEx.png")) + ,valueSelectedImageData(Resources::GetImageData("gameSettingsButtonExSelected.png")) + ,valueHighlightedImageData(Resources::GetImageData("gameSettingsButtonExHighlighted.png")) + ,touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH) + ,wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A) + ,buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true) + ,buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true) + ,buttonUpTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_UP | GuiTrigger::STICK_L_UP, true) + ,buttonDownTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_DOWN | GuiTrigger::STICK_L_DOWN, true) + ,DPADButtons(5,5) + ,buttonClickSound(Resources::GetSound("settings_click_2.mp3")) + { + showValues = false; + bChanged = false; + bSelectedChanged = false; + opened = false; + topValueText.setFontSize(32); + topValueText.setAlignment(ALIGN_LEFT); + topValueText.setPosition(10,-7); + topValueButton.setLabel(&topValueText); + topValueButton.setImage(&topValueImage); + topValueButton.setIconOver(&topValueImageSelected); + topValueButton.setTrigger(&touchTrigger); + topValueButton.setTrigger(&wpadTouchTrigger); + topValueButton.setSoundClick(buttonClickSound); + topValueButton.clicked.connect(this, &GuiSelectBox::OnTopValueClicked); + + valuesFrame.setState(STATE_HIDDEN); + + DPADButtons.setTrigger(&buttonBTrigger); + DPADButtons.setTrigger(&buttonATrigger); + DPADButtons.setTrigger(&buttonDownTrigger); + DPADButtons.setTrigger(&buttonUpTrigger); + DPADButtons.clicked.connect(this, &GuiSelectBox::OnDPADClick); + DPADButtons.setState(STATE_DISABLE_INPUT); + + append(&DPADButtons); + append(&valuesFrame); + append(&topValueButton); + + showValues = false; + bChanged = true; +} + +void GuiSelectBox::OnValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) +{ + for(u32 i = 0; i < valueButtons.size(); ++i){ + if(valueButtons[i].valueButton == button){ + selected = i; + SelectValue(i); + break; + } + } +} + +void GuiSelectBox::SelectValue(u32 value){ + if(value < valueButtons.size()){ + const wchar_t* w_text = valueButtons[value].valueButtonText->getText(); + std::wstring ws(w_text); + std::string text(ws.begin(), ws.end()); + topValueText.setText(getCaptionWithValue(text).c_str()); + + std::string real_value = buttonToValue[valueButtons[value].valueButton]; + if(real_value.compare(std::string()) == 0) real_value = ""; + + valueChanged(this,real_value); + ShowHideValues(false); + } +} +std::string GuiSelectBox::getCaptionWithValue(std::string value){ + u32 pad = (38 - captionText.size() -2); + if(pad > value.size()) + value.insert(0, pad - value.size(), ' '); + return strfmt("%s: %s",captionText.c_str(),value.c_str()); +} + +void GuiSelectBox::OnTopValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) +{ + ShowHideValues(!showValues); +} + +void GuiSelectBox::ShowHideValues(bool showhide) +{ + showValues = showhide; + bChanged = true; +} + +void GuiSelectBox::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) +{ + if(opened == true){ + if(trigger == &buttonATrigger) + { + //! do not auto launch when wiimote is pointing to screen and presses A + if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer) + { + return; + } + SelectValue(selected); + } + else if(trigger == &buttonBTrigger) + { + if(button == &DPADButtons){ + ShowHideValues(false); + }else{ + } + }else if(trigger == &buttonUpTrigger){ + if(selected > 0 ) selected--; + bSelectedChanged = true; + } + else if(trigger == &buttonDownTrigger){ + selected++; + if(selected >= valueButtons.size()) selected = valueButtons.size() - 1; + bSelectedChanged = true; + } + } +} + +void GuiSelectBox::Init(std::map values, int valueID) +{ + if((u32)valueID >= values.size()){ + valueID = 0; + } + + selected = valueID; + bSelectedChanged = true; + + DeleteValueData(); + + valueButtons.resize(values.size()); + + int i = 0; + f32 imgScale = 1.0f; + std::map::iterator itr; + for(itr = values.begin(); itr != values.end(); itr++) { + if(i == valueID){ + topValueText.setText(getCaptionWithValue(itr->first).c_str()); + } + + valueButtons[i].valueButtonImg = new GuiImage(valueImageData); + + valueButtons[i].valueButtonCheckedImg = new GuiImage(valueSelectedImageData); + valueButtons[i].valueButtonHighlightedImg = new GuiImage(valueHighlightedImageData); + valueButtons[i].valueButton = new GuiButton(valueButtons[i].valueButtonImg->getWidth() * imgScale, valueButtons[i].valueButtonImg->getHeight() * imgScale); + valueButtons[i].valueButtonText = new GuiText(itr->first.c_str(),32,glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); + + valueButtons[i].valueButtonText->setMaxWidth(valueButtons[i].valueButtonImg->getWidth() * imgScale - 20.0f, GuiText::WRAP); + valueButtons[i].valueButtonText->setPosition(0, 0); + + valueButtons[i].valueButtonImg->setScale(imgScale); + valueButtons[i].valueButtonCheckedImg->setScale(imgScale); + + valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonImg); + valueButtons[i].valueButton->setIconOver(valueButtons[i].valueButtonHighlightedImg); + valueButtons[i].valueButton->setTrigger(&touchTrigger); + valueButtons[i].valueButton->setTrigger(&wpadTouchTrigger); + valueButtons[i].valueButton->clicked.connect(this,&GuiSelectBox::OnValueClicked); + valueButtons[i].valueButton->setSoundClick(buttonClickSound); + valueButtons[i].valueButton->setLabel(valueButtons[i].valueButtonText); + + //valueButtons[i].valueButton->setState(STATE_HIDDEN); //Wont get disabled soon enough + + buttonToValue[valueButtons[i].valueButton] = itr->second; + + valueButtons[i].valueButton->setPosition(0, (((valueButtons[i].valueButtonImg->getHeight()*getScale()) * (i))+ (topValueImage.getHeight()-5)*getScale())*-1.0f); + valuesFrame.append(valueButtons[i].valueButton); + + i++; + } + //Collapse the thing! + showValues = false; + bChanged = true; +} + +void GuiSelectBox::DeleteValueData() +{ + for(u32 i = 0; i < valueButtons.size(); ++i) + { + valuesFrame.remove(valueButtons[i].valueButton); + delete valueButtons[i].valueButtonImg; + delete valueButtons[i].valueButtonCheckedImg; + delete valueButtons[i].valueButtonHighlightedImg; + delete valueButtons[i].valueButton; + delete valueButtons[i].valueButtonText; + } + buttonToValue.clear(); + valueButtons.clear(); +} + +/** + * Destructor for the GuiButton class. + */ +GuiSelectBox::~GuiSelectBox() +{ + DeleteValueData(); + bChanged = false; + selected = 0; + showValues = false; + Resources::RemoveSound(buttonClickSound); + Resources::RemoveImageData(topValueImageData); + Resources::RemoveImageData(topValueImageSelectedData); + Resources::RemoveImageData(valueImageData); + Resources::RemoveImageData(valueHighlightedImageData); + Resources::RemoveImageData(valueSelectedImageData); +} + + +void GuiSelectBox::setState(int s, int c) +{ + GuiElement::setState(s, c); +} + +void GuiSelectBox::OnValueCloseEffectFinish(GuiElement *element) +{ + valuesFrame.effectFinished.disconnect(this); +} + +f32 GuiSelectBox::getTopValueHeight() { + return topValueImage.getHeight(); +} + +f32 GuiSelectBox::getTopValueWidth() { + return topValueImage.getWidth(); +} + +void GuiSelectBox::OnValueOpenEffectFinish(GuiElement *element) +{ + valuesFrame.effectFinished.disconnect(this); + opened = true; +} + +void GuiSelectBox::update(GuiController * c){ + if(bChanged){ + showhide(this,showValues); + if(showValues){ + for(u32 i = 0; i < valueButtons.size(); ++i){ //TODO: only set when it really changed + if(i == selected){ + valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonCheckedImg); + }else{ + valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonImg); + } + } + valuesFrame.clearState(STATE_HIDDEN); + DPADButtons.clearState(STATE_DISABLE_INPUT); + valuesFrame.setEffect(EFFECT_FADE, 10, 255); + valuesFrame.effectFinished.connect(this, &GuiSelectBox::OnValueCloseEffectFinish); + }else{ + opened = false; + valuesFrame.setState(STATE_HIDDEN); + DPADButtons.setState(STATE_DISABLE_INPUT); + valuesFrame.setEffect(EFFECT_FADE, -10, 0); + valuesFrame.effectFinished.connect(this, &GuiSelectBox::OnValueOpenEffectFinish); + } + + bChanged = false; + } + if(bSelectedChanged){ + for(u32 i = 0; i < valueButtons.size(); ++i){ + if(i == selected){ + valueButtons[i].valueButton->setState(STATE_SELECTED); + }else{ + valueButtons[i].valueButton->clearState(STATE_SELECTED); + } + } + } + topValueButton.setState(getState()); + GuiFrame::update(c); +} diff --git a/src/gui/GuiSelectBox.h b/src/gui/GuiSelectBox.h new file mode 100644 index 0000000..1e8557e --- /dev/null +++ b/src/gui/GuiSelectBox.h @@ -0,0 +1,104 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#ifndef GUI_SELECTBOX_H_ +#define GUI_SELECTBOX_H_ + +#include "Gui.h" +#include "GuiImage.h" +#include "GuiImageData.h" + +//!A simple CheckBox +class GuiSelectBox : public GuiFrame, public sigslot::has_slots<> + +{ + public: + //!Constructor + //!\param checked Checked + GuiSelectBox(std::string caption,GuiFrame *parent = 0); + //!Destructor + virtual ~GuiSelectBox(); + + sigslot::signal2 valueChanged; + sigslot::signal2 showhide; + void OnTopValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger); + void Init(std::map values, int valueID); + + void setState(int s, int c = -1); + + virtual f32 getTopValueHeight(); + virtual f32 getTopValueWidth(); + + protected: + void DeleteValueData(); + void update(GuiController * c); + + void OnValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger); + + void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger); + void OnValueOpenEffectFinish(GuiElement *element); + void OnValueCloseEffectFinish(GuiElement *element); + void ShowHideValues(bool showhide); + void SelectValue(u32 value); + + u32 selected; + bool bChanged; + bool bSelectedChanged; + bool showValues; + bool opened; + std::string captionText; + GuiFrame valuesFrame; + GuiImageData *topValueImageData; + GuiImage topValueImage; + GuiImageData *topValueImageSelectedData; + GuiImage topValueImageSelected; + + GuiButton topValueButton; + GuiImageData * valueImageData; + GuiImageData * valueSelectedImageData; + GuiImageData * valueHighlightedImageData; + GuiText topValueText; + + GuiTrigger touchTrigger; + GuiTrigger wpadTouchTrigger; + + GuiTrigger buttonATrigger; + GuiTrigger buttonBTrigger; + GuiTrigger buttonLeftTrigger; + GuiTrigger buttonRightTrigger; + GuiTrigger buttonUpTrigger; + GuiTrigger buttonDownTrigger; + + GuiButton DPADButtons; + + GuiSound* buttonClickSound; + + std::string getCaptionWithValue(std::string value); + typedef struct + { + GuiImage *valueButtonImg; + GuiImage *valueButtonCheckedImg; + GuiImage *valueButtonHighlightedImg; + GuiButton *valueButton; + GuiText *valueButtonText; + } SelectBoxValueButton; + + std::map buttonToValue; + std::vector valueButtons; + +}; + +#endif diff --git a/src/gui/GuiSound.cpp b/src/gui/GuiSound.cpp new file mode 100644 index 0000000..502a8a2 --- /dev/null +++ b/src/gui/GuiSound.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "GuiSound.h" +#include "sounds/SoundHandler.hpp" +#include "dynamic_libs/os_functions.h" + +GuiSound::GuiSound(const char * filepath) +{ + voice = -1; + Load(filepath); +} + +GuiSound::GuiSound(const u8 * snd, s32 length) +{ + voice = -1; + Load(snd, length); +} + +GuiSound::~GuiSound() +{ + if(voice >= 0) + { + SoundHandler::instance()->RemoveDecoder(voice); + } +} + + +bool GuiSound::Load(const char * filepath) +{ + if(voice >= 0) + { + SoundHandler::instance()->RemoveDecoder(voice); + voice = -1; + } + + //! find next free decoder + for(int i = 0; i < MAX_DECODERS; i++) + { + SoundDecoder * decoder = SoundHandler::instance()->getDecoder(i); + if(decoder == NULL) + { + SoundHandler::instance()->AddDecoder(i, filepath); + decoder = SoundHandler::instance()->getDecoder(i); + if(decoder) + { + voice = i; + SoundHandler::instance()->ThreadSignal(); + } + break; + } + } + + if(voice < 0) + return false; + + return true; +} + +bool GuiSound::Load(const u8 * snd, s32 len) +{ + if(voice >= 0) + { + SoundHandler::instance()->RemoveDecoder(voice); + voice = -1; + } + + if(!snd) + return false; + + //! find next free decoder + for(int i = 0; i < MAX_DECODERS; i++) + { + SoundDecoder * decoder = SoundHandler::instance()->getDecoder(i); + if(decoder == NULL) + { + SoundHandler::instance()->AddDecoder(i, snd, len); + decoder = SoundHandler::instance()->getDecoder(i); + if(decoder) + { + voice = i; + SoundHandler::instance()->ThreadSignal(); + } + break; + } + } + + if(voice < 0) + return false; + + return true; +} + +void GuiSound::Play() +{ + Stop(); + + Voice * v = SoundHandler::instance()->getVoice(voice); + if(v) + v->setState(Voice::STATE_START); + + +} + +void GuiSound::Stop() +{ + Voice * v = SoundHandler::instance()->getVoice(voice); + if(v) + { + if((v->getState() != Voice::STATE_STOP) && (v->getState() != Voice::STATE_STOPPED)) + v->setState(Voice::STATE_STOP); + + while(v->getState() != Voice::STATE_STOPPED) + usleep(1000); + } + + SoundDecoder * decoder = SoundHandler::instance()->getDecoder(voice); + if(decoder) + { + decoder->Lock(); + decoder->Rewind(); + decoder->ClearBuffer(); + SoundHandler::instance()->ThreadSignal(); + decoder->Unlock(); + } +} + +void GuiSound::Pause() +{ + if(!IsPlaying()) + return; + + Voice * v = SoundHandler::instance()->getVoice(voice); + if(v) + v->setState(Voice::STATE_STOP); +} + +void GuiSound::Resume() +{ + if(IsPlaying()) + return; + + Voice * v = SoundHandler::instance()->getVoice(voice); + if(v) + v->setState(Voice::STATE_START); +} + +bool GuiSound::IsPlaying() +{ + Voice * v = SoundHandler::instance()->getVoice(voice); + if(v) + return v->getState() == Voice::STATE_PLAYING; + + return false; + +} + +void GuiSound::SetVolume(u32 vol) +{ + if(vol > 100) + vol = 100; + + u32 volumeConv = ( (0x8000 * vol) / 100 ) << 16; + + Voice * v = SoundHandler::instance()->getVoice(voice); + if(v) + v->setVolume(volumeConv); +} + +void GuiSound::SetLoop(bool l) +{ + SoundDecoder * decoder = SoundHandler::instance()->getDecoder(voice); + if(decoder) + decoder->SetLoop(l); +} + +void GuiSound::Rewind() +{ + Stop(); +} diff --git a/src/gui/GuiSound.h b/src/gui/GuiSound.h new file mode 100644 index 0000000..bb72a3b --- /dev/null +++ b/src/gui/GuiSound.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef GUI_SOUND_H_ +#define GUI_SOUND_H_ + +#include +#include "system/AsyncDeleter.h" + +//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc +class GuiSound : public AsyncDeleter::Element +{ + public: + //!Constructor + //!\param sound Pointer to the sound data + //!\param filesize Length of sound data + GuiSound(const char * filepath); + GuiSound(const u8 * sound, int length); + //!Destructor + virtual ~GuiSound(); + //!Load a file and replace the old one + bool Load(const char * filepath); + //!Load a file and replace the old one + bool Load(const u8 * snd, s32 len); + //!Start sound playback + void Play(); + //!Stop sound playback + void Stop(); + //!Pause sound playback + void Pause(); + //!Resume sound playback + void Resume(); + //!Checks if the sound is currently playing + //!\return true if sound is playing, false otherwise + bool IsPlaying(); + //!Rewind the music + void Rewind(); + //!Set sound volume + //!\param v Sound volume (0-100) + void SetVolume(u32 v); + //!\param l Loop (true to loop) + void SetLoop(bool l); + protected: + s32 voice; //!< Currently assigned ASND voice channel +}; + +#endif diff --git a/src/gui/GuiSwitch.cpp b/src/gui/GuiSwitch.cpp new file mode 100644 index 0000000..206a456 --- /dev/null +++ b/src/gui/GuiSwitch.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#include "GuiSwitch.h" +#include "GuiImage.h" +#include "GuiImageData.h" +/** + * Constructor for the GuiSwitch class. + */ + +GuiSwitch::GuiSwitch(bool checked,f32 switchscale) + : GuiToggle(checked,90*switchscale,38*switchscale) + ,switchbase_imgdata(Resources::GetImageData("switchIconBase.png")) + ,switchbase_img(switchbase_imgdata) + ,switchbase_highlighted_imgdata(Resources::GetImageData("switchIconBaseHighlighted.png")) + ,switchbase_highlighted_img(switchbase_highlighted_imgdata) + ,switchOn_imgdata(Resources::GetImageData("switchIconOn.png")) + ,switchOn_img(switchOn_imgdata) + ,switchOff_imgdata(Resources::GetImageData("switchIconOff.png")) + ,switchOff_img(switchOff_imgdata) +{ + f32 scale = 0.0; + if(switchbase_img.getHeight() > switchbase_img.getWidth()){ + scale = height*switchscale/switchbase_img.getHeight(); + }else{ + scale = width/switchbase_img.getWidth(); + } + + switchbase_img.setScale(scale); + switchbase_highlighted_img.setScale(scale); + switchOn_img.setScale(scale); + switchOff_img.setScale(scale); + + switchOn_img.setParent(this); + switchOn_img.setPosition((width/4.0),0); + switchOff_img.setParent(this); + switchOff_img.setPosition(-((width/4.0)),0); + setImage(&switchbase_img); + setIconOver(&switchbase_highlighted_img); +} +/** + * Destructor for the GuiButton class. + */ +GuiSwitch::~GuiSwitch() +{ + Resources::RemoveImageData(switchbase_imgdata); + Resources::RemoveImageData(switchbase_highlighted_imgdata); + Resources::RemoveImageData(switchOn_imgdata); + Resources::RemoveImageData(switchOff_imgdata); +} + +void GuiSwitch::draw(CVideo *v){ + GuiToggle::draw(v); + if(getValue()){ + switchOn_img.draw(v); + }else{ + switchOff_img.draw(v); + } +} diff --git a/src/gui/GuiSwitch.h b/src/gui/GuiSwitch.h new file mode 100644 index 0000000..4988d2d --- /dev/null +++ b/src/gui/GuiSwitch.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#ifndef GUI_SWTICH_H_ +#define GUI_SWTICH_H_ + +#include "GuiToggle.h" +#include "GuiImage.h" +#include "GuiImageData.h" + +//!A simple switch +class GuiSwitch : public GuiToggle +{ + public: + //!Constructor + //!\param checked Checked + GuiSwitch(bool checked,f32 switchscale = 1.0f); + //!Destructor + virtual ~GuiSwitch(); + + protected: + + GuiImageData * switchbase_imgdata; + GuiImage switchbase_img; + + GuiImageData * switchbase_highlighted_imgdata; + GuiImage switchbase_highlighted_img; + + GuiImageData * switchOn_imgdata; + GuiImage switchOn_img; + + GuiImageData * switchOff_imgdata; + GuiImage switchOff_img; + + void draw(CVideo * v); +}; + +#endif diff --git a/src/gui/GuiText.cpp b/src/gui/GuiText.cpp new file mode 100644 index 0000000..ab54e42 --- /dev/null +++ b/src/gui/GuiText.cpp @@ -0,0 +1,615 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "GuiText.h" +#include "FreeTypeGX.h" +#include "video/CVideo.h" + +FreeTypeGX * GuiText::presentFont = NULL; +int GuiText::presetSize = 28; +int GuiText::presetInternalRenderingScale = 2.0f; //Lets render the font at the doubled size. This make it even smoother! +int GuiText::presetMaxWidth = 0xFFFF; +int GuiText::presetAlignment = ALIGN_CENTER | ALIGN_MIDDLE; +GX2ColorF32 GuiText::presetColor = (GX2ColorF32){ 1.0f, 1.0f, 1.0f, 1.0f }; + +#define TEXT_SCROLL_DELAY 6 +#define TEXT_SCROLL_INITIAL_DELAY 10 +#define MAX_LINES_TO_DRAW 10 + +/** + * Constructor for the GuiText class. + */ + +GuiText::GuiText() +{ + text = NULL; + size = presetSize; + currentSize = size; + color = glm::vec4(presetColor.r, presetColor.g, presetColor.b, presetColor.a); + alpha = presetColor.a; + alignment = presetAlignment; + maxWidth = presetMaxWidth; + wrapMode = 0; + textWidth = 0; + font = presentFont; + linestodraw = MAX_LINES_TO_DRAW; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + textScrollDelay = TEXT_SCROLL_DELAY; + defaultBlur = 4.0f; + blurGlowIntensity = 0.0f; + blurAlpha = 0.0f; + blurGlowColor = glm::vec4(0.0f); + internalRenderingScale = presetInternalRenderingScale; +} + +GuiText::GuiText(const char * t, int s, const glm::vec4 & c) +{ + text = NULL; + size = s; + currentSize = size; + color = c; + alpha = c[3]; + alignment = ALIGN_CENTER | ALIGN_MIDDLE; + maxWidth = presetMaxWidth; + wrapMode = 0; + textWidth = 0; + font = presentFont; + linestodraw = MAX_LINES_TO_DRAW; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + textScrollDelay = TEXT_SCROLL_DELAY; + defaultBlur = 4.0f; + blurGlowIntensity = 0.0f; + blurAlpha = 0.0f; + blurGlowColor = glm::vec4(0.0f); + internalRenderingScale = presetInternalRenderingScale; + + if(t) + { + text = FreeTypeGX::charToWideChar(t); + if(!text) + return; + + textWidth = font->getWidth(text, currentSize); + } +} + +GuiText::GuiText(const wchar_t * t, int s, const glm::vec4 & c) +{ + text = NULL; + size = s; + currentSize = size; + color = c; + alpha = c[3]; + alignment = ALIGN_CENTER | ALIGN_MIDDLE; + maxWidth = presetMaxWidth; + wrapMode = 0; + textWidth = 0; + font = presentFont; + linestodraw = MAX_LINES_TO_DRAW; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + textScrollDelay = TEXT_SCROLL_DELAY; + defaultBlur = 4.0f; + blurGlowIntensity = 0.0f; + blurAlpha = 0.0f; + blurGlowColor = glm::vec4(0.0f); + internalRenderingScale = presetInternalRenderingScale; + + if(t) + { + text = new (std::nothrow) wchar_t[wcslen(t)+1]; + if(!text) + return; + + wcscpy(text, t); + + textWidth = font->getWidth(text, currentSize); + } +} + +/** + * Constructor for the GuiText class, uses presets + */ +GuiText::GuiText(const char * t) +{ + text = NULL; + size = presetSize; + currentSize = size; + color = glm::vec4(presetColor.r, presetColor.g, presetColor.b, presetColor.a); + alpha = presetColor.a; + alignment = presetAlignment; + maxWidth = presetMaxWidth; + wrapMode = 0; + textWidth = 0; + font = presentFont; + linestodraw = MAX_LINES_TO_DRAW; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + textScrollDelay = TEXT_SCROLL_DELAY; + defaultBlur = 4.0f; + blurGlowIntensity = 0.0f; + blurAlpha = 0.0f; + blurGlowColor = glm::vec4(0.0f); + internalRenderingScale = presetInternalRenderingScale; + + if(t) + { + text = FreeTypeGX::charToWideChar(t); + if(!text) + return; + + textWidth = font->getWidth(text, currentSize); + } +} + + +/** + * Destructor for the GuiText class. + */ +GuiText::~GuiText() +{ + if(text) + delete [] text; + text = NULL; + + clearDynamicText(); +} + +void GuiText::setText(const char * t) +{ + if(text) + delete [] text; + text = NULL; + + clearDynamicText(); + + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + + if(t) + { + text = FreeTypeGX::charToWideChar(t); + if(!text) + return; + + textWidth = font->getWidth(text, currentSize); + } +} + +void GuiText::setTextf(const char *format, ...) +{ + if(!format) + { + setText((char *) NULL); + return; + } + + int max_len = strlen(format) + 8192; + char *tmp = new char[max_len]; + va_list va; + va_start(va, format); + if((vsnprintf(tmp, max_len, format, va) >= 0) && tmp) + { + setText(tmp); + } + va_end(va); + + if(tmp) + delete [] tmp; +} + + +void GuiText::setText(const wchar_t * t) +{ + if(text) + delete [] text; + text = NULL; + + clearDynamicText(); + + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + + if(t) + { + text = new (std::nothrow) wchar_t[wcslen(t)+1]; + if(!text) + return; + + wcscpy(text, t); + + textWidth = font->getWidth(text, currentSize); + } +} + +void GuiText::clearDynamicText() +{ + for(u32 i = 0; i < textDyn.size(); i++) + { + if(textDyn[i]) + delete [] textDyn[i]; + } + textDyn.clear(); + textDynWidth.clear(); +} + +void GuiText::setPresets(int sz, const glm::vec4 & c, int w, int a) +{ + presetSize = sz; + presetColor = (GX2ColorF32) { (f32)c.r / 255.0f, (f32)c.g / 255.0f, (f32)c.b / 255.0f, (f32)c.a / 255.0f }; + presetMaxWidth = w; + presetAlignment = a; +} + +void GuiText::setPresetFont(FreeTypeGX *f) +{ + presentFont = f; +} + +void GuiText::setFontSize(int s) +{ + size = s; +} + +void GuiText::setMaxWidth(int width, int w) +{ + maxWidth = width; + wrapMode = w; + + if(w == SCROLL_HORIZONTAL) + { + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + textScrollDelay = TEXT_SCROLL_DELAY; + } + + clearDynamicText(); +} + +void GuiText::setColor(const glm::vec4 & c) +{ + color = c; + alpha = c[3]; +} + +void GuiText::setBlurGlowColor(float blur, const glm::vec4 & c) +{ + blurGlowColor = c; + blurGlowIntensity = blur; + blurAlpha = c[3]; +} + +int GuiText::getTextWidth(int ind) +{ + if(ind < 0 || ind >= (int) textDyn.size()) + return this->getTextWidth(); + + return font->getWidth(textDyn[ind], currentSize); +} + +const wchar_t * GuiText::getDynText(int ind) +{ + if(ind < 0 || ind >= (int) textDyn.size()) + return text; + + return textDyn[ind]; +} + +/** + * Change font + */ +bool GuiText::setFont(FreeTypeGX *f) +{ + if(!f) + return false; + + font = f; + textWidth = font->getWidth(text, currentSize); + return true; +} + +std::string GuiText::toUTF8(void) const +{ + if(!text) + return std::string(); + + char *pUtf8 = FreeTypeGX::wideCharToUTF8(text); + if(!pUtf8) + return std::string(); + + std::string strOutput(pUtf8); + + delete [] pUtf8; + + return strOutput; +} + +void GuiText::makeDottedText() +{ + int pos = textDyn.size(); + textDyn.resize(pos + 1); + + int i = 0, currentWidth = 0; + textDyn[pos] = new (std::nothrow) wchar_t[maxWidth]; + if(!textDyn[pos]) { + textDyn.resize(pos); + return; + } + + while (text[i]) + { + currentWidth += font->getCharWidth(text[i], currentSize, i > 0 ? text[i - 1] : 0); + if (currentWidth >= maxWidth && i > 2) + { + textDyn[pos][i - 2] = '.'; + textDyn[pos][i - 1] = '.'; + textDyn[pos][i] = '.'; + i++; + break; + } + + textDyn[pos][i] = text[i]; + + i++; + } + textDyn[pos][i] = 0; +} + +void GuiText::scrollText(u32 frameCount) +{ + if (textDyn.size() == 0) + { + int pos = textDyn.size(); + int i = 0, currentWidth = 0; + textDyn.resize(pos + 1); + + textDyn[pos] = new (std::nothrow) wchar_t[maxWidth]; + if(!textDyn[pos]) { + textDyn.resize(pos); + return; + } + + while (text[i] && currentWidth < maxWidth) + { + textDyn[pos][i] = text[i]; + + currentWidth += font->getCharWidth(text[i], currentSize, i > 0 ? text[i - 1] : 0); + + ++i; + } + textDyn[pos][i] = 0; + + return; + } + + if (frameCount % textScrollDelay != 0) + { + return; + } + + if (textScrollInitialDelay) + { + --textScrollInitialDelay; + return; + } + + int stringlen = wcslen(text); + + ++textScrollPos; + if (textScrollPos > stringlen) + { + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + } + + int ch = textScrollPos; + int pos = textDyn.size() - 1; + + if (!textDyn[pos]) + textDyn[pos] = new (std::nothrow) wchar_t[maxWidth]; + + if(!textDyn[pos]) { + textDyn.resize(pos); + return; + } + + int i = 0, currentWidth = 0; + + while (currentWidth < maxWidth) + { + if (ch > stringlen - 1) + { + textDyn[pos][i++] = ' '; + currentWidth += font->getCharWidth(L' ', currentSize, ch > 0 ? text[ch - 1] : 0); + textDyn[pos][i++] = ' '; + currentWidth += font->getCharWidth(L' ', currentSize, L' '); + textDyn[pos][i++] = ' '; + currentWidth += font->getCharWidth(L' ', currentSize, L' '); + ch = 0; + + if(currentWidth >= maxWidth) + break; + } + + textDyn[pos][i] = text[ch]; + currentWidth += font->getCharWidth(text[ch], currentSize, ch > 0 ? text[ch - 1] : 0); + ++ch; + ++i; + } + textDyn[pos][i] = 0; +} + +void GuiText::wrapText() +{ + if (textDyn.size() > 0) return; + + int i = 0; + int ch = 0; + int linenum = 0; + int lastSpace = -1; + int lastSpaceIndex = -1; + int currentWidth = 0; + + while (text[ch] && linenum < linestodraw) + { + if (linenum >= (int) textDyn.size()) + { + textDyn.resize(linenum + 1); + textDyn[linenum] = new (std::nothrow) wchar_t[maxWidth]; + if(!textDyn[linenum]) { + textDyn.resize(linenum); + break; + } + } + + textDyn[linenum][i] = text[ch]; + textDyn[linenum][i + 1] = 0; + + currentWidth += font->getCharWidth(text[ch], currentSize, ch > 0 ? text[ch - 1] : 0x0000); + + if (currentWidth >= maxWidth || (text[ch] == '\n')) + { + if(text[ch] == '\n') + { + lastSpace = -1; + lastSpaceIndex = -1; + } + else if (lastSpace >= 0) + { + textDyn[linenum][lastSpaceIndex] = 0; // discard space, and everything after + ch = lastSpace; // go backwards to the last space + lastSpace = -1; // we have used this space + lastSpaceIndex = -1; + } + + if (linenum + 1 == linestodraw && text[ch + 1] != 0x0000) + { + if(i < 2) + i = 2; + + textDyn[linenum][i - 2] = '.'; + textDyn[linenum][i - 1] = '.'; + textDyn[linenum][i] = '.'; + textDyn[linenum][i + 1] = 0; + } + + currentWidth = 0; + ++linenum; + i = -1; + } + if (text[ch] == ' ' && i >= 0) + { + lastSpace = ch; + lastSpaceIndex = i; + } + ++ch; + ++i; + } +} + +/** + * Draw the text on screen + */ +void GuiText::draw(CVideo *pVideo) +{ + if(!text) + return; + + if(!isVisible()) + return; + + color[3] = getAlpha(); + blurGlowColor[3] = blurAlpha * getAlpha(); + + float finalRenderingScale = 2.0f * internalRenderingScale; + + int newSize = size * getScale() * finalRenderingScale; + int normal_size = size * getScale(); + + if(newSize != currentSize) + { + currentSize = normal_size; + + if(text) + textWidth = font->getWidth(text, normal_size); + } + + f32 x_pos = getCenterX() * finalRenderingScale; + f32 y_pos = getCenterY() * finalRenderingScale; + + if(maxWidth > 0 && maxWidth <= textWidth) + { + if(wrapMode == DOTTED) // text dotted + { + if(textDyn.size() == 0) + makeDottedText(); + + if(textDynWidth.size() != textDyn.size()) + { + textDynWidth.resize(textDyn.size()); + + for(u32 i = 0; i < textDynWidth.size(); i++) + textDynWidth[i] = font->getWidth(textDyn[i], newSize); + } + + + if(textDyn.size() > 0) + font->drawText(pVideo, x_pos, y_pos, getDepth(), textDyn[textDyn.size()-1], newSize, color, alignment, textDynWidth[textDyn.size()-1], defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale); + } + + else if(wrapMode == SCROLL_HORIZONTAL) + { + scrollText(pVideo->getFrameCount()); + + if(textDyn.size() > 0) + font->drawText(pVideo, x_pos, y_pos, getDepth(), textDyn[textDyn.size()-1], newSize, color, alignment, maxWidth*finalRenderingScale, defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale); + + } + else if(wrapMode == WRAP) + { + int lineheight = newSize + 6; + int yoffset = 0; + int voffset = 0; + + if(textDyn.size() == 0) + wrapText(); + + if(textDynWidth.size() != textDyn.size()) + { + textDynWidth.resize(textDyn.size()); + + for(u32 i = 0; i < textDynWidth.size(); i++) + textDynWidth[i] = font->getWidth(textDyn[i], newSize); + } + + if(alignment & ALIGN_MIDDLE) + voffset = (lineheight * (textDyn.size()-1)) >> 1; + + for(u32 i = 0; i < textDyn.size(); i++) + { + font->drawText(pVideo, x_pos, y_pos + voffset + yoffset, getDepth(), textDyn[i], newSize, color, alignment, textDynWidth[i], defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale); + yoffset -= lineheight; + } + } + } + else + { + uint16_t newtextWidth = font->getWidth(text, newSize); + font->drawText(pVideo, x_pos, y_pos, getDepth(), text, newSize, color, alignment, newtextWidth, defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale); + } +} diff --git a/src/gui/GuiText.h b/src/gui/GuiText.h new file mode 100644 index 0000000..5fb8acd --- /dev/null +++ b/src/gui/GuiText.h @@ -0,0 +1,141 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef GUI_TEXT_H_ +#define GUI_TEXT_H_ + +#include "GuiElement.h" +//!Forward declaration +class FreeTypeGX; + +//!Display, manage, and manipulate text in the GUI +class GuiText : public GuiElement +{ +public: + //!Constructor + GuiText(); + //!\param t Text + //!\param s Font size + //!\param c Font color + GuiText(const char * t, int s, const glm::vec4 & c); + //!\overload + //!\param t Text + //!\param s Font size + //!\param c Font color + GuiText(const wchar_t * t, int s, const glm::vec4 & c); + //!\overload + //!\Assumes SetPresets() has been called to setup preferred text attributes + //!\param t Text + GuiText(const char * t); + //!Destructor + virtual ~GuiText(); + //!Sets the text of the GuiText element + //!\param t Text + virtual void setText(const char * t); + virtual void setText(const wchar_t * t); + virtual void setTextf(const char *format, ...) __attribute__((format(printf,2,3))); + //!Sets up preset values to be used by GuiText(t) + //!Useful when printing multiple text elements, all with the same attributes set + //!\param sz Font size + //!\param c Font color + //!\param w Maximum width of texture image (for text wrapping) + //!\param wrap Wrapmode when w>0 + //!\param a Text alignment + static void setPresets(int sz, const glm::vec4 & c, int w, int a); + static void setPresetFont(FreeTypeGX *font); + //!Sets the font size + //!\param s Font size + void setFontSize(int s); + //!Sets the maximum width of the drawn texture image + //!If the text exceeds this, it is wrapped to the next line + //!\param w Maximum width + //!\param m WrapMode + void setMaxWidth(int w = 0, int m = WRAP); + //!Sets the font color + //!\param c Font color + void setColor(const glm::vec4 & c); + + void setBlurGlowColor(float blurIntensity, const glm::vec4 & c); + + void setTextBlur(float blur) { defaultBlur = blur; } + //!Get the original text as char + virtual const wchar_t * getText() const { return text; } + virtual std::string toUTF8(void) const; + //!Get the Horizontal Size of Text + int getTextWidth() { return textWidth; } + int getTextWidth(int ind); + //!Get the max textwidth + int getTextMaxWidth() { return maxWidth; } + //!Get fontsize + int getFontSize() { return size; }; + //!Set max lines to draw + void setLinesToDraw(int l) { linestodraw = l; } + //!Get current Textline (for position calculation) + const wchar_t * getDynText(int ind = 0); + virtual const wchar_t * getTextLine(int ind) { return getDynText(ind); }; + //!Change the font + bool setFont(FreeTypeGX *font); + //! virtual function used in child classes + virtual int getStartWidth() { return 0; }; + //!Constantly called to draw the text + void draw(CVideo *pVideo); + //! text enums + enum + { + WRAP, + DOTTED, + SCROLL_HORIZONTAL, + SCROLL_NONE + }; +protected: + static FreeTypeGX * presentFont; + static int presetSize; + static int presetMaxWidth; + static int presetInternalRenderingScale; + static int presetAlignment; + static GX2ColorF32 presetColor; + + //!Clear the dynamic text + void clearDynamicText(); + //!Create a dynamic dotted text if the text is too long + void makeDottedText(); + //!Scroll the text once + void scrollText(u32 frameCount); + //!Wrap the text to several lines + void wrapText(); + + wchar_t * text; + std::vector textDyn; + std::vector textDynWidth; + int wrapMode; //!< Wrapping toggle + int textScrollPos; //!< Current starting index of text string for scrolling + int textScrollInitialDelay; //!< Delay to wait before starting to scroll + int textScrollDelay; //!< Scrolling speed + int size; //!< Font size + int maxWidth; //!< Maximum width of the generated text object (for text wrapping) + FreeTypeGX *font; + int textWidth; + int currentSize; + int linestodraw; + glm::vec4 color; + float defaultBlur; + float blurGlowIntensity; + float blurAlpha; + glm::vec4 blurGlowColor; + float internalRenderingScale; +}; + +#endif diff --git a/src/gui/GuiToggle.cpp b/src/gui/GuiToggle.cpp new file mode 100644 index 0000000..03d5b37 --- /dev/null +++ b/src/gui/GuiToggle.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#include "GuiToggle.h" +/** + * Constructor for the GuiToggle class. + */ + +GuiToggle::GuiToggle(bool checked,f32 width,f32 height) + : GuiButton(width,height) +{ + bChanged = false; + selected = false; + clicked.connect(this,&GuiToggle::OnToggleClick); +} + +/** + * Destructor for the GuiButton class. + */ +GuiToggle::~GuiToggle() +{ + bChanged = false; + selected = false; +} + +void GuiToggle::OnToggleClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger){ + if(!isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT)){ + log_print("Clicked on Toggle: "); + if(selected){ + log_print("Uncheck\n"); + setUnchecked(); + }else{ + log_print("Check\n"); + setChecked(); + } + } +} + +void GuiToggle::update(GuiController * c){ + GuiButton::update(c); +} + diff --git a/src/gui/GuiToggle.h b/src/gui/GuiToggle.h new file mode 100644 index 0000000..c6dc213 --- /dev/null +++ b/src/gui/GuiToggle.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * Copyright (C) 2016 Maschell + * + * 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 . + ****************************************************************************/ +#ifndef GUI_TOGGLE_H_ +#define GUI_TOGGLE_H_ + +#include "GuiButton.h" +#include "GuiFrame.h" + +//!A simple CheckBox +class GuiToggle : public GuiButton, public sigslot::has_slots<> +{ + public: + //!Constructor + //!\param checked Checked + GuiToggle(bool checked,f32 width,f32 height); + //!Destructor + virtual ~GuiToggle(); + void setValue(bool checked){ + if(selected != checked){ + selected = checked; + bChanged=true; + valueChanged(this,selected); + } + } + void setChecked(){ + setValue(true); + + } + void setUnchecked(){ + setValue(false); + } + bool getValue(){ + return selected; + } + sigslot::signal2 valueChanged; + void OnToggleClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger); + protected: + + bool selected; + bool bChanged; + + void update(GuiController * c); +}; + +#endif diff --git a/src/gui/GuiTrigger.cpp b/src/gui/GuiTrigger.cpp new file mode 100644 index 0000000..74e9d05 --- /dev/null +++ b/src/gui/GuiTrigger.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "GuiElement.h" +#include "GuiController.h" +#include "GuiTrigger.h" + +/** + * Constructor for the GuiTrigger class. + */ +GuiTrigger::GuiTrigger() + : chan(CHANNEL_ALL) + , btns(BUTTON_NONE) + , bClickEverywhere(false) + , bHoldEverywhere(false) + , bSelectionClickEverywhere(false) + , bLastTouched(false) +{ +} + +GuiTrigger::GuiTrigger(u32 ch, u32 btn, bool clickEverywhere, bool holdEverywhere, bool selectionClickEverywhere) + : chan(ch) + , btns(btn) + , bClickEverywhere(clickEverywhere) + , bHoldEverywhere(holdEverywhere) + , bSelectionClickEverywhere(selectionClickEverywhere) + , bLastTouched(false) +{ +} + +/** + * Destructor for the GuiTrigger class. + */ +GuiTrigger::~GuiTrigger() +{ +} + +/** + * Sets a simple trigger. Requires: + * - Element is selected + * - Trigger button is pressed + */ +void GuiTrigger::setTrigger(u32 ch, u32 btn) +{ + chan = ch; + btns = btn; +} + +bool GuiTrigger::left(const GuiController *controller) const +{ + if((controller->chan & chan) == 0) { + return false; + } + if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_LEFT | STICK_L_LEFT)) + { + return true; + } + return false; +} + +bool GuiTrigger::right(const GuiController *controller) const +{ + if((controller->chan & chan) == 0) { + return false; + } + if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_RIGHT | STICK_L_RIGHT)) + { + return true; + } + return false; +} + +bool GuiTrigger::up(const GuiController *controller) const +{ + if((controller->chan & chan) == 0) { + return false; + } + if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_UP | STICK_L_UP)) + { + return true; + } + return false; +} + +bool GuiTrigger::down(const GuiController *controller) const +{ + if((controller->chan & chan) == 0) { + return false; + } + if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_DOWN | STICK_L_DOWN)) + { + return true; + } + return false; +} + +int GuiTrigger::clicked(const GuiController *controller) const +{ + if((controller->chan & chan) == 0) { + return CLICKED_NONE; + } + + int bResult = CLICKED_NONE; + + if(controller->data.touched && controller->data.validPointer && (btns & VPAD_TOUCH) && !controller->lastData.touched) + { + bResult = CLICKED_TOUCH; + } + + if(controller->data.buttons_d & btns) + { + bResult = CLICKED_BUTTON; + } + return bResult; +} + +bool GuiTrigger::held(const GuiController *controller) const +{ + if((controller->chan & chan) == 0) { + return false; + } + + bool bResult = false; + + if(controller->data.touched && (btns & VPAD_TOUCH) && controller->data.validPointer && controller->lastData.touched && controller->lastData.validPointer) + { + bResult = true; + } + + if(controller->data.buttons_h & btns) + { + bResult = true; + } + + return bResult; +} + +bool GuiTrigger::released(const GuiController *controller) const +{ + if((controller->chan & chan) == 0) { + return false; + } + + if(clicked(controller) || held(controller)) + return false; + + bool bResult = false; + + if(!controller->data.touched && (btns & VPAD_TOUCH) && controller->lastData.touched && controller->lastData.validPointer) + { + bResult = true; + } + + if(controller->data.buttons_r & btns) + { + bResult = true; + } + + return bResult; +} + diff --git a/src/gui/GuiTrigger.h b/src/gui/GuiTrigger.h new file mode 100644 index 0000000..ea84b67 --- /dev/null +++ b/src/gui/GuiTrigger.h @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef GUI_TRIGGER_H_ +#define GUI_TRIGGER_H_ + +#include "dynamic_libs/os_functions.h" + + +//!Menu input trigger management. Determine if action is neccessary based on input data by comparing controller input data to a specific trigger element. +class GuiTrigger +{ +public: + enum eClicked{ + CLICKED_NONE = 0x00, + CLICKED_TOUCH = 0x01, + CLICKED_BUTTON = 0x02, + }; + enum eChannels { + CHANNEL_1 = 0x01, + CHANNEL_2 = 0x02, + CHANNEL_3 = 0x04, + CHANNEL_4 = 0x08, + CHANNEL_5 = 0x10, + CHANNEL_ALL = 0xFF + }; + enum eButtons { + BUTTON_NONE = 0x0000, + VPAD_TOUCH = 0x80000000, + BUTTON_Z = 0x20000, + BUTTON_C = 0x10000, + BUTTON_A = 0x8000, + BUTTON_B = 0x4000, + BUTTON_X = 0x2000, + BUTTON_Y = 0x1000, + BUTTON_1 = BUTTON_Y, + BUTTON_2 = BUTTON_X, + BUTTON_LEFT = 0x0800, + BUTTON_RIGHT = 0x0400, + BUTTON_UP = 0x0200, + BUTTON_DOWN = 0x0100, + BUTTON_ZL = 0x0080, + BUTTON_ZR = 0x0040, + BUTTON_L = 0x0020, + BUTTON_R = 0x0010, + BUTTON_PLUS = 0x0008, + BUTTON_MINUS = 0x0004, + BUTTON_HOME = 0x0002, + BUTTON_SYNC = 0x0001, + STICK_R_LEFT = 0x04000000, + STICK_R_RIGHT = 0x02000000, + STICK_R_UP = 0x01000000, + STICK_R_DOWN = 0x00800000, + STICK_L_LEFT = 0x40000000, + STICK_L_RIGHT = 0x20000000, + STICK_L_UP = 0x10000000, + STICK_L_DOWN = 0x08000000 + }; + + //!Constructor + GuiTrigger(); + //!Constructor + GuiTrigger(u32 ch, u32 btns, bool clickEverywhere = false, bool holdEverywhere = false, bool selectionClickEverywhere = false); + //!Destructor + virtual ~GuiTrigger(); + //!Sets a simple trigger. Requires: element is selected, and trigger button is pressed + void setTrigger(u32 ch, u32 btns); + + void setClickEverywhere(bool b) { bClickEverywhere = b; } + void setHoldOnly(bool b) { bHoldEverywhere = b; } + void setSelectionClickEverywhere(bool b) { bSelectionClickEverywhere = b; } + + bool isClickEverywhere() const { return bClickEverywhere; } + bool isHoldEverywhere() const { return bHoldEverywhere; } + bool isSelectionClickEverywhere() const { return bSelectionClickEverywhere; } + + bool left(const GuiController *controller) const; + bool right(const GuiController *controller) const; + bool up(const GuiController *controller) const; + bool down(const GuiController *controller) const; + int clicked(const GuiController *controller) const; + bool held(const GuiController *controller) const; + bool released(const GuiController *controller) const; +private: + u32 chan; + u32 btns; + bool bClickEverywhere; + bool bHoldEverywhere; + bool bSelectionClickEverywhere; + bool bLastTouched; +}; + +#endif diff --git a/src/gui/Scrollbar.cpp b/src/gui/Scrollbar.cpp new file mode 100644 index 0000000..84979b2 --- /dev/null +++ b/src/gui/Scrollbar.cpp @@ -0,0 +1,277 @@ +/*************************************************************************** + * Copyright (C) 2011 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "Scrollbar.h" +#include "resources/Resources.h" + +Scrollbar::Scrollbar(int h) + : touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH) + , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A) +{ + SelItem = 0; + SelInd = 0; + PageSize = 0; + EntrieCount = 0; + ScrollSpeed = 15; + ScrollState = 0; + + listChanged.connect(this, &Scrollbar::setScrollboxPosition); + + btnSoundClick = Resources::GetSound("button_click.mp3"); + scrollbarLine = Resources::GetImageData("scrollbarLine.png"); + arrowDown = Resources::GetImageData("scrollbarArrowDown.png"); + arrowUp = Resources::GetImageData("scrollbarArrowUp.png"); + scrollbarBox = Resources::GetImageData("scrollbarButton.png"); + + height = h; + width = scrollbarBox->getWidth(); + + MaxHeight = height * 0.5f - (scrollbarBox ? (scrollbarBox->getHeight() * 0.5f) : 0) - (arrowUp ? arrowUp->getHeight() : 0); + MinHeight = -height * 0.5f + (scrollbarBox ? (scrollbarBox->getHeight() * 0.5f) : 0) + (arrowDown ? arrowDown->getHeight() : 0); + + scrollbarLineImg = new GuiImage(scrollbarLine); + scrollbarLineImg->setParent(this); + scrollbarLineImg->setAlignment(ALIGN_CENTER | ALIGN_MIDDLE); + scrollbarLineImg->setPosition(0, 0); + + arrowDownImg = new GuiImage(arrowDown); + arrowUpImg = new GuiImage(arrowUp); + scrollbarBoxImg = new GuiImage(scrollbarBox); + + arrowUpBtn = new GuiButton(arrowUpImg->getWidth(), arrowUpImg->getHeight()); + arrowUpBtn->setParent(this); + arrowUpBtn->setImage(arrowUpImg); + arrowUpBtn->setAlignment(ALIGN_CENTER | ALIGN_TOP); + arrowUpBtn->setPosition(0, 0); + arrowUpBtn->setTrigger(&touchTrigger, 0); + arrowUpBtn->setTrigger(&wpadTouchTrigger, 1); + arrowUpBtn->setSoundClick(btnSoundClick); + arrowUpBtn->setEffectGrow(); + arrowUpBtn->clicked.connect(this, &Scrollbar::OnUpButtonClick); + + arrowDownBtn = new GuiButton(arrowDownImg->getWidth(), arrowDownImg->getHeight()); + arrowDownBtn->setParent(this); + arrowDownBtn->setImage(arrowDownImg); + arrowDownBtn->setAlignment(ALIGN_CENTER | ALIGN_BOTTOM); + arrowDownBtn->setPosition(0, 0); + arrowDownBtn->setTrigger(&touchTrigger, 0); + arrowDownBtn->setTrigger(&wpadTouchTrigger, 1); + arrowDownBtn->setSoundClick(btnSoundClick); + arrowDownBtn->setEffectGrow(); + arrowDownBtn->clicked.connect(this, &Scrollbar::OnDownButtonClick); + + scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->getWidth(), height); + scrollbarBoxBtn->setParent(this); + scrollbarBoxBtn->setImage(scrollbarBoxImg); + scrollbarBoxBtn->setAlignment(ALIGN_CENTER | ALIGN_TOP); + scrollbarBoxBtn->setPosition(0, MaxHeight); + scrollbarBoxBtn->setHoldable(true); + scrollbarBoxBtn->setTrigger(&touchTrigger, 0); + scrollbarBoxBtn->setTrigger(&wpadTouchTrigger, 1); + scrollbarBoxBtn->setEffectGrow(); + scrollbarBoxBtn->held.connect(this, &Scrollbar::OnBoxButtonHold); +} + +Scrollbar::~Scrollbar() +{ + Resources::RemoveSound(btnSoundClick); + Resources::RemoveImageData(scrollbarLine); + Resources::RemoveImageData(arrowDown); + Resources::RemoveImageData(arrowUp); + Resources::RemoveImageData(scrollbarBox); + + delete arrowUpBtn; + delete arrowDownBtn; + delete scrollbarBoxBtn; + + delete scrollbarLineImg; + + delete arrowDownImg; + delete arrowUpImg; + delete scrollbarBoxImg; +} + +void Scrollbar::ScrollOneUp() +{ + if(SelItem == 0 && SelInd > 0) + { + // move list up by 1 + --SelInd; + } + else if(SelInd+SelItem > 0) + { + --SelItem; + } +} + +void Scrollbar::ScrollOneDown() +{ + if(SelInd+SelItem + 1 < EntrieCount) + { + if(SelItem == PageSize-1) + { + // move list down by 1 + SelInd++; + } + else + { + SelItem++; + } + } +} + +void Scrollbar::OnUpButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) +{ + if(ScrollState < ScrollSpeed) + return; + + ScrollOneUp(); + + ScrollState = 0; + listChanged(SelItem, SelInd); +} + +void Scrollbar::OnDownButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) +{ + if(ScrollState < ScrollSpeed) + return; + + ScrollOneDown(); + + ScrollState = 0; + listChanged(SelItem, SelInd); +} + +void Scrollbar::OnBoxButtonHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) +{ + if(EntrieCount == 0) + return; + + if(!controller->data.validPointer) + return; + + int y = controller->data.y - this->getCenterY(); + + int positionWiimote = LIMIT(y - MinHeight, 0, MaxHeight - MinHeight); + + int newSelected = (EntrieCount - 1) - (int) ((float) positionWiimote / (float) (MaxHeight-MinHeight) * (float) (EntrieCount-1)); + + int diff = newSelected-SelInd-SelItem; + + if(newSelected <= 0) + { + SelItem = 0; + SelInd = 0; + } + else if(newSelected >= EntrieCount-1) + { + SelItem = (PageSize-1 < EntrieCount-1) ? PageSize-1 : EntrieCount-1; + SelInd = EntrieCount-PageSize; + } + else if(newSelected < PageSize && SelInd == 0 && diff < 0) + { + SelItem = std::max(SelItem+diff, 0); + } + else if(EntrieCount-newSelected < PageSize && SelInd == EntrieCount-PageSize && diff > 0) + { + SelItem = std::min(SelItem+diff, PageSize-1); + } + else + { + SelInd = LIMIT(SelInd+diff, 0, ((EntrieCount-PageSize < 0) ? 0 : EntrieCount-PageSize)); + } + + ScrollState = 0; + listChanged(SelItem, SelInd); +} + +void Scrollbar::SetPageSize(int size) +{ + if(PageSize == size) + return; + + PageSize = size; + listChanged(SelItem, SelInd); +} + +void Scrollbar::SetSelectedItem(int pos) +{ + if(SelItem == pos) + return; + + SelItem = LIMIT(pos, 0, EntrieCount-1); + listChanged(SelItem, SelInd); +} + +void Scrollbar::SetSelectedIndex(int pos) +{ + if(SelInd == pos) + return; + + SelInd = pos; + listChanged(SelItem, SelInd); +} + +void Scrollbar::SetEntrieCount(int cnt) +{ + if(EntrieCount == cnt) + return; + + EntrieCount = cnt; + listChanged(SelItem, SelInd); +} + +void Scrollbar::setScrollboxPosition(int SelItem, int SelInd) +{ + int position = MaxHeight-(MaxHeight-MinHeight)*(SelInd+SelItem)/(EntrieCount-1); + + if(position < MinHeight || (SelInd+SelItem >= EntrieCount-1)) + position = MinHeight; + else if(position > MaxHeight || (SelInd+SelItem) == 0) + position = MaxHeight; + + scrollbarBoxBtn->setPosition(0, position); +} + +void Scrollbar::draw(CVideo * video) +{ + scrollbarLineImg->draw(video); + arrowUpBtn->draw(video); + arrowDownBtn->draw(video); + scrollbarBoxBtn->draw(video); + + updateEffects(); +} + +void Scrollbar::update(GuiController * t) +{ + if(this->isStateSet(STATE_DISABLED)) + return; + + arrowUpBtn->update(t); + arrowDownBtn->update(t); + scrollbarBoxBtn->update(t); + + ++ScrollState; +} + diff --git a/src/gui/Scrollbar.h b/src/gui/Scrollbar.h new file mode 100644 index 0000000..cd7fc94 --- /dev/null +++ b/src/gui/Scrollbar.h @@ -0,0 +1,84 @@ +/*************************************************************************** + * Copyright (C) 2011 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef SCROLLBAR_HPP_ +#define SCROLLBAR_HPP_ + +#include "gui/GuiElement.h" +#include "gui/GuiButton.h" + +class Scrollbar : public GuiElement, public sigslot::has_slots<> +{ + public: + Scrollbar(int height); + virtual ~Scrollbar(); + void ScrollOneUp(); + void ScrollOneDown(); + int GetSelectedItem() { return SelItem; } + int GetSelectedIndex() { return SelInd; } + void draw(CVideo * video); + void update(GuiController * t); + + //! Signals + sigslot::signal2 listChanged; + //! Slots + void SetPageSize(int size); + void SetRowSize(int size); + void SetSelectedItem(int pos); + void SetSelectedIndex(int pos); + void SetEntrieCount(int cnt); + protected: + void setScrollboxPosition(int SelItem, int SelInd); + void OnUpButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger); + void OnDownButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger); + void OnBoxButtonHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger); + + u32 ScrollState; + u16 ScrollSpeed; + + int MinHeight; + int MaxHeight; + int SelItem; + int SelInd; + int PageSize; + int EntrieCount; + int pressedChan; + + GuiButton * arrowUpBtn; + GuiButton * arrowDownBtn; + GuiButton * scrollbarBoxBtn; + GuiImage * scrollbarLineImg; + GuiImage * arrowDownImg; + GuiImage * arrowUpImg; + GuiImage * scrollbarBoxImg; + GuiImageData * scrollbarLine; + GuiImageData * arrowDown; + GuiImageData * arrowUp; + GuiImageData * scrollbarBox; + GuiSound * btnSoundClick; + + GuiTrigger touchTrigger; + GuiTrigger wpadTouchTrigger; +}; + +#endif diff --git a/src/gui/VPadController.h b/src/gui/VPadController.h new file mode 100644 index 0000000..5223774 --- /dev/null +++ b/src/gui/VPadController.h @@ -0,0 +1,63 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef VPAD_CONTROLLER_H_ +#define VPAD_CONTROLLER_H_ + +#include "GuiController.h" +#include "dynamic_libs/vpad_functions.h" + +class VPadController : public GuiController +{ +public: + //!Constructor + VPadController(int channel) + : GuiController(channel) + { + memset(&vpad, 0, sizeof(vpad)); + } + + //!Destructor + virtual ~VPadController() {} + + bool update(int width, int height) + { + lastData = data; + + int vpadError = -1; + VPADRead(0, &vpad, 1, &vpadError); + + if(vpadError == 0) + { + data.buttons_r = vpad.btns_r; + data.buttons_h = vpad.btns_h; + data.buttons_d = vpad.btns_d; + data.validPointer = !vpad.tpdata.invalid; + data.touched = vpad.tpdata.touched; + //! calculate the screen offsets + data.x = -(width >> 1) + ((int)(vpad.tpdata1.x * ((width)/1211.0f)*width) >> 12)-30; + data.y = -(height >> 1) + ((int)(vpad.tpdata1.y * ((height)/653.0f)*height) >> 12)-35; + + return true; + } + return false; + } + +private: + VPADData vpad; +}; + +#endif diff --git a/src/gui/WPadController.h b/src/gui/WPadController.h new file mode 100644 index 0000000..26d1d98 --- /dev/null +++ b/src/gui/WPadController.h @@ -0,0 +1,179 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef WPAD_CONTROLLER_H_ +#define WPAD_CONTROLLER_H_ + +#include "GuiController.h" +#include "dynamic_libs/padscore_functions.h" + +class WPadController : public GuiController +{ +public: + //!Constructor + WPadController(int channel) + : GuiController(channel) + { + memset(&kpadData, 0, sizeof(kpadData)); + } + + //!Destructor + virtual ~WPadController() {} + + u32 remapWiiMoteButtons(u32 buttons) + { + u32 conv_buttons = 0; + + if(buttons & WPAD_BUTTON_LEFT) + conv_buttons |= GuiTrigger::BUTTON_LEFT; + + if(buttons & WPAD_BUTTON_RIGHT) + conv_buttons |= GuiTrigger::BUTTON_RIGHT; + + if(buttons & WPAD_BUTTON_DOWN) + conv_buttons |= GuiTrigger::BUTTON_DOWN; + + if(buttons & WPAD_BUTTON_UP) + conv_buttons |= GuiTrigger::BUTTON_UP; + + if(buttons & WPAD_BUTTON_PLUS) + conv_buttons |= GuiTrigger::BUTTON_PLUS; + + if(buttons & WPAD_BUTTON_2) + conv_buttons |= GuiTrigger::BUTTON_2; + + if(buttons & WPAD_BUTTON_1) + conv_buttons |= GuiTrigger::BUTTON_1; + + if(buttons & WPAD_BUTTON_B) + conv_buttons |= GuiTrigger::BUTTON_B; + + if(buttons & WPAD_BUTTON_A) + conv_buttons |= GuiTrigger::BUTTON_A; + + if(buttons & WPAD_BUTTON_MINUS) + conv_buttons |= GuiTrigger::BUTTON_MINUS; + + if(buttons & WPAD_BUTTON_Z) + conv_buttons |= GuiTrigger::BUTTON_Z; + + if(buttons & WPAD_BUTTON_C) + conv_buttons |= GuiTrigger::BUTTON_C; + + if(buttons & WPAD_BUTTON_HOME) + conv_buttons |= GuiTrigger::BUTTON_HOME; + + return conv_buttons; + } + u32 remapClassicButtons(u32 buttons) + { + u32 conv_buttons = 0; + + if(buttons & WPAD_CLASSIC_BUTTON_LEFT) + conv_buttons |= GuiTrigger::BUTTON_LEFT; + + if(buttons & WPAD_CLASSIC_BUTTON_RIGHT) + conv_buttons |= GuiTrigger::BUTTON_RIGHT; + + if(buttons & WPAD_CLASSIC_BUTTON_DOWN) + conv_buttons |= GuiTrigger::BUTTON_DOWN; + + if(buttons & WPAD_CLASSIC_BUTTON_UP) + conv_buttons |= GuiTrigger::BUTTON_UP; + + if(buttons & WPAD_CLASSIC_BUTTON_PLUS) + conv_buttons |= GuiTrigger::BUTTON_PLUS; + + if(buttons & WPAD_CLASSIC_BUTTON_X) + conv_buttons |= GuiTrigger::BUTTON_X; + + if(buttons & WPAD_CLASSIC_BUTTON_Y) + conv_buttons |= GuiTrigger::BUTTON_Y; + + if(buttons & WPAD_CLASSIC_BUTTON_B) + conv_buttons |= GuiTrigger::BUTTON_B; + + if(buttons & WPAD_CLASSIC_BUTTON_A) + conv_buttons |= GuiTrigger::BUTTON_A; + + if(buttons & WPAD_CLASSIC_BUTTON_MINUS) + conv_buttons |= GuiTrigger::BUTTON_MINUS; + + if(buttons & WPAD_CLASSIC_BUTTON_HOME) + conv_buttons |= GuiTrigger::BUTTON_HOME; + + if(buttons & WPAD_CLASSIC_BUTTON_ZR) + conv_buttons |= GuiTrigger::BUTTON_ZR; + + if(buttons & WPAD_CLASSIC_BUTTON_ZL) + conv_buttons |= GuiTrigger::BUTTON_ZL; + + if(buttons & WPAD_CLASSIC_BUTTON_R) + conv_buttons |= GuiTrigger::BUTTON_R; + + if(buttons & WPAD_CLASSIC_BUTTON_L) + conv_buttons |= GuiTrigger::BUTTON_L; + + return conv_buttons; + } + + bool update(int width, int height) + { + lastData = data; + + u32 controller_type; + + //! check if the controller is connected + if(WPADProbe(chanIdx-1, &controller_type) != 0) + return false; + + KPADRead(chanIdx-1, &kpadData, 1); + + if(kpadData.device_type <= 1) + { + data.buttons_r = remapWiiMoteButtons(kpadData.btns_r); + data.buttons_h = remapWiiMoteButtons(kpadData.btns_h); + data.buttons_d = remapWiiMoteButtons(kpadData.btns_d); + } + else + { + data.buttons_r = remapClassicButtons(kpadData.classic.btns_r); + data.buttons_h = remapClassicButtons(kpadData.classic.btns_h); + data.buttons_d = remapClassicButtons(kpadData.classic.btns_d); + } + + data.validPointer = (kpadData.pos_valid == 1 || kpadData.pos_valid == 2) && (kpadData.pos_x >= -1.0f && kpadData.pos_x <= 1.0f) && (kpadData.pos_y >= -1.0f && kpadData.pos_y <= 1.0f); + //! calculate the screen offsets if pointer is valid else leave old value + if(data.validPointer) + { + data.x = (width >> 1) * kpadData.pos_x; + data.y = (height >> 1) * (-kpadData.pos_y); + + if(kpadData.angle_y > 0.0f) + data.pointerAngle = (-kpadData.angle_x + 1.0f) * 0.5f * 180.0f; + else + data.pointerAngle = (kpadData.angle_x + 1.0f) * 0.5f * 180.0f - 180.0f; + } + + return true; + } + +private: + KPADData kpadData; + u32 lastButtons; +}; + +#endif diff --git a/src/gui/sigslot.h b/src/gui/sigslot.h new file mode 100644 index 0000000..d1f3844 --- /dev/null +++ b/src/gui/sigslot.h @@ -0,0 +1,2731 @@ +// sigslot.h: Signal/Slot classes +// +// Written by Sarah Thompson (sarah@telergy.com) 2002. +// +// License: Public domain. You are free to use this code however you like, with the proviso that +// the author takes on no responsibility or liability for any use. +// +// QUICK DOCUMENTATION +// +// (see also the full documentation at http://sigslot.sourceforge.net/) +// +// #define switches +// SIGSLOT_PURE_ISO - Define this to force ISO C++ compliance. This also disables +// all of the thread safety support on platforms where it is +// available. +// +// SIGSLOT_USE_POSIX_THREADS - Force use of Posix threads when using a C++ compiler other than +// gcc on a platform that supports Posix threads. (When using gcc, +// this is the default - use SIGSLOT_PURE_ISO to disable this if +// necessary) +// +// SIGSLOT_DEFAULT_MT_POLICY - Where thread support is enabled, this defaults to multi_threaded_global. +// Otherwise, the default is single_threaded. #define this yourself to +// override the default. In pure ISO mode, anything other than +// single_threaded will cause a compiler error. +// +// PLATFORM NOTES +// +// Win32 - On Win32, the WIN32 symbol must be #defined. Most mainstream +// compilers do this by default, but you may need to define it +// yourself if your build environment is less standard. This causes +// the Win32 thread support to be compiled in and used automatically. +// +// Unix/Linux/BSD, etc. - If you're using gcc, it is assumed that you have Posix threads +// available, so they are used automatically. You can override this +// (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using +// something other than gcc but still want to use Posix threads, you +// need to #define SIGSLOT_USE_POSIX_THREADS. +// +// ISO C++ - If none of the supported platforms are detected, or if +// SIGSLOT_PURE_ISO is defined, all multithreading support is turned off, +// along with any code that might cause a pure ISO C++ environment to +// complain. Before you ask, gcc -ansi -pedantic won't compile this +// library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of +// errors that aren't really there. If you feel like investigating this, +// please contact the author. +// +// +// THREADING MODES +// +// single_threaded - Your program is assumed to be single threaded from the point of view +// of signal/slot usage (i.e. all objects using signals and slots are +// created and destroyed from a single thread). Behaviour if objects are +// destroyed concurrently is undefined (i.e. you'll get the occasional +// segmentation fault/memory exception). +// +// multi_threaded_global - Your program is assumed to be multi threaded. Objects using signals and +// slots can be safely created and destroyed from any thread, even when +// connections exist. In multi_threaded_global mode, this is achieved by a +// single global mutex (actually a critical section on Windows because they +// are faster). This option uses less OS resources, but results in more +// opportunities for contention, possibly resulting in more context switches +// than are strictly necessary. +// +// multi_threaded_local - Behaviour in this mode is essentially the same as multi_threaded_global, +// except that each signal, and each object that inherits has_slots, all +// have their own mutex/critical section. In practice, this means that +// mutex collisions (and hence context switches) only happen if they are +// absolutely essential. However, on some platforms, creating a lot of +// mutexes can slow down the whole OS, so use this option with care. +// +// USING THE LIBRARY +// +// See the full documentation at http://sigslot.sourceforge.net/ +// +// +#ifndef SIGSLOT_H__ +#define SIGSLOT_H__ + +#include +#include + +#define _SIGSLOT_SINGLE_THREADED + +#ifndef SIGSLOT_DEFAULT_MT_POLICY +# ifdef _SIGSLOT_SINGLE_THREADED +# define SIGSLOT_DEFAULT_MT_POLICY single_threaded +# else +# define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local +# endif +#endif + + +namespace sigslot { + + class single_threaded + { + public: + single_threaded() + { + ; + } + + virtual ~single_threaded() + { + ; + } + + virtual void lock() + { + ; + } + + virtual void unlock() + { + ; + } + }; + +#ifdef _SIGSLOT_HAS_WIN32_THREADS + // The multi threading policies only get compiled in if they are enabled. + class multi_threaded_global + { + public: + multi_threaded_global() + { + static bool isinitialised = false; + + if(!isinitialised) + { + InitializeCriticalSection(get_critsec()); + isinitialised = true; + } + } + + multi_threaded_global(const multi_threaded_global&) + { + ; + } + + virtual ~multi_threaded_global() + { + ; + } + + virtual void lock() + { + EnterCriticalSection(get_critsec()); + } + + virtual void unlock() + { + LeaveCriticalSection(get_critsec()); + } + + private: + CRITICAL_SECTION* get_critsec() + { + static CRITICAL_SECTION g_critsec; + return &g_critsec; + } + }; + + class multi_threaded_local + { + public: + multi_threaded_local() + { + InitializeCriticalSection(&m_critsec); + } + + multi_threaded_local(const multi_threaded_local&) + { + InitializeCriticalSection(&m_critsec); + } + + virtual ~multi_threaded_local() + { + DeleteCriticalSection(&m_critsec); + } + + virtual void lock() + { + EnterCriticalSection(&m_critsec); + } + + virtual void unlock() + { + LeaveCriticalSection(&m_critsec); + } + + private: + CRITICAL_SECTION m_critsec; + }; +#endif // _SIGSLOT_HAS_WIN32_THREADS + +#ifdef _SIGSLOT_HAS_POSIX_THREADS + // The multi threading policies only get compiled in if they are enabled. + class multi_threaded_global + { + public: + multi_threaded_global() + { + pthread_mutex_init(get_mutex(), NULL); + } + + multi_threaded_global(const multi_threaded_global&) + { + ; + } + + virtual ~multi_threaded_global() + { + ; + } + + virtual void lock() + { + pthread_mutex_lock(get_mutex()); + } + + virtual void unlock() + { + pthread_mutex_unlock(get_mutex()); + } + + private: + pthread_mutex_t* get_mutex() + { + static pthread_mutex_t g_mutex; + return &g_mutex; + } + }; + + class multi_threaded_local + { + public: + multi_threaded_local() + { + pthread_mutex_init(&m_mutex, NULL); + } + + multi_threaded_local(const multi_threaded_local&) + { + pthread_mutex_init(&m_mutex, NULL); + } + + virtual ~multi_threaded_local() + { + pthread_mutex_destroy(&m_mutex); + } + + virtual void lock() + { + pthread_mutex_lock(&m_mutex); + } + + virtual void unlock() + { + pthread_mutex_unlock(&m_mutex); + } + + private: + pthread_mutex_t m_mutex; + }; +#endif // _SIGSLOT_HAS_POSIX_THREADS + +#ifdef _SIGSLOT_HAS_LWP_THREADS + + class multi_threaded_global + { + public: + multi_threaded_global() + { + ; + } + + multi_threaded_global(const multi_threaded_global&) + { + ; + } + + virtual ~multi_threaded_global() + { + ; + } + + virtual void lock() + { + ; + } + + virtual void unlock() + { + ; + } + }; + + class multi_threaded_local + { + public: + multi_threaded_local() + { + ; + } + + multi_threaded_local(const multi_threaded_local&) + { + ; + } + + virtual ~multi_threaded_local() + { + } + + virtual void lock() + { + ; + } + + virtual void unlock() + { + ; + } + }; + +#endif // _SIGSLOT_HAS_LWP_THREADS + + template + class lock_block + { + public: + mt_policy *m_mutex; + + lock_block(mt_policy *mtx) + : m_mutex(mtx) + { + m_mutex->lock(); + } + + ~lock_block() + { + m_mutex->unlock(); + } + }; + + template + class has_slots; + + template + class _connection_base0 + { + public: + virtual ~_connection_base0() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit() = 0; + virtual _connection_base0* clone() = 0; + virtual _connection_base0* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base1 + { + public: + virtual ~_connection_base1() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type) = 0; + virtual _connection_base1* clone() = 0; + virtual _connection_base1* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base2 + { + public: + virtual ~_connection_base2() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type) = 0; + virtual _connection_base2* clone() = 0; + virtual _connection_base2* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base3 + { + public: + virtual ~_connection_base3() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type) = 0; + virtual _connection_base3* clone() = 0; + virtual _connection_base3* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base4 + { + public: + virtual ~_connection_base4() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0; + virtual _connection_base4* clone() = 0; + virtual _connection_base4* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base5 + { + public: + virtual ~_connection_base5() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type) = 0; + virtual _connection_base5* clone() = 0; + virtual _connection_base5* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base6 + { + public: + virtual ~_connection_base6() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, + arg6_type) = 0; + virtual _connection_base6* clone() = 0; + virtual _connection_base6* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base7 + { + public: + virtual ~_connection_base7() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, + arg6_type, arg7_type) = 0; + virtual _connection_base7* clone() = 0; + virtual _connection_base7* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base8 + { + public: + virtual ~_connection_base8() { ; } + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, + arg6_type, arg7_type, arg8_type) = 0; + virtual _connection_base8* clone() = 0; + virtual _connection_base8* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _signal_base : public mt_policy + { + public: + virtual void slot_disconnect(has_slots* pslot) = 0; + virtual void slot_duplicate(const has_slots* poldslot, has_slots* pnewslot) = 0; + }; + + template + class has_slots : public mt_policy + { + private: + typedef typename std::set<_signal_base *> sender_set; + typedef typename sender_set::const_iterator const_iterator; + + public: + has_slots() + { + ; + } + + has_slots(const has_slots& hs) + : mt_policy(hs) + { + lock_block lock(this); + const_iterator it = hs.m_senders.begin(); + const_iterator itEnd = hs.m_senders.end(); + + while(it != itEnd) + { + (*it)->slot_duplicate(&hs, this); + m_senders.insert(*it); + ++it; + } + } + + void signal_connect(_signal_base* sender) + { + lock_block lock(this); + m_senders.insert(sender); + } + + void signal_disconnect(_signal_base* sender) + { + lock_block lock(this); + m_senders.erase(sender); + } + + virtual ~has_slots() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_senders.begin(); + const_iterator itEnd = m_senders.end(); + + while(it != itEnd) + { + (*it)->slot_disconnect(this); + ++it; + } + + m_senders.erase(m_senders.begin(), m_senders.end()); + } + + private: + sender_set m_senders; + }; + + template + class _signal_base0 : public _signal_base + { + public: + typedef typename std::list<_connection_base0 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base0() + { + ; + } + + _signal_base0(const _signal_base0& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + ~_signal_base0() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + bool connected() + { + return m_connected_slots.size() != 0; + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base1 : public _signal_base + { + public: + typedef typename std::list<_connection_base1 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base1() + { + ; + } + + _signal_base1(const _signal_base1& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base1() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + bool connected() + { + return m_connected_slots.size() != 0; + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base2 : public _signal_base + { + public: + typedef typename std::list<_connection_base2 *> + connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base2() + { + ; + } + + _signal_base2(const _signal_base2& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base2() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + bool connected() + { + return m_connected_slots.size() != 0; + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base3 : public _signal_base + { + public: + typedef std::list<_connection_base3 *> + connections_list; + + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + _signal_base3() + { + ; + } + + _signal_base3(const _signal_base3& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base3() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + bool connected() + { + return m_connected_slots.size() != 0; + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base4 : public _signal_base + { + public: + typedef std::list<_connection_base4 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base4() + { + ; + } + + _signal_base4(const _signal_base4& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base4() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + this->m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + bool connected() + { + return m_connected_slots.size() != 0; + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base5 : public _signal_base + { + public: + typedef std::list<_connection_base5 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base5() + { + ; + } + + _signal_base5(const _signal_base5& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base5() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + bool connected() + { + return m_connected_slots.size() != 0; + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base6 : public _signal_base + { + public: + typedef std::list<_connection_base6 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base6() + { + ; + } + + _signal_base6(const _signal_base6& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base6() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + bool connected() + { + return m_connected_slots.size() != 0; + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base7 : public _signal_base + { + public: + typedef std::list<_connection_base7 *> connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base7() + { + ; + } + + _signal_base7(const _signal_base7& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base7() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + bool connected() + { + return m_connected_slots.size() != 0; + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base8 : public _signal_base + { + public: + typedef std::list<_connection_base8 *> + connections_list; + typedef typename connections_list::const_iterator const_iterator; + typedef typename connections_list::iterator iterator; + + _signal_base8() + { + ; + } + + _signal_base8(const _signal_base8& s) + : _signal_base(s) + { + lock_block lock(this); + const_iterator it = s.m_connected_slots.begin(); + const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base8() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_connected_slots.begin(); + const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + bool connected() + { + return m_connected_slots.size() != 0; + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + iterator it = m_connected_slots.begin(); + iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + delete *it; + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + + template + class _connection0 : public _connection_base0 + { + public: + _connection0() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection0(dest_type* pobject, void (dest_type::*pmemfun)()) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection0() + { + ; + } + + virtual _connection_base0* clone() + { + return new _connection0(*this); + } + + virtual _connection_base0* duplicate(has_slots* pnewdest) + { + return new _connection0((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit() + { + (m_pobject->*m_pmemfun)(); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(); + }; + + template + class _connection1 : public _connection_base1 + { + public: + _connection1() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection1() + { + ; + } + + virtual _connection_base1* clone() + { + return new _connection1(*this); + } + + virtual _connection_base1* duplicate(has_slots* pnewdest) + { + return new _connection1((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1) + { + (m_pobject->*m_pmemfun)(a1); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type); + }; + + template + class _connection2 : public _connection_base2 + { + public: + _connection2() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection2() + { + ; + } + + + virtual _connection_base2* clone() + { + return new _connection2(*this); + } + + virtual _connection_base2* duplicate(has_slots* pnewdest) + { + return new _connection2((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2) + { + (m_pobject->*m_pmemfun)(a1, a2); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type); + }; + + template + class _connection3 : public _connection_base3 + { + public: + _connection3() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection3() + { + ; + } + + + virtual _connection_base3* clone() + { + return new _connection3(*this); + } + + virtual _connection_base3* duplicate(has_slots* pnewdest) + { + return new _connection3((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3) + { + (m_pobject->*m_pmemfun)(a1, a2, a3); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type); + }; + + template + class _connection4 : public _connection_base4 + { + public: + _connection4() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection4() + { + ; + } + + virtual _connection_base4* clone() + { + return new _connection4(*this); + } + + virtual _connection_base4* duplicate(has_slots* pnewdest) + { + return new _connection4((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, + arg4_type a4) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, + arg4_type); + }; + + template + class _connection5 : public _connection_base5 + { + public: + _connection5() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection5() + { + ; + } + + virtual _connection_base5* clone() + { + return new _connection5(*this); + } + + virtual _connection_base5* duplicate(has_slots* pnewdest) + { + return new _connection5((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type); + }; + + template + class _connection6 : public _connection_base6 + { + public: + _connection6() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection6() + { + ; + } + + virtual _connection_base6* clone() + { + return new _connection6(*this); + } + + virtual _connection_base6* duplicate(has_slots* pnewdest) + { + return new _connection6((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type, arg6_type); + }; + + template + class _connection7 : public _connection_base7 + { + public: + _connection7() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection7() + { + ; + } + + virtual _connection_base7* clone() + { + return new _connection7(*this); + } + + virtual _connection_base7* duplicate(has_slots* pnewdest) + { + return new _connection7((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type, arg6_type, arg7_type); + }; + + template + class _connection8 : public _connection_base8 + { + public: + _connection8() + { + this->pobject = NULL; + this->pmemfun = NULL; + } + + _connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, + arg7_type, arg8_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual ~_connection8() + { + ; + } + + virtual _connection_base8* clone() + { + return new _connection8(*this); + } + + virtual _connection_base8* duplicate(has_slots* pnewdest) + { + return new _connection8((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type, arg6_type, arg7_type, arg8_type); + }; + + template + class signal0 : public _signal_base0 + { + public: + typedef typename _signal_base0::connections_list::const_iterator const_iterator; + signal0() + { + ; + } + + signal0(const signal0& s) + : _signal_base0(s) + { + ; + } + + virtual ~signal0() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)()) + { + lock_block lock(this); + _connection0* conn = + new _connection0(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit() + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(); + + it = itNext; + } + } + + void operator()() + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(); + + it = itNext; + } + } + }; + + template + class signal1 : public _signal_base1 + { + public: + typedef typename _signal_base1::connections_list::const_iterator const_iterator; + signal1() + { + ; + } + + signal1(const signal1& s) + : _signal_base1(s) + { + ; + } + + virtual ~signal1() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type)) + { + lock_block lock(this); + _connection1* conn = + new _connection1(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1); + + it = itNext; + } + } + + void operator()(arg1_type a1) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1); + + it = itNext; + } + } + }; + + template + class signal2 : public _signal_base2 + { + public: + typedef typename _signal_base2::connections_list::const_iterator const_iterator; + signal2() + { + ; + } + + signal2(const signal2& s) + : _signal_base2(s) + { + ; + } + + virtual ~signal2() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type)) + { + lock_block lock(this); + _connection2* conn = new + _connection2(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2); + + it = itNext; + } + } + }; + + template + class signal3 : public _signal_base3 + { + public: + typedef typename _signal_base3::connections_list::const_iterator const_iterator; + signal3() + { + ; + } + + signal3(const signal3& s) + : _signal_base3(s) + { + ; + } + + virtual ~signal3() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type)) + { + lock_block lock(this); + _connection3* conn = + new _connection3(pclass, + pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3); + + it = itNext; + } + } + }; + + template + class signal4 : public _signal_base4 + { + public: + typedef typename _signal_base4::connections_list::const_iterator const_iterator; + signal4() + { + ; + } + + signal4(const signal4& s) + : _signal_base4(s) + { + ; + } + + virtual ~signal4() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type)) + { + lock_block lock(this); + _connection4* + conn = new _connection4(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4); + + it = itNext; + } + } + }; + + template + class signal5 : public _signal_base5 + { + public: + typedef typename _signal_base5::connections_list::const_iterator const_iterator; + signal5() + { + ; + } + + signal5(const signal5& s) + : _signal_base5(s) + { + ; + } + + virtual ~signal5() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type)) + { + lock_block lock(this); + _connection5* conn = new _connection5(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5); + + it = itNext; + } + } + }; + + + template + class signal6 : public _signal_base6 + { + public: + typedef typename _signal_base6::connections_list::const_iterator const_iterator; + signal6() + { + ; + } + + signal6(const signal6& s) + : _signal_base6(s) + { + ; + } + + virtual ~signal6() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) + { + lock_block lock(this); + _connection6* conn = + new _connection6(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6); + + it = itNext; + } + } + }; + + template + class signal7 : public _signal_base7 + { + public: + typedef typename _signal_base7::connections_list::const_iterator const_iterator; + signal7() + { + ; + } + + signal7(const signal7& s) + : _signal_base7(s) + { + ; + } + + virtual ~signal7() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, + arg7_type)) + { + lock_block lock(this); + _connection7* conn = + new _connection7(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7); + + it = itNext; + } + } + }; + + template + class signal8 : public _signal_base8 + { + public: + typedef typename _signal_base8::connections_list::const_iterator const_iterator; + signal8() + { + ; + } + + signal8(const signal8& s) + : _signal_base8(s) + { + ; + } + + virtual ~signal8() + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, + arg7_type, arg8_type)) + { + lock_block lock(this); + _connection8* conn = + new _connection8(pclass, pmemfun); + this->m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) + { + lock_block lock(this); + const_iterator itNext, it = this->m_connected_slots.begin(); + const_iterator itEnd = this->m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); + + it = itNext; + } + } + }; + +}; // namespace sigslot + +#endif // SIGSLOT_H__ diff --git a/src/kernel/kernel_functions.c b/src/kernel/kernel_functions.c new file mode 100644 index 0000000..31f9ad0 --- /dev/null +++ b/src/kernel/kernel_functions.c @@ -0,0 +1,49 @@ +#include +#include "common/common.h" +#include "common/kernel_defs.h" +#include "kernel/kernel_functions.h" +#include "kernel/syscalls.h" + +/* our retain data */ +ReducedCosAppXmlInfo cosAppXmlInfoStruct __attribute__((section(".data"))); +/* + * This function is a kernel hook function. It is called directly from kernel code at position 0xFFF18558. + */ +void my_PrepareTitle(CosAppXmlInfo *xmlKernelInfo) +{ + /** + * DBAT for access to our data region is setup at this point for the 0xC0000000 area. + */ + + //! Copy all data from the XML info + strncpy(cosAppXmlInfoStruct.rpx_name, xmlKernelInfo->rpx_name, FS_MAX_ENTNAME_SIZE); + + cosAppXmlInfoStruct.version_cos_xml = xmlKernelInfo->version_cos_xml; + cosAppXmlInfoStruct.os_version = xmlKernelInfo->os_version; + cosAppXmlInfoStruct.title_id = xmlKernelInfo->title_id; + cosAppXmlInfoStruct.app_type = xmlKernelInfo->app_type; + cosAppXmlInfoStruct.cmdFlags = xmlKernelInfo->cmdFlags; + cosAppXmlInfoStruct.max_size = xmlKernelInfo->max_size; + cosAppXmlInfoStruct.avail_size = xmlKernelInfo->avail_size; + cosAppXmlInfoStruct.codegen_size = xmlKernelInfo->codegen_size; + cosAppXmlInfoStruct.codegen_core = xmlKernelInfo->codegen_core; + cosAppXmlInfoStruct.max_codesize = xmlKernelInfo->max_codesize; + cosAppXmlInfoStruct.overlay_arena = xmlKernelInfo->overlay_arena; + cosAppXmlInfoStruct.default_stack0_size = xmlKernelInfo->default_stack0_size; + cosAppXmlInfoStruct.default_stack1_size = xmlKernelInfo->default_stack1_size; + cosAppXmlInfoStruct.default_stack2_size = xmlKernelInfo->default_stack2_size; + cosAppXmlInfoStruct.default_redzone0_size = xmlKernelInfo->default_redzone0_size; + cosAppXmlInfoStruct.default_redzone1_size = xmlKernelInfo->default_redzone1_size; + cosAppXmlInfoStruct.default_redzone2_size = xmlKernelInfo->default_redzone2_size; + cosAppXmlInfoStruct.exception_stack0_size = xmlKernelInfo->exception_stack0_size; + cosAppXmlInfoStruct.exception_stack1_size = xmlKernelInfo->exception_stack1_size; + cosAppXmlInfoStruct.exception_stack2_size = xmlKernelInfo->exception_stack2_size; + cosAppXmlInfoStruct.sdk_version = xmlKernelInfo->sdk_version; + cosAppXmlInfoStruct.title_version = xmlKernelInfo->title_version; +} + +void SetupKernelCallback(void) +{ + KernelSetupSyscalls(); +} + diff --git a/src/kernel/kernel_functions.h b/src/kernel/kernel_functions.h new file mode 100644 index 0000000..79b89e4 --- /dev/null +++ b/src/kernel/kernel_functions.h @@ -0,0 +1,19 @@ +#ifndef __KERNEL_FUNCTIONS_H_ +#define __KERNEL_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "common/kernel_defs.h" +#include "syscalls.h" + +void SetupKernelCallback(void); + +extern ReducedCosAppXmlInfo cosAppXmlInfoStruct; + +#ifdef __cplusplus +} +#endif + +#endif // __KERNEL_FUNCTIONS_H_ diff --git a/src/kernel/kernel_hooks.S b/src/kernel/kernel_hooks.S new file mode 100644 index 0000000..04452c4 --- /dev/null +++ b/src/kernel/kernel_hooks.S @@ -0,0 +1,136 @@ +# Created by dimok +# This stuff may need a change in different kernel versions +# This is only needed when launched directly through browser and not SD card. + +.section ".kernel_code" + .globl SaveAndResetDataBATs_And_SRs_hook +SaveAndResetDataBATs_And_SRs_hook: + # setup CTR to the position we need to return to + mflr r5 + mtctr r5 + # set link register to its original value + mtlr r7 + # setup us a nice DBAT for our code data with same region as our code + mfspr r5, 560 + mtspr 570, r5 + mfspr r5, 561 + mtspr 571, r5 + # restore the original kernel instructions that we replaced + lwz r5, 0x34(r3) + lwz r6, 0x38(r3) + lwz r7, 0x3C(r3) + lwz r8, 0x40(r3) + lwz r9, 0x44(r3) + lwz r10, 0x48(r3) + lwz r11, 0x4C(r3) + lwz r3, 0x50(r3) + isync + mtsr 7, r5 + # jump back to the position in kernel after our patch (from LR) + bctr + +.extern my_PrepareTitle + .globl my_PrepareTitle_hook +my_PrepareTitle_hook: + # store all registers on stack to avoid issues with the call to C functions + stwu r1, -0x90(r1) + # registers for our own usage + # only need r31 and rest is from tests before, just leaving it for later tests + stw r28, 0x20(r1) + stw r29, 0x24(r1) + stw r30, 0x28(r1) + stw r31, 0x2C(r1) + + stw r3, 0x30(r1) + stw r4, 0x34(r1) + stw r5, 0x38(r1) + stw r6, 0x3C(r1) + stw r7, 0x40(r1) + stw r8, 0x44(r1) + stw r9, 0x48(r1) + stw r10, 0x4C(r1) + stw r11, 0x50(r1) + stw r12, 0x54(r1) + stw r13, 0x58(r1) + stw r14, 0x5C(r1) + stw r15, 0x60(r1) + stw r16, 0x64(r1) + stw r17, 0x68(r1) + stw r18, 0x6C(r1) + stw r19, 0x70(r1) + stw r20, 0x74(r1) + stw r21, 0x78(r1) + stw r22, 0x7C(r1) + + # save original DBAT registers + mfdbatu r28, 0 + mfdbatl r29, 0 + + # setup access to our data memory range + lis r3, 0xC000 + ori r3, r3, 0x1FFF + mtdbatu 0, r3 + lis r3, 0x3000 + ori r3, r3, 0x0012 + mtdbatl 0, r3 + + # memory barrier + eieio + isync + + # save the LR from where we came + mflr r31 + + # the cos.xml/app.xml structure is at the location 0x68 of r11 + # there are actually many places that can be hooked for it + # e.g. 0xFFF16130 and r27 points to this structure + addi r3, r11, 0x68 + + bl my_PrepareTitle + + # restore original DBAT registers + mtdbatu 0, r28 + mtdbatl 0, r29 + + # memory barrier + eieio + isync + + # setup LR to jump back to kernel code + mtlr r31 + + # restore all original values of registers from stack + lwz r28, 0x20(r1) + lwz r29, 0x24(r1) + lwz r30, 0x28(r1) + lwz r31, 0x2C(r1) + + lwz r3, 0x30(r1) + lwz r4, 0x34(r1) + lwz r5, 0x38(r1) + lwz r6, 0x3C(r1) + lwz r7, 0x40(r1) + lwz r8, 0x44(r1) + lwz r9, 0x48(r1) + lwz r10, 0x4C(r1) + lwz r11, 0x50(r1) + lwz r12, 0x54(r1) + lwz r13, 0x58(r1) + lwz r14, 0x5C(r1) + lwz r15, 0x60(r1) + lwz r16, 0x64(r1) + lwz r17, 0x68(r1) + lwz r18, 0x6C(r1) + lwz r19, 0x70(r1) + lwz r20, 0x74(r1) + lwz r21, 0x78(r1) + lwz r22, 0x7C(r1) + + # restore the stack + addi r1, r1, 0x90 + + # restore original instruction that we replaced in the kernel + clrlwi r7, r12, 0 + + # jump back + blr diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c new file mode 100644 index 0000000..9685e4a --- /dev/null +++ b/src/kernel/syscalls.c @@ -0,0 +1,255 @@ +#include "common/os_defs.h" +#include "common/kernel_defs.h" +#include "common/common.h" +#include "dynamic_libs/os_functions.h" +#include "utils/utils.h" +#include "syscalls.h" + +extern void my_PrepareTitle_hook(void); + +static unsigned int origPrepareTitleInstr __attribute__((section(".data"))) = 0; + +static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len) +{ + /* + * Setup a DBAT access with cache inhibited to write through and read directly from memory + */ + unsigned int dbatu0, dbatl0, dbatu1, dbatl1; + // save the original DBAT value + asm volatile("mfdbatu %0, 0" : "=r" (dbatu0)); + asm volatile("mfdbatl %0, 0" : "=r" (dbatl0)); + asm volatile("mfdbatu %0, 1" : "=r" (dbatu1)); + asm volatile("mfdbatl %0, 1" : "=r" (dbatl1)); + + unsigned int target_dbatu0 = 0; + unsigned int target_dbatl0 = 0; + unsigned int target_dbatu1 = 0; + unsigned int target_dbatl1 = 0; + + unsigned char *dst_p = (unsigned char*)addr; + unsigned char *src_p = (unsigned char*)src; + + // we only need DBAT modification for addresses out of our own DBAT range + // as our own DBAT is available everywhere for user and supervisor + // since our own DBAT is on DBAT5 position we don't collide here + if(addr < 0x00800000 || addr >= 0x01000000) + { + target_dbatu0 = (addr & 0x00F00000) | 0xC0000000 | 0x1F; + target_dbatl0 = (addr & 0xFFF00000) | 0x32; + asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); + asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); + dst_p = (unsigned char*)((addr & 0xFFFFFF) | 0xC0000000); + } + if(src < 0x00800000 || src >= 0x01000000) + { + target_dbatu1 = (src & 0x00F00000) | 0xB0000000 | 0x1F; + target_dbatl1 = (src & 0xFFF00000) | 0x32; + + asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); + asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); + src_p = (unsigned char*)((src & 0xFFFFFF) | 0xB0000000); + } + + asm volatile("eieio; isync"); + + unsigned int i; + for(i = 0; i < len; i++) + { + // if we are on the edge to next chunk + if((target_dbatu0 != 0) && (((unsigned int)dst_p & 0x00F00000) != (target_dbatu0 & 0x00F00000))) + { + target_dbatu0 = ((addr + i) & 0x00F00000) | 0xC0000000 | 0x1F; + target_dbatl0 = ((addr + i) & 0xFFF00000) | 0x32; + dst_p = (unsigned char*)(((addr + i) & 0xFFFFFF) | 0xC0000000); + + asm volatile("eieio; isync"); + asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); + asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); + asm volatile("eieio; isync"); + } + if((target_dbatu1 != 0) && (((unsigned int)src_p & 0x00F00000) != (target_dbatu1 & 0x00F00000))) + { + target_dbatu1 = ((src + i) & 0x00F00000) | 0xB0000000 | 0x1F; + target_dbatl1 = ((src + i) & 0xFFF00000) | 0x32; + src_p = (unsigned char*)(((src + i) & 0xFFFFFF) | 0xB0000000); + + asm volatile("eieio; isync"); + asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); + asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); + asm volatile("eieio; isync"); + } + + *dst_p = *src_p; + + ++dst_p; + ++src_p; + } + + /* + * Restore original DBAT value + */ + asm volatile("eieio; isync"); + asm volatile("mtdbatu 0, %0" : : "r" (dbatu0)); + asm volatile("mtdbatl 0, %0" : : "r" (dbatl0)); + asm volatile("mtdbatu 1, %0" : : "r" (dbatu1)); + asm volatile("mtdbatl 1, %0" : : "r" (dbatl1)); + asm volatile("eieio; isync"); +} + +static void KernelReadDBATs(bat_table_t * table) +{ + u32 i = 0; + + asm volatile("eieio; isync"); + + asm volatile("mfspr %0, 536" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 537" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 538" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 539" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 540" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 541" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 542" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 543" : "=r" (table->bat[i].l)); + i++; + + asm volatile("mfspr %0, 568" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 569" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 570" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 571" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 572" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 573" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 574" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 575" : "=r" (table->bat[i].l)); +} + +static void KernelWriteDBATs(bat_table_t * table) +{ + u32 i = 0; + + asm volatile("eieio; isync"); + + asm volatile("mtspr 536, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 537, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 538, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 539, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 540, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 541, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 542, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 543, %0" : : "r" (table->bat[i].l)); + i++; + + asm volatile("mtspr 568, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 569, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 570, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 571, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 572, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 573, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 574, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 575, %0" : : "r" (table->bat[i].l)); + + asm volatile("eieio; isync"); +} + +/* Read a 32-bit word with kernel permissions */ +uint32_t __attribute__ ((noinline)) kern_read(const void *addr) +{ + uint32_t result; + asm volatile ( + "li 3,1\n" + "li 4,0\n" + "li 5,0\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%1\n" + "li 0,0x3400\n" + "mr %0,1\n" + "sc\n" + "nop\n" + "mr 1,%0\n" + "mr %0,3\n" + : "=r"(result) + : "b"(addr) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" + ); + + return result; +} + +/* Write a 32-bit word with kernel permissions */ +void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value) +{ + asm volatile ( + "li 3,1\n" + "li 4,0\n" + "mr 5,%1\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%0\n" + "mr %1,1\n" + "li 0,0x3500\n" + "sc\n" + "nop\n" + "mr 1,%1\n" + : + : "r"(addr), "r"(value) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" + ); +} + +void KernelSetupSyscalls(void) +{ + //! assign 1 so that this variable gets into the retained .data section + static uint8_t ucSyscallsSetupRequired = 1; + if(!ucSyscallsSetupRequired) + return; + + ucSyscallsSetupRequired = 0; + + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x25 * 4)), (unsigned int)KernelCopyData); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x25 * 4)), (unsigned int)KernelCopyData); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x25 * 4)), (unsigned int)KernelCopyData); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x25 * 4)), (unsigned int)KernelCopyData); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x25 * 4)), (unsigned int)KernelCopyData); + + //! write our hook to the + u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003; + DCFlushRange(&addr_my_PrepareTitle_hook, sizeof(addr_my_PrepareTitle_hook)); + + SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4); + SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)OSEffectiveToPhysical(&addr_my_PrepareTitle_hook), 4); +} + + +void KernelRestoreInstructions(void) +{ + if(origPrepareTitleInstr != 0) + SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)&origPrepareTitleInstr, 4); +} diff --git a/src/kernel/syscalls.h b/src/kernel/syscalls.h new file mode 100644 index 0000000..344fa39 --- /dev/null +++ b/src/kernel/syscalls.h @@ -0,0 +1,26 @@ + +#ifndef __SYSCALLS_H_ +#define __SYSCALLS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "common/kernel_defs.h" + +void KernelSetupSyscalls(void); +void KernelRestoreInstructions(void); + +void SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len); +void SC0x36_KernelReadDBATs(bat_table_t * table); +void SC0x37_KernelWriteDBATs(bat_table_t * table); + +uint32_t __attribute__ ((noinline)) kern_read(const void *addr); +void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value); + +#ifdef __cplusplus +} +#endif + +#endif // __KERNEL_FUNCTIONS_H_ diff --git a/src/kernel/syscalls_asm.S b/src/kernel/syscalls_asm.S new file mode 100644 index 0000000..60bf1fa --- /dev/null +++ b/src/kernel/syscalls_asm.S @@ -0,0 +1,20 @@ +# Created by dimok +# Syscalls for kernel that we use + + .globl SC0x36_KernelReadDBATs +SC0x36_KernelReadDBATs: + li r0, 0x3600 + sc + blr + + .globl SC0x37_KernelWriteDBATs +SC0x37_KernelWriteDBATs: + li r0, 0x3700 + sc + blr + + .globl SC0x25_KernelCopyData +SC0x25_KernelCopyData: + li r0, 0x2500 + sc + blr diff --git a/src/link.ld b/src/link.ld new file mode 100644 index 0000000..30737dc --- /dev/null +++ b/src/link.ld @@ -0,0 +1,43 @@ +OUTPUT(hidtovpad.elf); + +/* Tell linker where our application entry is so the garbage collect can work correct */ +ENTRY(__entry_menu); + +SECTIONS { + . = 0x00802000; + .text : { + *(.kernel_code*); + *(.text*); + /* Tell linker to not garbage collect this section as it is not referenced anywhere */ + KEEP(*(.kernel_code*)); + } + .rodata : { + *(.rodata*); + } + .data : { + *(.data*); + + __sdata_start = .; + *(.sdata*); + __sdata_end = .; + + __sdata2_start = .; + *(.sdata2*); + __sdata2_end = .; + } + .bss : { + __bss_start = .; + *(.bss*); + *(.sbss*); + *(COMMON); + __bss_end = .; + } + __CODE_END = .; + + /DISCARD/ : { + *(*); + } +} + +/******************************************************** FS ********************************************************/ +/* coreinit.rpl difference in addresses 0xFE3C00 */ diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..f1fd6c3 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,65 @@ +#include "Application.h" +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/gx2_functions.h" +#include "dynamic_libs/syshid_functions.h" +#include "dynamic_libs/vpad_functions.h" +#include "dynamic_libs/padscore_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "dynamic_libs/sys_functions.h" +#include "dynamic_libs/ax_functions.h" +#include "dynamic_libs/fs_functions.h" +#include "fs/fs_utils.h" +#include "fs/sd_fat_devoptab.h" +#include "system/memory.h" +#include "utils/logger.h" +#include "utils/utils.h" +#include "common/common.h" + +#include "main.h" +#include "common/common.h" + +#include "utils/logger.h" + +#include "system/memory.h" + +/* Entry point */ +extern "C" int Menu_Main(void){ + //!******************************************************************* + //! Initialize function pointers * + //!******************************************************************* + //! do OS (for acquire) and sockets first so we got logging + InitOSFunctionPointers(); + InitSocketFunctionPointers(); + InitGX2FunctionPointers(); + InitSysFunctionPointers(); + InitVPadFunctionPointers(); + InitPadScoreFunctionPointers(); + InitAXFunctionPointers(); + InitFSFunctionPointers(); + + log_init("192.168.1.12"); + + //Otherwise apply the patches!!! + log_printf("GX2_template\n\n"); + + //!******************************************************************* + //! Initialize heap memory * + //!******************************************************************* + log_print("Initialize memory management\n"); + memoryInitialize(); + + log_printf("Mount SD partition\n"); + mount_sd_fat("sd"); + log_printf("Start main application\n"); + Application::instance()->exec(); + + Application::destroyInstance(); + log_printf("Unmount SD\n"); + unmount_sd_fat("sd"); + memoryRelease(); + + log_print("Going back to the Homebrew launcher\n"); + + log_deinit(); + return EXIT_SUCCESS; +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..a0fb71e --- /dev/null +++ b/src/main.h @@ -0,0 +1,19 @@ +#ifndef _MAIN_H_ +#define _MAIN_H_ + +#include "common/types.h" +#include "dynamic_libs/os_functions.h" + +/* Main */ +#ifdef __cplusplus +extern "C" { +#endif + +//! C wrapper for our C++ functions +int Menu_Main(void); +void deInit(void); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/menu/MainWindow.cpp b/src/menu/MainWindow.cpp new file mode 100644 index 0000000..e7f55ab --- /dev/null +++ b/src/menu/MainWindow.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * Modified by Maschell, 2016 for GX2_GUI_Template + * + * 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 . + ****************************************************************************/ +#include "MainWindow.h" +#include "MainWindowTV.h" +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "Application.h" +#include "utils/StringTools.h" +#include "utils/logger.h" + +MainWindow::MainWindow(int w, int h) + : width(w) + , height(h) +{ + for(int i = 0; i < 4; i++) + { + std::string filename = strfmt("player%i_point.png", i+1); + pointerImgData[i] = Resources::GetImageData(filename.c_str()); + pointerImg[i] = new GuiImage(pointerImgData[i]); + pointerImg[i]->setScale(1.5f); + pointerValid[i] = false; + } + + SetupMainView(); +} + +MainWindow::~MainWindow() +{ + + while(!tvElements.empty()) + { + delete tvElements[0]; + remove(tvElements[0]); + } + while(!drcElements.empty()) + { + delete drcElements[0]; + remove(drcElements[0]); + } + for(int i = 0; i < 4; i++) + { + delete pointerImg[i]; + Resources::RemoveImageData(pointerImgData[i]); + } +} + +void MainWindow::updateEffects() +{ + //! dont read behind the initial elements in case one was added + u32 tvSize = tvElements.size(); + u32 drcSize = drcElements.size(); + + for(u32 i = 0; (i < drcSize) && (i < drcElements.size()); ++i) + { + drcElements[i]->updateEffects(); + } + + //! only update TV elements that are not updated yet because they are on DRC + for(u32 i = 0; (i < tvSize) && (i < tvElements.size()); ++i) + { + u32 n; + for(n = 0; (n < drcSize) && (n < drcElements.size()); n++) + { + if(tvElements[i] == drcElements[n]) + break; + } + if(n == drcElements.size()) + { + tvElements[i]->updateEffects(); + } + } +} + +void MainWindow::process(){ + //! dont read behind the initial elements in case one was added + u32 tvSize = tvElements.size(); + u32 drcSize = drcElements.size(); + + for(u32 i = 0; (i < drcSize) && (i < drcElements.size()); ++i) + { + drcElements[i]->process(); + } + + //! only update TV elements that are not updated yet because they are on DRC + for(u32 i = 0; (i < tvSize) && (i < tvElements.size()); ++i) + { + u32 n; + for(n = 0; (n < drcSize) && (n < drcElements.size()); n++) + { + if(tvElements[i] == drcElements[n]) + break; + } + if(n == drcElements.size()) + { + tvElements[i]->process(); + } + } +} + +void MainWindow::update(GuiController *controller) +{ + //! dont read behind the initial elements in case one was added + //u32 tvSize = tvElements.size(); + + if(controller->chan & GuiTrigger::CHANNEL_1) + { + u32 drcSize = drcElements.size(); + + for(u32 i = 0; (i < drcSize) && (i < drcElements.size()); ++i) + { + drcElements[i]->update(controller); + } + } + else + { + u32 tvSize = tvElements.size(); + + for(u32 i = 0; (i < tvSize) && (i < tvElements.size()); ++i) + { + tvElements[i]->update(controller); + } + } + +// //! only update TV elements that are not updated yet because they are on DRC +// for(u32 i = 0; (i < tvSize) && (i < tvElements.size()); ++i) +// { +// u32 n; +// for(n = 0; (n < drcSize) && (n < drcElements.size()); n++) +// { +// if(tvElements[i] == drcElements[n]) +// break; +// } +// if(n == drcElements.size()) +// { +// tvElements[i]->update(controller); +// } +// } + + if(controller->chanIdx >= 1 && controller->chanIdx <= 4 && controller->data.validPointer) + { + int wpadIdx = controller->chanIdx - 1; + f32 posX = controller->data.x; + f32 posY = controller->data.y; + pointerImg[wpadIdx]->setPosition(posX, posY); + pointerImg[wpadIdx]->setAngle(controller->data.pointerAngle); + pointerValid[wpadIdx] = true; + } +} + +void MainWindow::drawDrc(CVideo *video) +{ + for(u32 i = 0; i < drcElements.size(); ++i) + { + drcElements[i]->draw(video); + } + + for(int i = 0; i < 4; i++) + { + if(pointerValid[i]) + { + pointerImg[i]->setAlpha(0.5f); + pointerImg[i]->draw(video); + pointerImg[i]->setAlpha(1.0f); + } + } +} + +void MainWindow::drawTv(CVideo *video) +{ + for(u32 i = 0; i < tvElements.size(); ++i) + { + tvElements[i]->draw(video); + } + + for(int i = 0; i < 4; i++) + { + if(pointerValid[i]) + { + pointerImg[i]->draw(video); + pointerValid[i] = false; + } + } +} + +void MainWindow::SetupMainView() +{ + + //DrcFrame = new MainWindowDRC(width,height); + TvFrame = new MainWindowTV(width,height); + DrcFrame = TvFrame; + appendTv(TvFrame); + appendDrc(DrcFrame); +} + +void MainWindow::OnOpenEffectFinish(GuiElement *element) +{ + //! once the menu is open reset its state and allow it to be "clicked/hold" + element->effectFinished.disconnect(this); + element->clearState(GuiElement::STATE_DISABLED); +} + +void MainWindow::OnCloseEffectFinish(GuiElement *element) +{ + //! remove element from draw list and push to delete queue + remove(element); + AsyncDeleter::pushForDelete(element); +} diff --git a/src/menu/MainWindow.h b/src/menu/MainWindow.h new file mode 100644 index 0000000..8f160a3 --- /dev/null +++ b/src/menu/MainWindow.h @@ -0,0 +1,153 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * Modified by Maschell, 2016 for GX2_GUI_Template + * + * 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 . + ****************************************************************************/ +#ifndef _MAIN_WINDOW_H_ +#define _MAIN_WINDOW_H_ + +#include +#include +#include "gui/Gui.h" +#include "system/CMutex.h" +#include "gui/GuiMainWindowScreen.h" + +class CVideo; + +class MainWindow : public sigslot::has_slots<> +{ +public: + MainWindow(int w, int h); + virtual ~MainWindow(); + + void appendTv(GuiElement *e) + { + if(!e) + return; + + removeTv(e); + tvElements.push_back(e); + } + void appendDrc(GuiElement *e) + { + if(!e) + return; + + removeDrc(e); + drcElements.push_back(e); + } + + void append(GuiElement *e) + { + appendTv(e); + appendDrc(e); + } + + void insertTv(u32 pos, GuiElement *e) + { + if(!e) + return; + + removeTv(e); + tvElements.insert(tvElements.begin() + pos, e); + } + void insertDrc(u32 pos, GuiElement *e) + { + if(!e) + return; + + removeDrc(e); + drcElements.insert(drcElements.begin() + pos, e); + } + + void insert(u32 pos, GuiElement *e) + { + insertTv(pos, e); + insertDrc(pos, e); + } + + void removeTv(GuiElement *e) + { + for(u32 i = 0; i < tvElements.size(); ++i) + { + if(e == tvElements[i]) + { + tvElements.erase(tvElements.begin() + i); + break; + } + } + } + void removeDrc(GuiElement *e) + { + for(u32 i = 0; i < drcElements.size(); ++i) + { + if(e == drcElements[i]) + { + drcElements.erase(drcElements.begin() + i); + break; + } + } + } + + void remove(GuiElement *e) + { + removeTv(e); + removeDrc(e); + } + void removeAll() + { + tvElements.clear(); + drcElements.clear(); + } + + void drawDrc(CVideo *video); + void drawTv(CVideo *video); + void update(GuiController *controller); + void updateEffects(); + + void process(); + + void lockGUI() + { + guiMutex.lock(); + } + void unlockGUI() + { + guiMutex.unlock(); + } + +private: + void SetupMainView(void); + + void OnOpenEffectFinish(GuiElement *element); + void OnCloseEffectFinish(GuiElement *element); + + int width, height; + std::vector drcElements; + std::vector tvElements; + + GuiSound *ClickSound; + + GuiMainWindowScreen * TvFrame; + GuiMainWindowScreen * DrcFrame; + + GuiImageData *pointerImgData[4]; + GuiImage *pointerImg[4]; + bool pointerValid[4]; + + CMutex guiMutex; +}; + +#endif //_MAIN_WINDOW_H_ diff --git a/src/menu/MainWindowTV.cpp b/src/menu/MainWindowTV.cpp new file mode 100644 index 0000000..68d0198 --- /dev/null +++ b/src/menu/MainWindowTV.cpp @@ -0,0 +1,236 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * Modified by Maschell, 2016 for GX2_GUI_Template + * + * 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 . + ****************************************************************************/ +#include "MainWindowTV.h" +#include "utils/logger.h" + +MainWindowTV::MainWindowTV(int w, int h) + : GuiMainWindowScreen(w, h) + , width(w) + , height(h) + ,bgImageColor(w, h, (GX2Color){ 0, 0, 0, 0 }) +{ + bgImageColor.setImageColor((GX2Color){ 248, 248, 249, 255 }, 0); + bgImageColor.setImageColor((GX2Color){ 248, 248, 249, 255 }, 1); + bgImageColor.setImageColor((GX2Color){ 248, 248, 249, 255 }, 2); + bgImageColor.setImageColor((GX2Color){ 248, 248, 249, 255 }, 3); + append(&bgImageColor); + + + + + wingSound = new GuiSound(Resources::GetFile("sfx_wing.ogg"), Resources::GetFileSize("sfx_wing.ogg")); + pointSound = new GuiSound(Resources::GetFile("sfx_point.ogg"), Resources::GetFileSize("sfx_point.ogg")); + swooshSound = new GuiSound(Resources::GetFile("sfx_swooshing.ogg"), Resources::GetFileSize("sfx_swooshing.ogg")); + dieSound = new GuiSound(Resources::GetFile("sfx_die.ogg"), Resources::GetFileSize("sfx_die.ogg")); + + // The below code will draw a pumpkin_pie.jpg mage from + // the /data folder when uncommented + splashImgData = Resources::GetImageData("splash.png"); + looseImgData = Resources::GetImageData("loose.png"); + + flappy_bird_frm[0] = Resources::GetImageData("flappy_bird_1.png"); + flappy_bird_frm[1] = Resources::GetImageData("flappy_bird_2.png"); + flappy_bird_frm[2] = Resources::GetImageData("flappy_bird_3.png"); + flappy_bird_frm[3] = Resources::GetImageData("flappy_bird_4.png"); + + splash = new SplashScreen(splashImgData); + //splash = new GuiImage(splashImgData); + flappy_bird = new GuiImage(flappy_bird_frm[0]); + + for (int i=0;i<4;i++) pipes[i] = new Pipe(150.0f+((float)i*320.0f)); + + bg = new Background("bg_back.png",0); + fg = new Background("bg_front.png",0); + + score_img = new ScoreImage(-54, 200); + + + + //splash->setAlignment(ALIGN_CENTER | ALIGN_CENTER); + flappy_bird->setAlignment(ALIGN_CENTER | ALIGN_CENTER); + + //splash->setPosition(0, 0); + flappy_bird->setPosition(-150, -5); + + append(bg); + append(flappy_bird); + for (int i=0;i<4;i++) append(pipes[i]); + append(fg); + append(splash); + + + // The below code wll draw "Hello World!" as a string + // opionally underneath the pie, if it is available + //const char* cpName = "Hello World!"; + //GuiText* hello = new GuiText(cpName, 28, glm::vec4(0, 0, 0, 1)); + //hello->setAlignment(ALIGN_RIGHT | ALIGN_CENTER); // start from midright + //hello->setPosition(-250, 0); // move the text left 200 from the right + //append(hello); +} + +MainWindowTV::~MainWindowTV() +{ + remove(&bgImageColor); + delete(wingSound); + delete(swooshSound); + delete(dieSound); + //delete(bg); + //for (int i=0;i<4;i++) delete pipes[i]; + //pipes = NULL; + //delete(fg); + delete(splash); + delete(flappy_bird); +} + +void MainWindowTV::draw(CVideo *v){ + GuiMainWindowScreen::draw(v); + //gets called on every frame for drawing +} + + +void MainWindowTV::update(GuiController * c){ + GuiMainWindowScreen::update(c); + //CONTROLLER UPDATE!!! + switch(game_state) { + case state_splash: //Start screen + if(c->data.buttons_d & VPAD_BUTTON_A || c->data.buttons_d & VPAD_BUTTON_B) { + splash->FadeExit(); + append(score_img); + for(int i=0;i<4;i++) pipes[i]->setScroll(true); + bg->setScrollSpeed(0.5f); + fg->setScrollSpeed(1.5f); + flappy_bird_velocity = jump; //Jump after start + wingSound->Stop(); + wingSound->Play(); + + game_state=state_ingame; + } + break; + case state_ingame: + if(c->data.buttons_d & VPAD_BUTTON_A || c->data.buttons_d & VPAD_BUTTON_B) { + flappy_bird_velocity = jump; + wingSound->Stop(); + wingSound->Play(); + } + break; + case state_gameover: + if(dieSound->IsPlaying() == false && (c->data.buttons_d & VPAD_BUTTON_A || c->data.buttons_d & VPAD_BUTTON_B)) { + flappy_bird_position=-5; + flappy_bird_rotation = 0.0f; + flappy_bird_velocity = 0.0f; + flappy_bird->setPosition(-150, -5); + flappy_bird->setAngle(0.0f); + + score=0; + score_img->setScore(score); + + for (int i=0;i<4;i++) pipes[i]->setPosX(150.0f+((float)i*320.0f)); + + splash->setSplashImageData(splashImgData); + splash->FadeEnter(); + swooshSound->Stop(); + swooshSound->Play(); + game_state=state_splash; + } + break; + default: + break; + } + +} + +void MainWindowTV::process(){ + GuiMainWindowScreen::process(); + if (game_state!=2) { //If not game over + if (++flappy_bird_change_skip==6) { //Animate picture + flappy_bird_change_skip=0; + if (++flappy_bird_curr_frame==4) flappy_bird_curr_frame=0; + flappy_bird->setImageData(flappy_bird_frm[flappy_bird_curr_frame]); + } + } + + switch(game_state) { + case state_ingame: + flappy_bird_velocity += gravity; + flappy_bird_position -= flappy_bird_velocity; + + if(flappy_bird_position<-224) flappy_bird_position=-224; + if(flappy_bird_position>328) flappy_bird_position=328; + + flappy_bird->setPosition(-150, (int)flappy_bird_position); + if ((((float)flappy_bird_velocity / 10.0f) * 90.0f)<90.0f) flappy_bird_rotation = (((float)flappy_bird_velocity / 10.0f) * 90.0f); + else flappy_bird_rotation = 90.0f; + flappy_bird->setAngle(flappy_bird_rotation); + + for (int i=0;i<4;i++) { + collision_state[i]=pipes[i]->checkCollision(flappy_bird); + if(collision_state[i]!=0) { + if(collision_state[i]==-1) { + //Add point + score_img->setScore(++score); + pointSound->Stop(); + pointSound->Play(); + } + if(collision_state[i]==1) { + bg->setScrollSpeed(0.0f); + fg->setScrollSpeed(0.0f); + for(int i=0;i<4;i++) pipes[i]->setScroll(false); + dieSound->Stop(); + dieSound->Play(); + game_state=state_collided; + } + } + } + if (flappy_bird_position<-220) game_state=state_die; + break; + case state_collided: //is dying from a pipe: go down by gravity + flappy_bird_velocity += gravity; + flappy_bird_position -= flappy_bird_velocity; + + if(flappy_bird_position<-224) flappy_bird_position=-224; + if(flappy_bird_position>328) flappy_bird_position=328; + + flappy_bird->setPosition(-150, (int)flappy_bird_position); + if ((((float)flappy_bird_velocity / 10.0f) * 90.0f)<90.0f) flappy_bird_rotation = (((float)flappy_bird_velocity / 10.0f) * 90.0f); + else flappy_bird_rotation = 90.0f; + flappy_bird->setAngle(flappy_bird_rotation); + + if (flappy_bird_position<-220) game_state=state_show_gameover; + break; + case state_show_gameover: //IsDying + if(dieSound->IsPlaying() == false) { + swooshSound->Stop(); + swooshSound->Play(); + splash->setSplashImageData(looseImgData); + splash->FadeEnter(); + remove(score_img); + game_state=state_gameover; + } + break; + case state_die: //Die + bg->setScrollSpeed(0.0f); + fg->setScrollSpeed(0.0f); + for(int i=0;i<4;i++) pipes[i]->setScroll(false); + dieSound->Stop(); + dieSound->Play(); + game_state=state_show_gameover; + break; + default: + break; + } +} diff --git a/src/menu/MainWindowTV.h b/src/menu/MainWindowTV.h new file mode 100644 index 0000000..4056af2 --- /dev/null +++ b/src/menu/MainWindowTV.h @@ -0,0 +1,94 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * Modified by Maschell, 2016 for GX2_GUI_Template + * + * 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 . + ****************************************************************************/ +#ifndef _MAIN_WINDOW_TV_H_ +#define _MAIN_WINDOW_TV_H_ + +#include "gui/Gui.h" +#include "gui/GuiMainWindowScreen.h" +#include "gui/VPadController.h" +#include "game/Pipe.h" +#include "game/Background.h" +#include "game/ScoreImage.h" +#include "game/SplashScreen.h" + +#define state_splash 0 +#define state_ingame 1 +#define state_gameover 2 +#define state_die 5 +#define state_collided 3 +#define state_show_gameover 4 + +class CVideo; + +class MainWindowTV : public GuiMainWindowScreen{ +public: + MainWindowTV(int w, int h); + virtual ~MainWindowTV(); +private: + int width, height; + + GuiImage bgImageColor; + + GuiSound *wingSound; + GuiSound *pointSound; + GuiSound *swooshSound; + GuiSound *dieSound; + + GuiImageData* bgImgData; + GuiImageData* fgImgData; + GuiImageData* splashImgData; + GuiImageData* looseImgData; + + Background* bg; + Background* fg; + //GuiImage* splash; //Splash screen + SplashScreen* splash; + + ScoreImage *score_img; + int score=0; + + Pipe* pipes[4]; + int collision_state[4]; + + int bg_offset=0; + int fg_offset=0; + + GuiImageData *flappy_bird_frm[4]; + + GuiImage* flappy_bird; + + int flappy_bird_change_skip=0; + int flappy_bird_curr_frame=0; + + + int game_state=0; //0=start, 1=in-game, 2=game over + int set_gameover=0; + + #define gravity 0.25f + #define jump -4.6f + + float flappy_bird_position=-5.0f; + float flappy_bird_velocity = 0.0f; + float flappy_bird_rotation = 0.0f; + + void draw(CVideo *v); + void update(GuiController * c); + void process(); +}; + +#endif //_MAIN_WINDOW_TV_H_ diff --git a/src/resources/Resources.cpp b/src/resources/Resources.cpp new file mode 100644 index 0000000..eabee60 --- /dev/null +++ b/src/resources/Resources.cpp @@ -0,0 +1,189 @@ +#include +#include +#include +#include "Resources.h" +#include "filelist.h" +#include "system/AsyncDeleter.h" +#include "fs/fs_utils.h" +#include "gui/GuiImageAsync.h" +#include "gui/GuiSound.h" + +Resources * Resources::instance = NULL; + +void Resources::Clear() +{ + for(int i = 0; RecourceList[i].filename != NULL; ++i) + { + if(RecourceList[i].CustomFile) + { + free(RecourceList[i].CustomFile); + RecourceList[i].CustomFile = NULL; + } + + if(RecourceList[i].CustomFileSize != 0) + RecourceList[i].CustomFileSize = 0; + } + + if(instance) + delete instance; + + instance = NULL; +} + +bool Resources::LoadFiles(const char * path) +{ + if(!path) + return false; + + bool result = false; + Clear(); + + for(int i = 0; RecourceList[i].filename != NULL; ++i) + { + std::string fullpath(path); + fullpath += "/"; + fullpath += RecourceList[i].filename; + + u8 * buffer = NULL; + u32 filesize = 0; + + LoadFileToMem(fullpath.c_str(), &buffer, &filesize); + + RecourceList[i].CustomFile = buffer; + RecourceList[i].CustomFileSize = (u32) filesize; + result |= (buffer != 0); + } + + return result; +} + +const u8 * Resources::GetFile(const char * filename) +{ + for(int i = 0; RecourceList[i].filename != NULL; ++i) + { + if(strcasecmp(filename, RecourceList[i].filename) == 0) + { + return (RecourceList[i].CustomFile ? RecourceList[i].CustomFile : RecourceList[i].DefaultFile); + } + } + + return NULL; +} + +u32 Resources::GetFileSize(const char * filename) +{ + for(int i = 0; RecourceList[i].filename != NULL; ++i) + { + if(strcasecmp(filename, RecourceList[i].filename) == 0) + { + return (RecourceList[i].CustomFile ? RecourceList[i].CustomFileSize : RecourceList[i].DefaultFileSize); + } + } + return 0; +} + +GuiImageData * Resources::GetImageData(const char * filename) +{ + if(!instance) + instance = new Resources; + + std::map >::iterator itr = instance->imageDataMap.find(std::string(filename)); + if(itr != instance->imageDataMap.end()) + { + itr->second.first++; + return itr->second.second; + } + + for(int i = 0; RecourceList[i].filename != NULL; ++i) + { + if(strcasecmp(filename, RecourceList[i].filename) == 0) + { + const u8 * buff = RecourceList[i].CustomFile ? RecourceList[i].CustomFile : RecourceList[i].DefaultFile; + const u32 size = RecourceList[i].CustomFile ? RecourceList[i].CustomFileSize : RecourceList[i].DefaultFileSize; + + if(buff == NULL) + return NULL; + + GuiImageData * image = new GuiImageData(buff, size); + instance->imageDataMap[std::string(filename)].first = 1; + instance->imageDataMap[std::string(filename)].second = image; + + return image; + } + } + + return NULL; +} + +void Resources::RemoveImageData(GuiImageData * image) +{ + std::map >::iterator itr; + + for(itr = instance->imageDataMap.begin(); itr != instance->imageDataMap.end(); itr++) + { + if(itr->second.second == image) + { + itr->second.first--; + + if(itr->second.first == 0) + { + AsyncDeleter::pushForDelete( itr->second.second ); + instance->imageDataMap.erase(itr); + } + break; + } + } +} + +GuiSound * Resources::GetSound(const char * filename) +{ + if(!instance) + instance = new Resources; + + std::map >::iterator itr = instance->soundDataMap.find(std::string(filename)); + if(itr != instance->soundDataMap.end()) + { + itr->second.first++; + return itr->second.second; + } + + for(int i = 0; RecourceList[i].filename != NULL; ++i) + { + if(strcasecmp(filename, RecourceList[i].filename) == 0) + { + const u8 * buff = RecourceList[i].CustomFile ? RecourceList[i].CustomFile : RecourceList[i].DefaultFile; + const u32 size = RecourceList[i].CustomFile ? RecourceList[i].CustomFileSize : RecourceList[i].DefaultFileSize; + + if(buff == NULL) + return NULL; + + GuiSound * sound = new GuiSound(buff, size); + instance->soundDataMap[std::string(filename)].first = 1; + instance->soundDataMap[std::string(filename)].second = sound; + + return sound; + } + } + + return NULL; +} + +void Resources::RemoveSound(GuiSound * sound) +{ + std::map >::iterator itr; + + for(itr = instance->soundDataMap.begin(); itr != instance->soundDataMap.end(); itr++) + { + if(itr->second.second == sound) + { + itr->second.first--; + + if(itr->second.first == 0) + { + AsyncDeleter::pushForDelete( itr->second.second ); + instance->soundDataMap.erase(itr); + } + break; + } + } +} diff --git a/src/resources/Resources.h b/src/resources/Resources.h new file mode 100644 index 0000000..3d0921b --- /dev/null +++ b/src/resources/Resources.h @@ -0,0 +1,34 @@ +#ifndef RECOURCES_H_ +#define RECOURCES_H_ + + +#include + +//! forward declaration +class GuiImageData; +class GuiSound; + +class Resources +{ +public: + static void Clear(); + static bool LoadFiles(const char * path); + static const u8 * GetFile(const char * filename); + static u32 GetFileSize(const char * filename); + + static GuiImageData * GetImageData(const char * filename); + static void RemoveImageData(GuiImageData * image); + + static GuiSound * GetSound(const char * filename); + static void RemoveSound(GuiSound * sound); +private: + static Resources *instance; + + Resources() {} + ~Resources() {} + + std::map > imageDataMap; + std::map > soundDataMap; +}; + +#endif diff --git a/src/resources/filelist.h b/src/resources/filelist.h new file mode 100644 index 0000000..c5646f3 --- /dev/null +++ b/src/resources/filelist.h @@ -0,0 +1,140 @@ +/**************************************************************************** + * Loadiine resource files. + * This file is generated automatically. + * Includes 28 files. + * + * NOTE: + * Any manual modification of this file will be overwriten by the generation. + ****************************************************************************/ +#ifndef _FILELIST_H_ +#define _FILELIST_H_ + +#include + +typedef struct _RecourceFile +{ + const char *filename; + const u8 *DefaultFile; + const u32 &DefaultFileSize; + u8 *CustomFile; + u32 CustomFileSize; +} RecourceFile; + +extern const u8 bg_back_png[]; +extern const u32 bg_back_png_size; + +extern const u8 bg_front_png[]; +extern const u32 bg_front_png_size; + +extern const u8 bgMusic_ogg[]; +extern const u32 bgMusic_ogg_size; + +extern const u8 button_click_mp3[]; +extern const u32 button_click_mp3_size; + +extern const u8 flappy_bird_1_png[]; +extern const u32 flappy_bird_1_png_size; + +extern const u8 flappy_bird_2_png[]; +extern const u32 flappy_bird_2_png_size; + +extern const u8 flappy_bird_3_png[]; +extern const u32 flappy_bird_3_png_size; + +extern const u8 flappy_bird_4_png[]; +extern const u32 flappy_bird_4_png_size; + +extern const u8 font_big_0_png[]; +extern const u32 font_big_0_png_size; + +extern const u8 font_big_1_png[]; +extern const u32 font_big_1_png_size; + +extern const u8 font_big_2_png[]; +extern const u32 font_big_2_png_size; + +extern const u8 font_big_3_png[]; +extern const u32 font_big_3_png_size; + +extern const u8 font_big_4_png[]; +extern const u32 font_big_4_png_size; + +extern const u8 font_big_5_png[]; +extern const u32 font_big_5_png_size; + +extern const u8 font_big_6_png[]; +extern const u32 font_big_6_png_size; + +extern const u8 font_big_7_png[]; +extern const u32 font_big_7_png_size; + +extern const u8 font_big_8_png[]; +extern const u32 font_big_8_png_size; + +extern const u8 font_big_9_png[]; +extern const u32 font_big_9_png_size; + +extern const u8 font_big_null_png[]; +extern const u32 font_big_null_png_size; + +extern const u8 font_ttf[]; +extern const u32 font_ttf_size; + +extern const u8 loose_png[]; +extern const u32 loose_png_size; + +extern const u8 pipe_down_png[]; +extern const u32 pipe_down_png_size; + +extern const u8 pipe_up_png[]; +extern const u32 pipe_up_png_size; + +extern const u8 sfx_die_ogg[]; +extern const u32 sfx_die_ogg_size; + +extern const u8 sfx_point_ogg[]; +extern const u32 sfx_point_ogg_size; + +extern const u8 sfx_swooshing_ogg[]; +extern const u32 sfx_swooshing_ogg_size; + +extern const u8 sfx_wing_ogg[]; +extern const u32 sfx_wing_ogg_size; + +extern const u8 splash_png[]; +extern const u32 splash_png_size; + +static RecourceFile RecourceList[] = +{ + {"bg_back.png", bg_back_png, bg_back_png_size, NULL, 0}, + {"bg_front.png", bg_front_png, bg_front_png_size, NULL, 0}, + {"bgMusic.ogg", bgMusic_ogg, bgMusic_ogg_size, NULL, 0}, + {"button_click.mp3", button_click_mp3, button_click_mp3_size, NULL, 0}, + {"flappy_bird_1.png", flappy_bird_1_png, flappy_bird_1_png_size, NULL, 0}, + {"flappy_bird_2.png", flappy_bird_2_png, flappy_bird_2_png_size, NULL, 0}, + {"flappy_bird_3.png", flappy_bird_3_png, flappy_bird_3_png_size, NULL, 0}, + {"flappy_bird_4.png", flappy_bird_4_png, flappy_bird_4_png_size, NULL, 0}, + {"font_big_0.png", font_big_0_png, font_big_0_png_size, NULL, 0}, + {"font_big_1.png", font_big_1_png, font_big_1_png_size, NULL, 0}, + {"font_big_2.png", font_big_2_png, font_big_2_png_size, NULL, 0}, + {"font_big_3.png", font_big_3_png, font_big_3_png_size, NULL, 0}, + {"font_big_4.png", font_big_4_png, font_big_4_png_size, NULL, 0}, + {"font_big_5.png", font_big_5_png, font_big_5_png_size, NULL, 0}, + {"font_big_6.png", font_big_6_png, font_big_6_png_size, NULL, 0}, + {"font_big_7.png", font_big_7_png, font_big_7_png_size, NULL, 0}, + {"font_big_8.png", font_big_8_png, font_big_8_png_size, NULL, 0}, + {"font_big_9.png", font_big_9_png, font_big_9_png_size, NULL, 0}, + {"font_big_null.png", font_big_null_png, font_big_null_png_size, NULL, 0}, + {"font.ttf", font_ttf, font_ttf_size, NULL, 0}, + {"loose.png", loose_png, loose_png_size, NULL, 0}, + {"pipe_down.png", pipe_down_png, pipe_down_png_size, NULL, 0}, + {"pipe_up.png", pipe_up_png, pipe_up_png_size, NULL, 0}, + {"sfx_die.ogg", sfx_die_ogg, sfx_die_ogg_size, NULL, 0}, + {"sfx_point.ogg", sfx_point_ogg, sfx_point_ogg_size, NULL, 0}, + {"sfx_swooshing.ogg", sfx_swooshing_ogg, sfx_swooshing_ogg_size, NULL, 0}, + {"sfx_wing.ogg", sfx_wing_ogg, sfx_wing_ogg_size, NULL, 0}, + {"splash.png", splash_png, splash_png_size, NULL, 0}, + {NULL, NULL, 0, NULL, 0} +}; + +#endif diff --git a/src/sounds/BufferCircle.cpp b/src/sounds/BufferCircle.cpp new file mode 100644 index 0000000..b0ee705 --- /dev/null +++ b/src/sounds/BufferCircle.cpp @@ -0,0 +1,142 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include "utils/utils.h" +#include "BufferCircle.hpp" + +BufferCircle::BufferCircle() +{ + which = 0; + BufferBlockSize = 0; +} + +BufferCircle::~BufferCircle() +{ + FreeBuffer(); + SoundBuffer.clear(); + BufferSize.clear(); + BufferReady.clear(); +} + +void BufferCircle::SetBufferBlockSize(int size) +{ + if(size < 0) + return; + + BufferBlockSize = size; + + for(int i = 0; i < Size(); i++) + { + if(SoundBuffer[i] != NULL) + free(SoundBuffer[i]); + + SoundBuffer[i] = (u8 *) memalign(32, ALIGN32(BufferBlockSize)); + BufferSize[i] = 0; + BufferReady[i] = false; + } +} + +void BufferCircle::Resize(int size) +{ + while(size < Size()) + RemoveBuffer(Size()-1); + + int oldSize = Size(); + + SoundBuffer.resize(size); + BufferSize.resize(size); + BufferReady.resize(size); + + for(int i = oldSize; i < Size(); i++) + { + if(BufferBlockSize > 0) + SoundBuffer[i] = (u8 *) memalign(32, ALIGN32(BufferBlockSize)); + else + SoundBuffer[i] = NULL; + BufferSize[i] = 0; + BufferReady[i] = false; + } +} + +void BufferCircle::RemoveBuffer(int pos) +{ + if(!Valid(pos)) + return; + + if(SoundBuffer[pos] != NULL) + free(SoundBuffer[pos]); + + SoundBuffer.erase(SoundBuffer.begin()+pos); + BufferSize.erase(BufferSize.begin()+pos); + BufferReady.erase(BufferReady.begin()+pos); +} + +void BufferCircle::ClearBuffer() +{ + for(int i = 0; i < Size(); i++) + { + BufferSize[i] = 0; + BufferReady[i] = false; + } + which = 0; +} + +void BufferCircle::FreeBuffer() +{ + for(int i = 0; i < Size(); i++) + { + if(SoundBuffer[i] != NULL) + free(SoundBuffer[i]); + + SoundBuffer[i] = NULL; + BufferSize[i] = 0; + BufferReady[i] = false; + } +} + +void BufferCircle::LoadNext() +{ + BufferReady[which] = false; + BufferSize[which] = 0; + + which = Next(); +} + +void BufferCircle::SetBufferReady(int pos, bool state) +{ + if(!Valid(pos)) + return; + + BufferReady[pos] = state; +} + +void BufferCircle::SetBufferSize(int pos, int size) +{ + if(!Valid(pos)) + return; + + BufferSize[pos] = size; +} diff --git a/src/sounds/BufferCircle.hpp b/src/sounds/BufferCircle.hpp new file mode 100644 index 0000000..b07c1c4 --- /dev/null +++ b/src/sounds/BufferCircle.hpp @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#ifndef BUFFER_CIRCLE_HPP_ +#define BUFFER_CIRCLE_HPP_ + +#include +#include + +class BufferCircle +{ + public: + //!> Constructor + BufferCircle(); + //!> Destructor + ~BufferCircle(); + //!> Set circle size + void Resize(int size); + //!> Get the circle size + int Size() { return SoundBuffer.size(); }; + //!> Set/resize the buffer size + void SetBufferBlockSize(int size); + //!> Remove a buffer + void RemoveBuffer(int pos); + //!> Set all buffers clear + void ClearBuffer(); + //!> Free all buffers + void FreeBuffer(); + //!> Switch to next buffer + void LoadNext(); + //!> Get the current buffer + u8 * GetBuffer() { return GetBuffer(which); }; + //!> Get a buffer at a position + u8 * GetBuffer(int pos) { if(!Valid(pos)) return NULL; else return SoundBuffer[pos]; }; + //!> Get current buffer size + u32 GetBufferSize() { return GetBufferSize(which); }; + //!> Get buffer size at position + u32 GetBufferSize(int pos) { if(!Valid(pos)) return 0; else return BufferSize[pos]; }; + //!> Is current buffer ready + bool IsBufferReady() { return IsBufferReady(which); }; + //!> Is a buffer at a position ready + bool IsBufferReady(int pos) { if(!Valid(pos)) return false; else return BufferReady[pos]; }; + //!> Set a buffer at a position to a ready state + void SetBufferReady(int pos, bool st); + //!> Set the buffersize at a position + void SetBufferSize(int pos, int size); + //!> Get the current position in the circle + u16 Which() { return which; }; + + //!> Get the next location + inline u16 Next() { return (which+1 >= Size()) ? 0 : which+1; } + inline u16 Prev() { if(Size() == 0) return 0; else return ((int)which-1 < 0) ? Size()-1 : which-1; } + protected: + //!> Check if the position is a valid position in the vector + bool Valid(int pos) { return !(pos < 0 || pos >= Size()); }; + + u16 which; + u32 BufferBlockSize; + std::vector SoundBuffer; + std::vector BufferSize; + std::vector BufferReady; +}; + +#endif diff --git a/src/sounds/Mp3Decoder.cpp b/src/sounds/Mp3Decoder.cpp new file mode 100644 index 0000000..1246b4a --- /dev/null +++ b/src/sounds/Mp3Decoder.cpp @@ -0,0 +1,217 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "dynamic_libs/os_functions.h" +#include "Mp3Decoder.hpp" + +Mp3Decoder::Mp3Decoder(const char * filepath) + : SoundDecoder(filepath) +{ + SoundType = SOUND_MP3; + ReadBuffer = NULL; + mad_timer_reset(&Timer); + mad_stream_init(&Stream); + mad_frame_init(&Frame); + mad_synth_init(&Synth); + + if(!file_fd) + return; + + OpenFile(); +} + +Mp3Decoder::Mp3Decoder(const u8 * snd, int len) + : SoundDecoder(snd, len) +{ + SoundType = SOUND_MP3; + ReadBuffer = NULL; + mad_timer_reset(&Timer); + mad_stream_init(&Stream); + mad_frame_init(&Frame); + mad_synth_init(&Synth); + + if(!file_fd) + return; + + OpenFile(); +} + +Mp3Decoder::~Mp3Decoder() +{ + ExitRequested = true; + while(Decoding) + usleep(100); + + mad_synth_finish(&Synth); + mad_frame_finish(&Frame); + mad_stream_finish(&Stream); + + if(ReadBuffer) + free(ReadBuffer); + ReadBuffer = NULL; +} + +void Mp3Decoder::OpenFile() +{ + GuardPtr = NULL; + ReadBuffer = (u8 *) memalign(32, SoundBlockSize*SoundBlocks); + if(!ReadBuffer) + { + if(file_fd) + delete file_fd; + file_fd = NULL; + return; + } + + u8 dummybuff[4096]; + int ret = Read(dummybuff, 4096, 0); + if(ret <= 0) + { + if(file_fd) + delete file_fd; + file_fd = NULL; + return; + } + + SampleRate = (u32) Frame.header.samplerate; + Format = ((MAD_NCHANNELS(&Frame.header) == 2) ? (FORMAT_PCM_16_BIT | CHANNELS_STEREO) : (FORMAT_PCM_16_BIT | CHANNELS_MONO)); + Rewind(); +} + +int Mp3Decoder::Rewind() +{ + mad_synth_finish(&Synth); + mad_frame_finish(&Frame); + mad_stream_finish(&Stream); + mad_timer_reset(&Timer); + mad_stream_init(&Stream); + mad_frame_init(&Frame); + mad_synth_init(&Synth); + SynthPos = 0; + GuardPtr = NULL; + + if(!file_fd) + return -1; + + return SoundDecoder::Rewind(); +} + +static inline s16 FixedToShort(mad_fixed_t Fixed) +{ + /* Clipping */ + if(Fixed>=MAD_F_ONE) + return(SHRT_MAX); + if(Fixed<=-MAD_F_ONE) + return(-SHRT_MAX); + + Fixed=Fixed>>(MAD_F_FRACBITS-15); + return((s16)Fixed); +} + +int Mp3Decoder::Read(u8 * buffer, int buffer_size, int pos) +{ + if(!file_fd) + return -1; + + if(Format == (FORMAT_PCM_16_BIT | CHANNELS_STEREO)) + buffer_size &= ~0x0003; + else + buffer_size &= ~0x0001; + + u8 * write_pos = buffer; + u8 * write_end = buffer+buffer_size; + + while(1) + { + while(SynthPos < Synth.pcm.length) + { + if(write_pos >= write_end) + return write_pos-buffer; + + *((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[0][SynthPos]); + write_pos += 2; + + if(MAD_NCHANNELS(&Frame.header) == 2) + { + *((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[1][SynthPos]); + write_pos += 2; + } + SynthPos++; + } + + if(Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN) + { + u8 * ReadStart = ReadBuffer; + int ReadSize = SoundBlockSize*SoundBlocks; + int Remaining = 0; + + if(Stream.next_frame != NULL) + { + Remaining = Stream.bufend - Stream.next_frame; + memmove(ReadBuffer, Stream.next_frame, Remaining); + ReadStart += Remaining; + ReadSize -= Remaining; + } + + ReadSize = file_fd->read(ReadStart, ReadSize); + if(ReadSize <= 0) + { + GuardPtr = ReadStart; + memset(GuardPtr, 0, MAD_BUFFER_GUARD); + ReadSize = MAD_BUFFER_GUARD; + } + + CurPos += ReadSize; + mad_stream_buffer(&Stream, ReadBuffer, Remaining+ReadSize); + } + + if(mad_frame_decode(&Frame,&Stream)) + { + if(MAD_RECOVERABLE(Stream.error)) + { + if(Stream.error != MAD_ERROR_LOSTSYNC || !GuardPtr) + continue; + } + else + { + if(Stream.error != MAD_ERROR_BUFLEN) + return -1; + else if(Stream.error == MAD_ERROR_BUFLEN && GuardPtr) + return -1; + } + } + + mad_timer_add(&Timer,Frame.header.duration); + mad_synth_frame(&Synth,&Frame); + SynthPos = 0; + } + return 0; +} diff --git a/src/sounds/Mp3Decoder.hpp b/src/sounds/Mp3Decoder.hpp new file mode 100644 index 0000000..ccc437b --- /dev/null +++ b/src/sounds/Mp3Decoder.hpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include + +#include "SoundDecoder.hpp" + +class Mp3Decoder : public SoundDecoder +{ + public: + Mp3Decoder(const char * filepath); + Mp3Decoder(const u8 * sound, int len); + virtual ~Mp3Decoder(); + int Rewind(); + int Read(u8 * buffer, int buffer_size, int pos); + protected: + void OpenFile(); + struct mad_stream Stream; + struct mad_frame Frame; + struct mad_synth Synth; + mad_timer_t Timer; + u8 * GuardPtr; + u8 * ReadBuffer; + u32 SynthPos; +}; diff --git a/src/sounds/OggDecoder.cpp b/src/sounds/OggDecoder.cpp new file mode 100644 index 0000000..abb64f4 --- /dev/null +++ b/src/sounds/OggDecoder.cpp @@ -0,0 +1,138 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include +#include "dynamic_libs/os_functions.h" +#include "OggDecoder.hpp" + +static int ogg_read(void * punt, int bytes, int blocks, int *f) +{ + return ((CFile *) f)->read((u8 *) punt, bytes*blocks); +} + +static int ogg_seek(int *f, ogg_int64_t offset, int mode) +{ + return ((CFile *) f)->seek((u64) offset, mode); +} + +static int ogg_close(int *f) +{ + ((CFile *) f)->close(); + return 0; +} + +static long ogg_tell(int *f) +{ + return (long) ((CFile *) f)->tell(); +} + +static ov_callbacks callbacks = { + (size_t (*)(void *, size_t, size_t, void *)) ogg_read, + (int (*)(void *, ogg_int64_t, int)) ogg_seek, + (int (*)(void *)) ogg_close, + (long (*)(void *)) ogg_tell +}; + +OggDecoder::OggDecoder(const char * filepath) + : SoundDecoder(filepath) +{ + SoundType = SOUND_OGG; + + if(!file_fd) + return; + + OpenFile(); +} + +OggDecoder::OggDecoder(const u8 * snd, int len) + : SoundDecoder(snd, len) +{ + SoundType = SOUND_OGG; + + if(!file_fd) + return; + + OpenFile(); +} + +OggDecoder::~OggDecoder() +{ + ExitRequested = true; + while(Decoding) + usleep(100); + + if(file_fd) + ov_clear(&ogg_file); +} + +void OggDecoder::OpenFile() +{ + if (ov_open_callbacks(file_fd, &ogg_file, NULL, 0, callbacks) < 0) + { + delete file_fd; + file_fd = NULL; + return; + } + + ogg_info = ov_info(&ogg_file, -1); + if(!ogg_info) + { + ov_clear(&ogg_file); + delete file_fd; + file_fd = NULL; + return; + } + + Format = ((ogg_info->channels == 2) ? (FORMAT_PCM_16_BIT | CHANNELS_STEREO) : (FORMAT_PCM_16_BIT | CHANNELS_MONO)); + SampleRate = ogg_info->rate; +} + +int OggDecoder::Rewind() +{ + if(!file_fd) + return -1; + + int ret = ov_time_seek(&ogg_file, 0); + CurPos = 0; + EndOfFile = false; + + return ret; +} + +int OggDecoder::Read(u8 * buffer, int buffer_size, int pos) +{ + if(!file_fd) + return -1; + + int bitstream = 0; + + int read = ov_read(&ogg_file, (char *) buffer, buffer_size, &bitstream); + + if(read > 0) + CurPos += read; + + return read; +} diff --git a/src/sounds/OggDecoder.hpp b/src/sounds/OggDecoder.hpp new file mode 100644 index 0000000..8dc568e --- /dev/null +++ b/src/sounds/OggDecoder.hpp @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include + +#include "SoundDecoder.hpp" + +class OggDecoder : public SoundDecoder +{ + public: + OggDecoder(const char * filepath); + OggDecoder(const u8 * snd, int len); + virtual ~OggDecoder(); + int Rewind(); + int Read(u8 * buffer, int buffer_size, int pos); + protected: + void OpenFile(); + OggVorbis_File ogg_file; + vorbis_info *ogg_info; +}; diff --git a/src/sounds/SoundDecoder.cpp b/src/sounds/SoundDecoder.cpp new file mode 100644 index 0000000..e449170 --- /dev/null +++ b/src/sounds/SoundDecoder.cpp @@ -0,0 +1,225 @@ +/**************************************************************************** + * Copyright (C) 2009-2013 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include +#include +#include +#include "dynamic_libs/os_functions.h" +#include "SoundDecoder.hpp" + +static const u32 FixedPointShift = 15; +static const u32 FixedPointScale = 1 << FixedPointShift; + +SoundDecoder::SoundDecoder() +{ + file_fd = NULL; + Init(); +} + +SoundDecoder::SoundDecoder(const std::string & filepath) +{ + file_fd = new CFile(filepath, CFile::ReadOnly); + Init(); +} + +SoundDecoder::SoundDecoder(const u8 * buffer, int size) +{ + file_fd = new CFile(buffer, size); + Init(); +} + +SoundDecoder::~SoundDecoder() +{ + ExitRequested = true; + while(Decoding) + usleep(1000); + + //! lock unlock once to make sure it's really not decoding + Lock(); + Unlock(); + + if(file_fd) + delete file_fd; + file_fd = NULL; + + if(ResampleBuffer) + free(ResampleBuffer); +} + +void SoundDecoder::Init() +{ + SoundType = SOUND_RAW; + SoundBlocks = 8; + SoundBlockSize = 0x4000; + ResampleTo48kHz = false; + CurPos = 0; + whichLoad = 0; + Loop = false; + EndOfFile = false; + Decoding = false; + ExitRequested = false; + SoundBuffer.SetBufferBlockSize(SoundBlockSize); + SoundBuffer.Resize(SoundBlocks); + ResampleBuffer = NULL; + ResampleRatio = 0; +} + +int SoundDecoder::Rewind() +{ + CurPos = 0; + EndOfFile = false; + file_fd->rewind(); + + return 0; +} + +int SoundDecoder::Read(u8 * buffer, int buffer_size, int pos) +{ + int ret = file_fd->read(buffer, buffer_size); + CurPos += ret; + + return ret; +} + +void SoundDecoder::EnableUpsample(void) +{ + if( (ResampleBuffer == NULL) + && IsStereo() && Is16Bit() + && SampleRate != 32000 + && SampleRate != 48000) + { + ResampleBuffer = (u8*)memalign(32, SoundBlockSize); + ResampleRatio = ( FixedPointScale * SampleRate ) / 48000; + SoundBlockSize = ( SoundBlockSize * ResampleRatio ) / FixedPointScale; + SoundBlockSize &= ~0x03; + // set new sample rate + SampleRate = 48000; + } +} + +void SoundDecoder::Upsample(s16 *src, s16 *dst, u32 nr_src_samples, u32 nr_dst_samples) +{ + int timer = 0; + + for(u32 i = 0, n = 0; i < nr_dst_samples; i += 2) + { + if((n+3) < nr_src_samples) { + // simple fixed point linear interpolation + dst[i] = src[n] + ( ((src[n+2] - src[n] ) * timer) >> FixedPointShift ); + dst[i+1] = src[n+1] + ( ((src[n+3] - src[n+1]) * timer) >> FixedPointShift ); + } + else { + dst[i] = src[n]; + dst[i+1] = src[n+1]; + } + + timer += ResampleRatio; + + if(timer >= (int)FixedPointScale) { + n += 2; + timer -= FixedPointScale; + } + } +} + +void SoundDecoder::Decode() +{ + if(!file_fd || ExitRequested || EndOfFile) + return; + + // check if we are not at the pre-last buffer (last buffer is playing) + u16 whichPlaying = SoundBuffer.Which(); + if( ((whichPlaying == 0) && (whichLoad == SoundBuffer.Size()-2)) + || ((whichPlaying == 1) && (whichLoad == SoundBuffer.Size()-1)) + || (whichLoad == (whichPlaying-2))) + { + return; + } + + Decoding = true; + + int done = 0; + u8 * write_buf = SoundBuffer.GetBuffer(whichLoad); + if(!write_buf) + { + ExitRequested = true; + Decoding = false; + return; + } + + if(ResampleTo48kHz && !ResampleBuffer) + EnableUpsample(); + + while(done < SoundBlockSize) + { + int ret = Read(&write_buf[done], SoundBlockSize-done, Tell()); + + if(ret <= 0) + { + if(Loop) + { + Rewind(); + continue; + } + else + { + EndOfFile = true; + break; + } + } + + done += ret; + } + + if(done > 0) + { + // check if we need to resample + if(ResampleBuffer && ResampleRatio) + { + memcpy(ResampleBuffer, write_buf, done); + + int src_samples = done >> 1; + int dest_samples = ( src_samples * FixedPointScale ) / ResampleRatio; + dest_samples &= ~0x01; + Upsample((s16*)ResampleBuffer, (s16*)write_buf, src_samples, dest_samples); + done = dest_samples << 1; + } + + //! TODO: remove this later and add STEREO support with two voices, for now we convert to MONO + if(IsStereo()) + { + s16* monoBuf = (s16*)write_buf; + done = done >> 1; + + for(int i = 0; i < done; i++) + monoBuf[i] = monoBuf[i << 1]; + } + + DCFlushRange(write_buf, done); + SoundBuffer.SetBufferSize(whichLoad, done); + SoundBuffer.SetBufferReady(whichLoad, true); + if(++whichLoad >= SoundBuffer.Size()) + whichLoad = 0; + } + + // check if next in queue needs to be filled as well and do so + if(!SoundBuffer.IsBufferReady(whichLoad)) + Decode(); + + Decoding = false; +} + diff --git a/src/sounds/SoundDecoder.hpp b/src/sounds/SoundDecoder.hpp new file mode 100644 index 0000000..c0c9da1 --- /dev/null +++ b/src/sounds/SoundDecoder.hpp @@ -0,0 +1,105 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#ifndef SOUND_DECODER_HPP +#define SOUND_DECODER_HPP + +#include "fs/CFile.hpp" +#include "system/CMutex.h" +#include "BufferCircle.hpp" + +class SoundDecoder +{ +public: + SoundDecoder(); + SoundDecoder(const std::string & filepath); + SoundDecoder(const u8 * buffer, int size); + virtual ~SoundDecoder(); + virtual void Lock() { mutex.lock(); } + virtual void Unlock() { mutex.unlock(); } + virtual int Read(u8 * buffer, int buffer_size, int pos); + virtual int Tell() { return CurPos; } + virtual int Seek(int pos) { CurPos = pos; return file_fd->seek(CurPos, SEEK_SET); } + virtual int Rewind(); + virtual u16 GetFormat() { return Format; } + virtual u16 GetSampleRate() { return SampleRate; } + virtual void Decode(); + virtual bool IsBufferReady() { return SoundBuffer.IsBufferReady(); } + virtual u8 * GetBuffer() { return SoundBuffer.GetBuffer(); } + virtual u32 GetBufferSize() { return SoundBuffer.GetBufferSize(); } + virtual void LoadNext() { SoundBuffer.LoadNext(); } + virtual bool IsEOF() { return EndOfFile; } + virtual void SetLoop(bool l) { Loop = l; EndOfFile = false; } + virtual u8 GetSoundType() { return SoundType; } + virtual void ClearBuffer() { SoundBuffer.ClearBuffer(); whichLoad = 0; } + virtual bool IsStereo() { return (GetFormat() & CHANNELS_STEREO) != 0; } + virtual bool Is16Bit() { return ((GetFormat() & 0xFF) == FORMAT_PCM_16_BIT); } + virtual bool IsDecoding() { return Decoding; } + + void EnableUpsample(void); + + enum SoundFormats + { + FORMAT_PCM_16_BIT = 0x0A, + FORMAT_PCM_8_BIT = 0x19, + }; + enum SoundChannels + { + CHANNELS_MONO = 0x100, + CHANNELS_STEREO = 0x200 + }; + + enum SoundType + { + SOUND_RAW = 0, + SOUND_MP3, + SOUND_OGG, + SOUND_WAV + }; +protected: + void Init(); + void Upsample(s16 *src, s16 *dst, u32 nr_src_samples, u32 nr_dst_samples); + + CFile * file_fd; + BufferCircle SoundBuffer; + u8 SoundType; + u16 whichLoad; + u16 SoundBlocks; + int SoundBlockSize; + int CurPos; + bool ResampleTo48kHz; + bool Loop; + bool EndOfFile; + bool Decoding; + bool ExitRequested; + u16 Format; + u16 SampleRate; + u8 *ResampleBuffer; + u32 ResampleRatio; + CMutex mutex; +}; + + +#endif diff --git a/src/sounds/SoundHandler.cpp b/src/sounds/SoundHandler.cpp new file mode 100644 index 0000000..68f9dd5 --- /dev/null +++ b/src/sounds/SoundHandler.cpp @@ -0,0 +1,351 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include +#include "common/common.h" +#include "dynamic_libs/ax_functions.h" +#include "fs/CFile.hpp" +#include "SoundHandler.hpp" +#include "WavDecoder.hpp" +#include "Mp3Decoder.hpp" +#include "OggDecoder.hpp" + +SoundHandler * SoundHandler::handlerInstance = NULL; + +SoundHandler::SoundHandler() + : CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x8000) +{ + Decoding = false; + ExitRequested = false; + for(u32 i = 0; i < MAX_DECODERS; ++i) + { + DecoderList[i] = NULL; + voiceList[i] = NULL; + } + + resumeThread(); + + //! wait for initialization + while(!isThreadSuspended()) + usleep(1000); +} + +SoundHandler::~SoundHandler() +{ + ExitRequested = true; + ThreadSignal(); + + ClearDecoderList(); +} + +void SoundHandler::AddDecoder(int voice, const char * filepath) +{ + if(voice < 0 || voice >= MAX_DECODERS) + return; + + if(DecoderList[voice] != NULL) + RemoveDecoder(voice); + + DecoderList[voice] = GetSoundDecoder(filepath); +} + +void SoundHandler::AddDecoder(int voice, const u8 * snd, int len) +{ + if(voice < 0 || voice >= MAX_DECODERS) + return; + + if(DecoderList[voice] != NULL) + RemoveDecoder(voice); + + DecoderList[voice] = GetSoundDecoder(snd, len); +} + +void SoundHandler::RemoveDecoder(int voice) +{ + if(voice < 0 || voice >= MAX_DECODERS) + return; + + if(DecoderList[voice] != NULL) + { + if(voiceList[voice] && voiceList[voice]->getState() != Voice::STATE_STOPPED) + { + if(voiceList[voice]->getState() != Voice::STATE_STOP) + voiceList[voice]->setState(Voice::STATE_STOP); + + while(voiceList[voice]->getState() != Voice::STATE_STOPPED) + usleep(1000); + } + SoundDecoder *decoder = DecoderList[voice]; + decoder->Lock(); + DecoderList[voice] = NULL; + decoder->Unlock(); + delete decoder; + } +} + +void SoundHandler::ClearDecoderList() +{ + for(u32 i = 0; i < MAX_DECODERS; ++i) + RemoveDecoder(i); +} + +static inline bool CheckMP3Signature(const u8 * buffer) +{ + const char MP3_Magic[][3] = + { + {'I', 'D', '3'}, //'ID3' + {0xff, 0xfe}, //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'), + {0xff, 0xff}, //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'), + {0xff, 0xfa}, //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'), + {0xff, 0xfb}, //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'), + {0xff, 0xf2}, //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'), + {0xff, 0xf3}, //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'), + {0xff, 0xf4}, //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'), + {0xff, 0xf5}, //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'), + {0xff, 0xf6}, //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'), + {0xff, 0xf7}, //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'), + {0xff, 0xe2}, //'MPEG ADTS, layer III, v2.5 [protected]', 'mp3', 'audio/mpeg'), + {0xff, 0xe3}, //'MPEG ADTS, layer III, v2.5', 'mp3', 'audio/mpeg'), + }; + + if(buffer[0] == MP3_Magic[0][0] && buffer[1] == MP3_Magic[0][1] && + buffer[2] == MP3_Magic[0][2]) + { + return true; + } + + for(int i = 1; i < 13; i++) + { + if(buffer[0] == MP3_Magic[i][0] && buffer[1] == MP3_Magic[i][1]) + return true; + } + + return false; +} + +SoundDecoder * SoundHandler::GetSoundDecoder(const char * filepath) +{ + u32 magic; + CFile f(filepath, CFile::ReadOnly); + if(f.size() == 0) + return NULL; + + do + { + f.read((u8 *) &magic, 1); + } + while(((u8 *) &magic)[0] == 0 && f.tell() < f.size()); + + if(f.tell() == f.size()) + return NULL; + + f.seek(f.tell()-1, SEEK_SET); + f.read((u8 *) &magic, 4); + f.close(); + + if(magic == 0x4f676753) // 'OggS' + { + return new OggDecoder(filepath); + } + else if(magic == 0x52494646) // 'RIFF' + { + return new WavDecoder(filepath); + } + else if(CheckMP3Signature((u8 *) &magic) == true) + { + return new Mp3Decoder(filepath); + } + + return new SoundDecoder(filepath); +} + +SoundDecoder * SoundHandler::GetSoundDecoder(const u8 * sound, int length) +{ + const u8 * check = sound; + int counter = 0; + + while(check[0] == 0 && counter < length) + { + check++; + counter++; + } + + if(counter >= length) + return NULL; + + u32 * magic = (u32 *) check; + + if(magic[0] == 0x4f676753) // 'OggS' + { + return new OggDecoder(sound, length); + } + else if(magic[0] == 0x52494646) // 'RIFF' + { + return new WavDecoder(sound, length); + } + else if(CheckMP3Signature(check) == true) + { + return new Mp3Decoder(sound, length); + } + + return new SoundDecoder(sound, length); +} + +void SoundHandler::executeThread() +{ + // v2 sound lib can not properly end transition audio on old firmwares + if (OS_FIRMWARE >= 400 && OS_FIRMWARE <= 410) + { + ProperlyEndTransitionAudio(); + } + + //! initialize 48 kHz renderer + u32 params[3] = { 1, 0, 0 }; + + if(AXInitWithParams != 0) + AXInitWithParams(params); + else + AXInit(); + + // The problem with last voice on 500 was caused by it having priority 0 + // We would need to change this priority distribution if for some reason + // we would need MAX_DECODERS > Voice::PRIO_MAX + for(u32 i = 0; i < MAX_DECODERS; ++i) + { + int priority = (MAX_DECODERS - i) * Voice::PRIO_MAX / MAX_DECODERS; + voiceList[i] = new Voice(priority); // allocate voice 0 with highest priority + } + + AXRegisterFrameCallback((void*)&axFrameCallback); + + + u16 i = 0; + while (!ExitRequested) + { + suspendThread(); + + for(i = 0; i < MAX_DECODERS; ++i) + { + if(DecoderList[i] == NULL) + continue; + + Decoding = true; + if(DecoderList[i]) + DecoderList[i]->Lock(); + if(DecoderList[i]) + DecoderList[i]->Decode(); + if(DecoderList[i]) + DecoderList[i]->Unlock(); + } + Decoding = false; + } + + for(u32 i = 0; i < MAX_DECODERS; ++i) + voiceList[i]->stop(); + + AXRegisterFrameCallback(NULL); + AXQuit(); + + for(u32 i = 0; i < MAX_DECODERS; ++i) + { + delete voiceList[i]; + voiceList[i] = NULL; + } +} + +void SoundHandler::axFrameCallback(void) +{ + for (u32 i = 0; i < MAX_DECODERS; i++) + { + Voice *voice = handlerInstance->getVoice(i); + + switch (voice->getState()) + { + default: + case Voice::STATE_STOPPED: + break; + + case Voice::STATE_START: { + SoundDecoder * decoder = handlerInstance->getDecoder(i); + decoder->Lock(); + if(decoder->IsBufferReady()) + { + const u8 *buffer = decoder->GetBuffer(); + const u32 bufferSize = decoder->GetBufferSize(); + decoder->LoadNext(); + + const u8 *nextBuffer = NULL; + u32 nextBufferSize = 0; + + if(decoder->IsBufferReady()) + { + nextBuffer = decoder->GetBuffer(); + nextBufferSize = decoder->GetBufferSize(); + decoder->LoadNext(); + } + + voice->play(buffer, bufferSize, nextBuffer, nextBufferSize, decoder->GetFormat() & 0xff, decoder->GetSampleRate()); + + handlerInstance->ThreadSignal(); + + voice->setState(Voice::STATE_PLAYING); + } + decoder->Unlock(); + break; + } + case Voice::STATE_PLAYING: + if(voice->getInternState() == 1) + { + if(voice->isBufferSwitched()) + { + SoundDecoder * decoder = handlerInstance->getDecoder(i); + decoder->Lock(); + if(decoder->IsBufferReady()) + { + voice->setNextBuffer(decoder->GetBuffer(), decoder->GetBufferSize()); + decoder->LoadNext(); + handlerInstance->ThreadSignal(); + } + else if(decoder->IsEOF()) + { + voice->setState(Voice::STATE_STOP); + } + decoder->Unlock(); + } + } + else + { + voice->setState(Voice::STATE_STOPPED); + } + break; + case Voice::STATE_STOP: + if(voice->getInternState() != 0) + voice->stop(); + voice->setState(Voice::STATE_STOPPED); + break; + } + } +} diff --git a/src/sounds/SoundHandler.hpp b/src/sounds/SoundHandler.hpp new file mode 100644 index 0000000..7b0beb6 --- /dev/null +++ b/src/sounds/SoundHandler.hpp @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#ifndef SOUNDHANDLER_H_ +#define SOUNDHANDLER_H_ + +#include +#include +#include "system/CThread.h" +#include "SoundDecoder.hpp" +#include "Voice.h" + +#define MAX_DECODERS 16 // can be increased up to 96 + +class SoundHandler : public CThread +{ +public: + static SoundHandler * instance() { + if (!handlerInstance) + handlerInstance = new SoundHandler(); + return handlerInstance; + } + + static void DestroyInstance() { delete handlerInstance; handlerInstance = NULL; } + + void AddDecoder(int voice, const char * filepath); + void AddDecoder(int voice, const u8 * snd, int len); + void RemoveDecoder(int voice); + + SoundDecoder * getDecoder(int i) { return ((i < 0 || i >= MAX_DECODERS) ? NULL : DecoderList[i]); }; + Voice * getVoice(int i) { return ((i < 0 || i >= MAX_DECODERS) ? NULL : voiceList[i]); }; + + void ThreadSignal() { resumeThread(); }; + bool IsDecoding() { return Decoding; }; +protected: + SoundHandler(); + ~SoundHandler(); + + static void axFrameCallback(void); + + void executeThread(void); + void ClearDecoderList(); + + SoundDecoder * GetSoundDecoder(const char * filepath); + SoundDecoder * GetSoundDecoder(const u8 * sound, int length); + + static SoundHandler * handlerInstance; + + bool Decoding; + bool ExitRequested; + + Voice * voiceList[MAX_DECODERS]; + SoundDecoder * DecoderList[MAX_DECODERS]; +}; + +#endif diff --git a/src/sounds/Voice.h b/src/sounds/Voice.h new file mode 100644 index 0000000..63fd94e --- /dev/null +++ b/src/sounds/Voice.h @@ -0,0 +1,170 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef _AXSOUND_H_ +#define _AXSOUND_H_ + +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/ax_functions.h" + +class Voice +{ +public: + + enum VoicePriorities + { + PRIO_MIN = 1, + PRIO_MAX = 31 + }; + + enum VoiceStates + { + STATE_STOPPED, + STATE_START, + STATE_PLAYING, + STATE_STOP, + }; + + Voice(int prio) + : state(STATE_STOPPED) + { + lastLoopCounter = 0; + nextBufferSize = 0; + + voice = AXAcquireVoice(prio, 0, 0); + if(voice) + { + AXVoiceBegin(voice); + AXSetVoiceType(voice, 0); + setVolume(0x80000000); + + u32 mix[24]; + memset(mix, 0, sizeof(mix)); + mix[0] = 0x80000000; + mix[4] = 0x80000000; + + AXSetVoiceDeviceMix(voice, 0, 0, mix); + AXSetVoiceDeviceMix(voice, 1, 0, mix); + + AXVoiceEnd(voice); + } + } + + ~Voice() + { + if(voice) + { + AXFreeVoice(voice); + } + } + + void play(const u8 *buffer, u32 bufferSize, const u8 *nextBuffer, u32 nextBufSize, u16 format, u32 sampleRate) + { + if(!voice) + return; + + memset(&voiceBuffer, 0, sizeof(voiceBuffer)); + + voiceBuffer.samples = buffer; + voiceBuffer.format = format; + voiceBuffer.loop = (nextBuffer == NULL) ? 0 : 1; + voiceBuffer.cur_pos = 0; + voiceBuffer.end_pos = bufferSize >> 1; + voiceBuffer.loop_offset = ((nextBuffer - buffer) >> 1); + nextBufferSize = nextBufSize; + + u32 samplesPerSec = (AXGetInputSamplesPerSec != 0) ? AXGetInputSamplesPerSec() : 32000; + + ratioBits[0] = (u32)(0x00010000 * ((f32)sampleRate / (f32)samplesPerSec)); + ratioBits[1] = 0; + ratioBits[2] = 0; + ratioBits[3] = 0; + + AXSetVoiceOffsets(voice, &voiceBuffer); + AXSetVoiceSrc(voice, ratioBits); + AXSetVoiceSrcType(voice, 1); + AXSetVoiceState(voice, 1); + } + + void stop() + { + if(voice) + AXSetVoiceState(voice, 0); + } + + void setVolume(u32 vol) + { + if(voice) + AXSetVoiceVe(voice, &vol); + } + + + void setNextBuffer(const u8 *buffer, u32 bufferSize) + { + voiceBuffer.loop_offset = ((buffer - voiceBuffer.samples) >> 1); + nextBufferSize = bufferSize; + + AXSetVoiceLoopOffset(voice, voiceBuffer.loop_offset); + } + + bool isBufferSwitched() + { + u32 loopCounter = AXGetVoiceLoopCount(voice); + if(lastLoopCounter != loopCounter) + { + lastLoopCounter = loopCounter; + AXSetVoiceEndOffset(voice, voiceBuffer.loop_offset + (nextBufferSize >> 1)); + return true; + } + return false; + } + + u32 getInternState() const { + if(voice) + return ((u32 *)voice)[1]; + return 0; + } + u32 getState() const { + return state; + } + void setState(u32 s) { + state = s; + } + + void * getVoice() const { + return voice; + } + +private: + void *voice; + u32 ratioBits[4]; + + typedef struct _ax_buffer_t { + u16 format; + u16 loop; + u32 loop_offset; + u32 end_pos; + u32 cur_pos; + const unsigned char *samples; + } ax_buffer_t; + + ax_buffer_t voiceBuffer; + u32 state; + u32 nextBufferSize; + u32 lastLoopCounter; +}; + +#endif // _AXSOUND_H_ diff --git a/src/sounds/WavDecoder.cpp b/src/sounds/WavDecoder.cpp new file mode 100644 index 0000000..f241df0 --- /dev/null +++ b/src/sounds/WavDecoder.cpp @@ -0,0 +1,154 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include "WavDecoder.hpp" +#include "utils/utils.h" + +WavDecoder::WavDecoder(const char * filepath) + : SoundDecoder(filepath) +{ + SoundType = SOUND_WAV; + SampleRate = 48000; + Format = CHANNELS_STEREO | FORMAT_PCM_16_BIT; + + if(!file_fd) + return; + + OpenFile(); +} + +WavDecoder::WavDecoder(const u8 * snd, int len) + : SoundDecoder(snd, len) +{ + SoundType = SOUND_WAV; + SampleRate = 48000; + Format = CHANNELS_STEREO | FORMAT_PCM_16_BIT; + + if(!file_fd) + return; + + OpenFile(); +} + +WavDecoder::~WavDecoder() +{ +} + + +void WavDecoder::OpenFile() +{ + SWaveHdr Header; + SWaveFmtChunk FmtChunk; + memset(&Header, 0, sizeof(SWaveHdr)); + memset(&FmtChunk, 0, sizeof(SWaveFmtChunk)); + + file_fd->read((u8 *) &Header, sizeof(SWaveHdr)); + file_fd->read((u8 *) &FmtChunk, sizeof(SWaveFmtChunk)); + + if (Header.magicRIFF != 0x52494646) // 'RIFF' + { + CloseFile(); + return; + } + else if(Header.magicWAVE != 0x57415645) // 'WAVE' + { + CloseFile(); + return; + } + else if(FmtChunk.magicFMT != 0x666d7420) // 'fmt ' + { + CloseFile(); + return; + } + + DataOffset = sizeof(SWaveHdr)+le32(FmtChunk.size)+8; + file_fd->seek(DataOffset, SEEK_SET); + SWaveChunk DataChunk; + file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk)); + + while(DataChunk.magicDATA != 0x64617461) // 'data' + { + DataOffset += 8+le32(DataChunk.size); + file_fd->seek(DataOffset, SEEK_SET); + int ret = file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk)); + if(ret <= 0) + { + CloseFile(); + return; + } + } + + DataOffset += 8; + DataSize = le32(DataChunk.size); + Is16Bit = (le16(FmtChunk.bps) == 16); + SampleRate = le32(FmtChunk.freq); + + if (le16(FmtChunk.channels) == 1 && le16(FmtChunk.bps) == 8 && le16(FmtChunk.alignment) <= 1) + Format = CHANNELS_MONO | FORMAT_PCM_8_BIT; + else if (le16(FmtChunk.channels) == 1 && le16(FmtChunk.bps) == 16 && le16(FmtChunk.alignment) <= 2) + Format = CHANNELS_MONO | FORMAT_PCM_16_BIT; + else if (le16(FmtChunk.channels) == 2 && le16(FmtChunk.bps) == 8 && le16(FmtChunk.alignment) <= 2) + Format = CHANNELS_STEREO | FORMAT_PCM_8_BIT; + else if (le16(FmtChunk.channels) == 2 && le16(FmtChunk.bps) == 16 && le16(FmtChunk.alignment) <= 4) + Format = CHANNELS_STEREO | FORMAT_PCM_16_BIT; +} + +void WavDecoder::CloseFile() +{ + if(file_fd) + delete file_fd; + + file_fd = NULL; +} + +int WavDecoder::Read(u8 * buffer, int buffer_size, int pos) +{ + if(!file_fd) + return -1; + + if(CurPos >= (int) DataSize) + return 0; + + file_fd->seek(DataOffset+CurPos, SEEK_SET); + + if(buffer_size > (int) DataSize-CurPos) + buffer_size = DataSize-CurPos; + + int read = file_fd->read(buffer, buffer_size); + if(read > 0) + { + if (Is16Bit) + { + read &= ~0x0001; + + for (u32 i = 0; i < (u32) (read / sizeof (u16)); ++i) + ((u16 *) buffer)[i] = le16(((u16 *) buffer)[i]); + } + CurPos += read; + } + + return read; +} diff --git a/src/sounds/WavDecoder.hpp b/src/sounds/WavDecoder.hpp new file mode 100644 index 0000000..5981883 --- /dev/null +++ b/src/sounds/WavDecoder.hpp @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#ifndef WAVDECODER_HPP_ +#define WAVDECODER_HPP_ + +#include "SoundDecoder.hpp" + +typedef struct +{ + u32 magicRIFF; + u32 size; + u32 magicWAVE; +} SWaveHdr; + +typedef struct +{ + u32 magicFMT; + u32 size; + u16 format; + u16 channels; + u32 freq; + u32 avgBps; + u16 alignment; + u16 bps; +} SWaveFmtChunk; + +typedef struct +{ + u32 magicDATA; + u32 size; +} SWaveChunk; + +class WavDecoder : public SoundDecoder +{ + public: + WavDecoder(const char * filepath); + WavDecoder(const u8 * snd, int len); + virtual ~WavDecoder(); + int Read(u8 * buffer, int buffer_size, int pos); + protected: + void OpenFile(); + void CloseFile(); + u32 DataOffset; + u32 DataSize; + bool Is16Bit; +}; + +#endif diff --git a/src/system/AsyncDeleter.cpp b/src/system/AsyncDeleter.cpp new file mode 100644 index 0000000..7b69751 --- /dev/null +++ b/src/system/AsyncDeleter.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include "AsyncDeleter.h" + +AsyncDeleter * AsyncDeleter::deleterInstance = NULL; + +AsyncDeleter::AsyncDeleter() + : CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff) + , exitApplication(false) +{ +} + +AsyncDeleter::~AsyncDeleter() +{ + exitApplication = true; +} + +void AsyncDeleter::triggerDeleteProcess(void) +{ + if(!deleterInstance) + deleterInstance = new AsyncDeleter; + + //! to trigger the event after GUI process is finished execution + //! this function is used to swap elements from one to next array + if(!deleterInstance->deleteElements.empty()) + { + deleterInstance->deleteMutex.lock(); + while(!deleterInstance->deleteElements.empty()) + { + deleterInstance->realDeleteElements.push(deleterInstance->deleteElements.front()); + deleterInstance->deleteElements.pop(); + } + deleterInstance->deleteMutex.unlock(); + deleterInstance->resumeThread(); + } +} + +void AsyncDeleter::executeThread(void) +{ + while(!exitApplication) + { + suspendThread(); + log_printf("AsyncDeleter thread running\n"); + //! delete elements that require post process deleting + //! because otherwise they would block or do invalid access on GUI thread + while(!realDeleteElements.empty()) + { + deleteMutex.lock(); + AsyncDeleter::Element *element = realDeleteElements.front(); + realDeleteElements.pop(); + deleteMutex.unlock(); + + delete element; + } + } + +} diff --git a/src/system/AsyncDeleter.h b/src/system/AsyncDeleter.h new file mode 100644 index 0000000..6cce1fa --- /dev/null +++ b/src/system/AsyncDeleter.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef _ASYNC_DELETER_H +#define _ASYNC_DELETER_H + +#include +#include "CThread.h" +#include "CMutex.h" + +class AsyncDeleter : public CThread +{ +public: + static void destroyInstance() + { + if(deleterInstance != NULL){ + delete deleterInstance; + deleterInstance = NULL; + } + } + + class Element + { + public: + Element() {} + virtual ~Element() {} + }; + + static void pushForDelete(AsyncDeleter::Element *e) + { + if(!deleterInstance) + deleterInstance = new AsyncDeleter; + deleterInstance->deleteElements.push(e); + } + + static void triggerDeleteProcess(void); + +private: + AsyncDeleter(); + virtual ~AsyncDeleter(); + + static AsyncDeleter *deleterInstance; + + void executeThread(void); + + bool exitApplication; + std::queue deleteElements; + std::queue realDeleteElements; + CMutex deleteMutex; +}; + +#endif // _ASYNC_DELETER_H diff --git a/src/system/CMutex.h b/src/system/CMutex.h new file mode 100644 index 0000000..3e7cc1b --- /dev/null +++ b/src/system/CMutex.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef _CMUTEX_H_ +#define _CMUTEX_H_ + +#include +#include "dynamic_libs/os_functions.h" + +class CMutex +{ +public: + CMutex() { + pMutex = malloc(OS_MUTEX_SIZE); + if(!pMutex) + return; + + OSInitMutex(pMutex); + } + virtual ~CMutex() { + if(pMutex) + free(pMutex); + } + + void lock(void) { + if(pMutex) + OSLockMutex(pMutex); + } + void unlock(void) { + if(pMutex) + OSUnlockMutex(pMutex); + } + bool tryLock(void) { + if(!pMutex) + return false; + + return (OSTryLockMutex(pMutex) != 0); + } +private: + void *pMutex; +}; + +class CMutexLock +{ +public: + CMutexLock() { + mutex.lock(); + } + virtual ~CMutexLock() { + mutex.unlock(); + } +private: + CMutex mutex; +}; + +#endif // _CMUTEX_H_ diff --git a/src/system/CThread.h b/src/system/CThread.h new file mode 100644 index 0000000..3fade45 --- /dev/null +++ b/src/system/CThread.h @@ -0,0 +1,121 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef CTHREAD_H_ +#define CTHREAD_H_ + +#include +#include +#include +#include "dynamic_libs/os_functions.h" +#include "utils/logger.h" + +class CThread +{ +public: + typedef void (* Callback)(CThread *thread, void *arg); + + //! constructor + CThread(int iAttr, int iPriority = 16, int iStackSize = 0x8000, CThread::Callback callback = NULL, void *callbackArg = NULL) + : pThread(NULL) + , pThreadStack(NULL) + , pCallback(callback) + , pCallbackArg(callbackArg) + { + //! save attribute assignment + iAttributes = iAttr; + //! allocate the thread + pThread = memalign(8, 0x1000); + //! allocate the stack + pThreadStack = (u8 *) memalign(0x20, iStackSize); + //! create the thread + if(pThread && pThreadStack) + OSCreateThread(pThread, &CThread::threadCallback, 1, this, (u32)pThreadStack+iStackSize, iStackSize, iPriority, iAttributes); + } + + //! destructor + virtual ~CThread() { shutdownThread(); } + + static CThread *create(CThread::Callback callback, void *callbackArg, int iAttr = eAttributeNone, int iPriority = 16, int iStackSize = 0x8000) + { + return ( new CThread(iAttr, iPriority, iStackSize, callback, callbackArg) ); + } + + //! Get thread ID + virtual void* getThread() const { return pThread; } + //! Thread entry function + virtual void executeThread(void) + { + if(pCallback) + pCallback(this, pCallbackArg); + } + //! Suspend thread + virtual void suspendThread(void) { if(isThreadSuspended()) return; if(pThread) OSSuspendThread(pThread); } + //! Resume thread + virtual void resumeThread(void) { if(!isThreadSuspended()) return; if(pThread) OSResumeThread(pThread); } + //! Set thread priority + virtual void setThreadPriority(int prio) { if(pThread) OSSetThreadPriority(pThread, prio); } + //! Check if thread is suspended + virtual bool isThreadSuspended(void) const { if(pThread) return OSIsThreadSuspended(pThread); return false; } + //! Check if thread is terminated + virtual bool isThreadTerminated(void) const { if(pThread) return OSIsThreadTerminated(pThread); return false; } + //! Check if thread is running + virtual bool isThreadRunning(void) const { return !isThreadSuspended() && !isThreadRunning(); } + //! Shutdown thread + virtual void shutdownThread(void) + { + //! wait for thread to finish + if(pThread && !(iAttributes & eAttributeDetach)) + { + while(isThreadSuspended()){ + resumeThread(); + } + OSJoinThread(pThread, NULL); + } + //! free the thread stack buffer + if(pThreadStack){ + free(pThreadStack); + } + if(pThread) + free(pThread); + pThread = NULL; + pThreadStack = NULL; + } + //! Thread attributes + enum eCThreadAttributes + { + eAttributeNone = 0x07, + eAttributeAffCore0 = 0x01, + eAttributeAffCore1 = 0x02, + eAttributeAffCore2 = 0x04, + eAttributeDetach = 0x08, + eAttributePinnedAff = 0x10 + }; +private: + static int threadCallback(int argc, void *arg) + { + //! After call to start() continue with the internal function + ((CThread *) arg)->executeThread(); + return 0; + } + int iAttributes; + void *pThread; + u8 *pThreadStack; + Callback pCallback; + void *pCallbackArg; +}; + +#endif diff --git a/src/system/exception_handler.c b/src/system/exception_handler.c new file mode 100644 index 0000000..b642248 --- /dev/null +++ b/src/system/exception_handler.c @@ -0,0 +1,169 @@ +#include +#include "dynamic_libs/os_functions.h" +#include "utils/logger.h" +#include "exception_handler.h" + +#define OS_EXCEPTION_MODE_GLOBAL_ALL_CORES 4 + +#define OS_EXCEPTION_DSI 2 +#define OS_EXCEPTION_ISI 3 +#define OS_EXCEPTION_PROGRAM 6 + +/* Exceptions */ +typedef struct OSContext +{ + /* OSContext identifier */ + uint32_t tag1; + uint32_t tag2; + + /* GPRs */ + uint32_t gpr[32]; + + /* Special registers */ + uint32_t cr; + uint32_t lr; + uint32_t ctr; + uint32_t xer; + + /* Initial PC and MSR */ + uint32_t srr0; + uint32_t srr1; + + /* Only valid during DSI exception */ + uint32_t exception_specific0; + uint32_t exception_specific1; + + /* There is actually a lot more here but we don't need the rest*/ +} OSContext; + +#define CPU_STACK_TRACE_DEPTH 10 +#define __stringify(rn) #rn + +#define mfspr(_rn) \ +({ register uint32_t _rval = 0; \ + asm volatile("mfspr %0," __stringify(_rn) \ + : "=r" (_rval));\ + _rval; \ +}) + +typedef struct _framerec { + struct _framerec *up; + void *lr; +} frame_rec, *frame_rec_t; + +static const char *exception_names[] = { + "DSI", + "ISI", + "PROGRAM" +}; + +static const char exception_print_formats[18][45] = { + "Exception type %s occurred!\n", // 0 + "GPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n", // 1 + "GPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n", // 2 + "GPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n", // 3 + "GPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n", // 4 + "GPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n", // 5 + "GPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n", // 6 + "GPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n", // 7 + "GPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n", // 8 + "LR %08X SRR0 %08x SRR1 %08x\n", // 9 + "DAR %08X DSISR %08X\n", // 10 + "\nSTACK DUMP:", // 11 + " --> ", // 12 + " -->\n", // 13 + "\n", // 14 + "%p", // 15 + "\nCODE DUMP:\n", // 16 + "%p: %08X %08X %08X %08X\n", // 17 +}; + +static unsigned char exception_cb(void * c, unsigned char exception_type) { + char buf[850]; + int pos = 0; + + OSContext *context = (OSContext *) c; + /* + * This part is mostly from libogc. Thanks to the devs over there. + */ + pos += sprintf(buf + pos, exception_print_formats[0], exception_names[exception_type]); + pos += sprintf(buf + pos, exception_print_formats[1], context->gpr[0], context->gpr[8], context->gpr[16], context->gpr[24]); + pos += sprintf(buf + pos, exception_print_formats[2], context->gpr[1], context->gpr[9], context->gpr[17], context->gpr[25]); + pos += sprintf(buf + pos, exception_print_formats[3], context->gpr[2], context->gpr[10], context->gpr[18], context->gpr[26]); + pos += sprintf(buf + pos, exception_print_formats[4], context->gpr[3], context->gpr[11], context->gpr[19], context->gpr[27]); + pos += sprintf(buf + pos, exception_print_formats[5], context->gpr[4], context->gpr[12], context->gpr[20], context->gpr[28]); + pos += sprintf(buf + pos, exception_print_formats[6], context->gpr[5], context->gpr[13], context->gpr[21], context->gpr[29]); + pos += sprintf(buf + pos, exception_print_formats[7], context->gpr[6], context->gpr[14], context->gpr[22], context->gpr[30]); + pos += sprintf(buf + pos, exception_print_formats[8], context->gpr[7], context->gpr[15], context->gpr[23], context->gpr[31]); + pos += sprintf(buf + pos, exception_print_formats[9], context->lr, context->srr0, context->srr1); + + //if(exception_type == OS_EXCEPTION_DSI) { + pos += sprintf(buf + pos, exception_print_formats[10], context->exception_specific1, context->exception_specific0); // this freezes + //} + + void *pc = (void*)context->srr0; + void *lr = (void*)context->lr; + void *r1 = (void*)context->gpr[1]; + register uint32_t i = 0; + register frame_rec_t l,p = (frame_rec_t)lr; + + l = p; + p = r1; + if(!p) + asm volatile("mr %0,%%r1" : "=r"(p)); + + pos += sprintf(buf + pos, exception_print_formats[11]); + + for(i = 0; i < CPU_STACK_TRACE_DEPTH-1 && p->up; p = p->up, i++) { + if(i % 4) + pos += sprintf(buf + pos, exception_print_formats[12]); + else { + if(i > 0) + pos += sprintf(buf + pos, exception_print_formats[13]); + else + pos += sprintf(buf + pos, exception_print_formats[14]); + } + + switch(i) { + case 0: + if(pc) + pos += sprintf(buf + pos, exception_print_formats[15],pc); + break; + case 1: + if(!l) + l = (frame_rec_t)mfspr(8); + pos += sprintf(buf + pos, exception_print_formats[15],(void*)l); + break; + default: + pos += sprintf(buf + pos, exception_print_formats[15],(void*)(p->up->lr)); + break; + } + } + + //if(exception_type == OS_EXCEPTION_DSI) { + uint32_t *pAdd = (uint32_t*)context->srr0; + pos += sprintf(buf + pos, exception_print_formats[16]); + // TODO by Dimok: this was actually be 3 instead of 2 lines in libogc .... but there is just no more space anymore on the screen + for (i = 0; i < 8; i += 4) + pos += sprintf(buf + pos, exception_print_formats[17], &(pAdd[i]),pAdd[i], pAdd[i+1], pAdd[i+2], pAdd[i+3]); + //} + log_print(buf); + OSFatal(buf); + return 1; +} + +static unsigned char dsi_exception_cb(void * context) { + return exception_cb(context, 0); +} +static unsigned char isi_exception_cb(void * context) { + return exception_cb(context, 1); +} +static unsigned char program_exception_cb(void * context) { + return exception_cb(context, 2); +} + +void setup_os_exceptions(void) { + OSSetExceptionCallback(OS_EXCEPTION_DSI, &dsi_exception_cb); + OSSetExceptionCallback(OS_EXCEPTION_ISI, &isi_exception_cb); + OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb); +} diff --git a/src/system/exception_handler.h b/src/system/exception_handler.h new file mode 100644 index 0000000..7626f92 --- /dev/null +++ b/src/system/exception_handler.h @@ -0,0 +1,14 @@ +#ifndef __EXCEPTION_HANDLER_H_ +#define __EXCEPTION_HANDLER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void setup_os_exceptions(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/system/memory.c b/src/system/memory.c new file mode 100644 index 0000000..91f5392 --- /dev/null +++ b/src/system/memory.c @@ -0,0 +1,198 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include +#include "dynamic_libs/os_functions.h" +#include "common/common.h" +#include "memory.h" + +#define MEMORY_ARENA_1 0 +#define MEMORY_ARENA_2 1 +#define MEMORY_ARENA_3 2 +#define MEMORY_ARENA_4 3 +#define MEMORY_ARENA_5 4 +#define MEMORY_ARENA_6 5 +#define MEMORY_ARENA_7 6 +#define MEMORY_ARENA_8 7 +#define MEMORY_ARENA_FG_BUCKET 8 + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Memory functions +//! This is the only place where those are needed so lets keep them more or less private +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern unsigned int * pMEMAllocFromDefaultHeapEx; +extern unsigned int * pMEMAllocFromDefaultHeap; +extern unsigned int * pMEMFreeToDefaultHeap; + +extern int (* MEMGetBaseHeapHandle)(int mem_arena); +extern unsigned int (* MEMGetAllocatableSizeForFrmHeapEx)(int heap, int align); +extern void *(* MEMAllocFromFrmHeapEx)(int heap, unsigned int size, int align); +extern void (* MEMFreeToFrmHeap)(int heap, int mode); +extern void *(* MEMAllocFromExpHeapEx)(int heap, unsigned int size, int align); +extern int (* MEMCreateExpHeapEx)(void* address, unsigned int size, unsigned short flags); +extern void *(* MEMDestroyExpHeap)(int heap); +extern void (* MEMFreeToExpHeap)(int heap, void* ptr); + +static int mem1_heap = -1; +static int bucket_heap = -1; + +void memoryInitialize(void) +{ + int mem1_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_1); + unsigned int mem1_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(mem1_heap_handle, 4); + void *mem1_memory = MEMAllocFromFrmHeapEx(mem1_heap_handle, mem1_allocatable_size, 4); + if(mem1_memory) + mem1_heap = MEMCreateExpHeapEx(mem1_memory, mem1_allocatable_size, 0); + + int bucket_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET); + unsigned int bucket_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(bucket_heap_handle, 4); + void *bucket_memory = MEMAllocFromFrmHeapEx(bucket_heap_handle, bucket_allocatable_size, 4); + if(bucket_memory) + bucket_heap = MEMCreateExpHeapEx(bucket_memory, bucket_allocatable_size, 0); +} + +void memoryRelease(void) +{ + MEMDestroyExpHeap(mem1_heap); + MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_1), 3); + mem1_heap = -1; + + MEMDestroyExpHeap(bucket_heap); + MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET), 3); + bucket_heap = -1; +} + +//!------------------------------------------------------------------------------------------- +//! wraps +//!------------------------------------------------------------------------------------------- +void *__wrap_malloc(size_t size) +{ + // pointer to a function resolve + return ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(size); +} + +void *__wrap_memalign(size_t align, size_t size) +{ + if (align < 4) + align = 4; + + // pointer to a function resolve + return ((void * (*)(size_t, size_t))(*pMEMAllocFromDefaultHeapEx))(size, align); +} + +void __wrap_free(void *p) +{ + // pointer to a function resolve + if(p != 0) + ((void (*)(void *))(*pMEMFreeToDefaultHeap))(p); +} + +void *__wrap_calloc(size_t n, size_t size) +{ + void *p = __wrap_malloc(n * size); + if (p != 0) { + memset(p, 0, n * size); + } + return p; +} + +size_t __wrap_malloc_usable_size(void *p) +{ + //! TODO: this is totally wrong and needs to be addressed + return 0x7FFFFFFF; +} + +void *__wrap_realloc(void *p, size_t size) +{ + void *new_ptr = __wrap_malloc(size); + if (new_ptr != 0) + { + memcpy(new_ptr, p, __wrap_malloc_usable_size(p) < size ? __wrap_malloc_usable_size(p) : size); + __wrap_free(p); + } + return new_ptr; +} + +//!------------------------------------------------------------------------------------------- +//! reent versions +//!------------------------------------------------------------------------------------------- +void *__wrap__malloc_r(struct _reent *r, size_t size) +{ + return __wrap_malloc(size); +} + +void *__wrap__calloc_r(struct _reent *r, size_t n, size_t size) +{ + return __wrap_calloc(n, size); +} + +void *__wrap__memalign_r(struct _reent *r, size_t align, size_t size) +{ + return __wrap_memalign(align, size); +} + +void __wrap__free_r(struct _reent *r, void *p) +{ + __wrap_free(p); +} + +size_t __wrap__malloc_usable_size_r(struct _reent *r, void *p) +{ + return __wrap_malloc_usable_size(p); +} + +void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) +{ + return __wrap_realloc(p, size); +} + +//!------------------------------------------------------------------------------------------- +//! some wrappers +//!------------------------------------------------------------------------------------------- +void * MEM2_alloc(unsigned int size, unsigned int align) +{ + return __wrap_memalign(align, size); +} + +void MEM2_free(void *ptr) +{ + __wrap_free(ptr); +} + +void * MEM1_alloc(unsigned int size, unsigned int align) +{ + if (align < 4) + align = 4; + return MEMAllocFromExpHeapEx(mem1_heap, size, align); +} + +void MEM1_free(void *ptr) +{ + MEMFreeToExpHeap(mem1_heap, ptr); +} + +void * MEMBucket_alloc(unsigned int size, unsigned int align) +{ + if (align < 4) + align = 4; + return MEMAllocFromExpHeapEx(bucket_heap, size, align); +} + +void MEMBucket_free(void *ptr) +{ + MEMFreeToExpHeap(bucket_heap, ptr); +} diff --git a/src/system/memory.h b/src/system/memory.h new file mode 100644 index 0000000..59764d0 --- /dev/null +++ b/src/system/memory.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef __MEMORY_H_ +#define __MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void memoryInitialize(void); +void memoryRelease(void); + +void * MEM2_alloc(unsigned int size, unsigned int align); +void MEM2_free(void *ptr); + +void * MEM1_alloc(unsigned int size, unsigned int align); +void MEM1_free(void *ptr); + +void * MEMBucket_alloc(unsigned int size, unsigned int align); +void MEMBucket_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif // __MEMORY_H_ diff --git a/src/utils/StringTools.cpp b/src/utils/StringTools.cpp new file mode 100644 index 0000000..debb6c7 --- /dev/null +++ b/src/utils/StringTools.cpp @@ -0,0 +1,207 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +const char * fmt(const char * format, ...) +{ + static char strChar[512]; + strChar[0] = 0; + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + snprintf(strChar, sizeof(strChar), tmp); + free(tmp); + va_end(va); + return (const char *) strChar; + } + va_end(va); + + if(tmp) + free(tmp); + + return NULL; +} + +const wchar_t * wfmt(const char * format, ...) +{ + static wchar_t strWChar[512]; + strWChar[0] = 0; + + if(!format) + return (const wchar_t *) strWChar; + + if(strcmp(format, "") == 0) + return (const wchar_t *) strWChar; + + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + int bt; + int strlength = strlen(tmp); + bt = mbstowcs(strWChar, tmp, (strlength < 512) ? strlength : 512 ); + free(tmp); + tmp = 0; + + if(bt > 0) + { + strWChar[bt] = 0; + return (const wchar_t *) strWChar; + } + } + va_end(va); + + if(tmp) + free(tmp); + + return NULL; +} + +int strprintf(std::string &str, const char * format, ...) +{ + int result = 0; + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + str = tmp; + result = str.size(); + } + va_end(va); + + if(tmp) + free(tmp); + + return result; +} + +std::string strfmt(const char * format, ...) +{ + std::string str; + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + str = tmp; + } + va_end(va); + + if(tmp) + free(tmp); + + return str; +} + +bool char2wchar_t(const char * strChar, wchar_t * dest) +{ + if(!strChar || !dest) + return false; + + int bt; + bt = mbstowcs(dest, strChar, strlen(strChar)); + if (bt > 0) { + dest[bt] = 0; + return true; + } + + return false; +} + +int strtokcmp(const char * string, const char * compare, const char * separator) +{ + if(!string || !compare) + return -1; + + char TokCopy[512]; + strncpy(TokCopy, compare, sizeof(TokCopy)); + TokCopy[511] = '\0'; + + char * strTok = strtok(TokCopy, separator); + + while (strTok != NULL) + { + if (strcasecmp(string, strTok) == 0) + { + return 0; + } + strTok = strtok(NULL,separator); + } + + return -1; +} + +int strextcmp(const char * string, const char * extension, char seperator) +{ + if(!string || !extension) + return -1; + + char *ptr = strrchr(string, seperator); + if(!ptr) + return -1; + + return strcasecmp(ptr + 1, extension); +} + + +std::vector stringSplit(const std::string & inValue, const std::string & splitter) +{ + std::string value = inValue; + std::vector result; + while (true) { + unsigned int index = value.find(splitter); + if (index == std::string::npos) { + result.push_back(value); + break; + } + std::string first = value.substr(0, index); + result.push_back(first); + if (index + splitter.size() == value.length()) { + result.push_back(""); + break; + } + if(index + splitter.size() > value.length()) { + break; + } + value = value.substr(index + splitter.size(), value.length()); + } + return result; +} diff --git a/src/utils/StringTools.h b/src/utils/StringTools.h new file mode 100644 index 0000000..bcf89c4 --- /dev/null +++ b/src/utils/StringTools.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#ifndef __STRING_TOOLS_H +#define __STRING_TOOLS_H + +#include +#include +#include + +const char * fmt(const char * format, ...); +const wchar_t * wfmt(const char * format, ...); +int strprintf(std::string &str, const char * format, ...); +std::string strfmt(const char * format, ...); +bool char2wchar_t(const char * src, wchar_t * dest); +int strtokcmp(const char * string, const char * compare, const char * separator); +int strextcmp(const char * string, const char * extension, char seperator); + +inline const char * FullpathToFilename(const char *path) +{ + if(!path) return path; + + const char * ptr = path; + const char * Filename = ptr; + + while(*ptr != '\0') + { + if(ptr[0] == '/' && ptr[1] != '\0') + Filename = ptr+1; + + ++ptr; + } + + return Filename; +} + +inline void RemoveDoubleSlashs(std::string &str) +{ + u32 length = str.size(); + + //! clear path of double slashes + for(u32 i = 1; i < length; ++i) + { + if(str[i-1] == '/' && str[i] == '/') + { + str.erase(i, 1); + i--; + length--; + } + } +} + +std::vector stringSplit(const std::string & value, const std::string & splitter); + +#endif /* __STRING_TOOLS_H */ + diff --git a/src/utils/logger.c b/src/utils/logger.c new file mode 100644 index 0000000..e1e411f --- /dev/null +++ b/src/utils/logger.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "logger.h" + +#ifdef DEBUG_LOGGER +static int log_socket = -1; +static volatile int log_lock = 0; + + +void log_init(const char * ipString) +{ + log_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (log_socket < 0) + return; + + struct sockaddr_in connect_addr; + memset(&connect_addr, 0, sizeof(connect_addr)); + connect_addr.sin_family = AF_INET; + connect_addr.sin_port = 4405; + inet_aton(ipString, &connect_addr.sin_addr); + + if(connect(log_socket, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) < 0) + { + socketclose(log_socket); + log_socket = -1; + } +} + +void log_deinit(void) +{ + if(log_socket >= 0) + { + socketclose(log_socket); + log_socket = -1; + } +} + +void log_print(const char *str) +{ + // socket is always 0 initially as it is in the BSS + if(log_socket < 0) { + return; + } + + while(log_lock) + usleep(1000); + log_lock = 1; + + int len = strlen(str); + int ret; + while (len > 0) { + int block = len < 1400 ? len : 1400; // take max 1400 bytes per UDP packet + ret = send(log_socket, str, block, 0); + if(ret < 0) + break; + + len -= ret; + str += ret; + } + + log_lock = 0; +} + +void log_printf(const char *format, ...) +{ + if(log_socket < 0) { + return; + } + + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + log_print(tmp); + } + va_end(va); + + if(tmp) + free(tmp); +} +#endif diff --git a/src/utils/logger.h b/src/utils/logger.h new file mode 100644 index 0000000..dd7cc71 --- /dev/null +++ b/src/utils/logger.h @@ -0,0 +1,26 @@ +#ifndef __LOGGER_H_ +#define __LOGGER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEBUG_LOGGER 1 + +#ifdef DEBUG_LOGGER +void log_init(const char * ip); +void log_deinit(void); +void log_print(const char *str); +void log_printf(const char *format, ...); +#else +#define log_init(x) +#define log_deinit() +#define log_print(x) +#define log_printf(x, ...) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/utils/utils.h b/src/utils/utils.h new file mode 100644 index 0000000..c460fa2 --- /dev/null +++ b/src/utils/utils.h @@ -0,0 +1,47 @@ +#ifndef __UTILS_H_ +#define __UTILS_H_ + +#include +#include "../common/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FlushBlock(addr) asm volatile("dcbf %0, %1\n" \ + "icbi %0, %1\n" \ + "sync\n" \ + "eieio\n" \ + "isync\n" \ + : \ + :"r"(0), "r"(((addr) & ~31)) \ + :"memory", "ctr", "lr", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12" \ + ); + +#define LIMIT(x, min, max) \ + ({ \ + typeof( x ) _x = x; \ + typeof( min ) _min = min; \ + typeof( max ) _max = max; \ + ( ( ( _x ) < ( _min ) ) ? ( _min ) : ( ( _x ) > ( _max ) ) ? ( _max) : ( _x ) ); \ + }) + +#define DegToRad(a) ( (a) * 0.01745329252f ) +#define RadToDeg(a) ( (a) * 57.29577951f ) + +#define ALIGN4(x) (((x) + 3) & ~3) +#define ALIGN32(x) (((x) + 31) & ~31) + +// those work only in powers of 2 +#define ROUNDDOWN(val, align) ((val) & ~(align-1)) +#define ROUNDUP(val, align) ROUNDDOWN(((val) + (align-1)), align) + +#define le16(i) ((((u16) ((i) & 0xFF)) << 8) | ((u16) (((i) & 0xFF00) >> 8))) +#define le32(i) ((((u32)le16((i) & 0xFFFF)) << 16) | ((u32)le16(((i) & 0xFFFF0000) >> 16))) +#define le64(i) ((((u64)le32((i) & 0xFFFFFFFFLL)) << 32) | ((u64)le32(((i) & 0xFFFFFFFF00000000LL) >> 32))) + +#ifdef __cplusplus +} +#endif + +#endif // __UTILS_H_ diff --git a/src/video/CVideo.cpp b/src/video/CVideo.cpp new file mode 100644 index 0000000..63d134b --- /dev/null +++ b/src/video/CVideo.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include +#include "CVideo.h" +#include "system/memory.h" +#include "shaders/Texture2DShader.h" +#include "shaders/ColorShader.h" +#include "shaders/Shader3D.h" +#include "shaders/ShaderFractalColor.h" +#include "shaders/FXAAShader.h" +#include "dynamic_libs/os_functions.h" + +CVideo::CVideo(s32 forceTvScanMode, s32 forceDrcScanMode) +{ + tvEnabled = false; + drcEnabled = false; + + //! allocate MEM2 command buffer memory + gx2CommandBuffer = MEM2_alloc(GX2_COMMAND_BUFFER_SIZE, 0x40); + + //! initialize GX2 command buffer + u32 gx2_init_attributes[9]; + gx2_init_attributes[0] = GX2_INIT_ATTRIB_CB_BASE; + gx2_init_attributes[1] = (u32)gx2CommandBuffer; + gx2_init_attributes[2] = GX2_INIT_ATTRIB_CB_SIZE; + gx2_init_attributes[3] = GX2_COMMAND_BUFFER_SIZE; + gx2_init_attributes[4] = GX2_INIT_ATTRIB_ARGC; + gx2_init_attributes[5] = 0; + gx2_init_attributes[6] = GX2_INIT_ATTRIB_ARGV; + gx2_init_attributes[7] = 0; + gx2_init_attributes[8] = GX2_INIT_ATTRIB_NULL; + GX2Init(gx2_init_attributes); + + //! GX2 resources are not used in this application but if needed, the allocator is setup + GX2RSetAllocator(&CVideo::GX2RAlloc, &CVideo::GX2RFree); + + u32 scanBufferSize = 0; + s32 scaleNeeded = 0; + + s32 tvScanMode = (forceTvScanMode >= 0) ? forceTvScanMode : GX2GetSystemTVScanMode(); + s32 drcScanMode = (forceDrcScanMode >= 0) ? forceDrcScanMode : GX2GetSystemDRCScanMode(); + + s32 tvRenderMode; + u32 tvWidth = 0; + u32 tvHeight = 0; + + switch(tvScanMode) + { + case GX2_TV_SCAN_MODE_480I: + case GX2_TV_SCAN_MODE_480P: + tvWidth = 854; + tvHeight = 480; + tvRenderMode = GX2_TV_RENDER_480_WIDE; + break; + case GX2_TV_SCAN_MODE_1080I: + case GX2_TV_SCAN_MODE_1080P: + tvWidth = 1920; + tvHeight = 1080; + tvRenderMode = GX2_TV_RENDER_1080; + break; + case GX2_TV_SCAN_MODE_720P: + default: + tvWidth = 1280; + tvHeight = 720; + tvRenderMode = GX2_TV_RENDER_720; + break; + } + + s32 tvAAMode = GX2_AA_MODE_1X; + s32 drcAAMode = GX2_AA_MODE_4X; + + //! calculate the scale factor for later texture resize + widthScaleFactor = 1.0f / (f32)tvWidth; + heightScaleFactor = 1.0f / (f32)tvHeight; + depthScaleFactor = widthScaleFactor; + + //! calculate the size needed for the TV scan buffer and allocate the buffer from bucket memory + GX2CalcTVSize(tvRenderMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE, &scanBufferSize, &scaleNeeded); + tvScanBuffer = MEMBucket_alloc(scanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT); + GX2Invalidate(GX2_INVALIDATE_CPU, tvScanBuffer, scanBufferSize); + GX2SetTVBuffer(tvScanBuffer, scanBufferSize, tvRenderMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE); + + //! calculate the size needed for the DRC scan buffer and allocate the buffer from bucket memory + GX2CalcDRCSize(drcScanMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE, &scanBufferSize, &scaleNeeded); + drcScanBuffer = MEMBucket_alloc(scanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT); + GX2Invalidate(GX2_INVALIDATE_CPU, drcScanBuffer, scanBufferSize); + GX2SetDRCBuffer(drcScanBuffer, scanBufferSize, drcScanMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE); + + //! Setup color buffer for TV rendering + GX2InitColorBuffer(&tvColorBuffer, GX2_SURFACE_DIM_2D, tvWidth, tvHeight, 1, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, tvAAMode); + tvColorBuffer.surface.image_data = MEM1_alloc(tvColorBuffer.surface.image_size, tvColorBuffer.surface.align); + GX2Invalidate(GX2_INVALIDATE_CPU, tvColorBuffer.surface.image_data, tvColorBuffer.surface.image_size); + + //! due to AA we can only use 16 bit depth buffer in MEM1 otherwise we would have to switch to mem2 for depth buffer + //! this should be ok for our purpose i guess + + //! Setup TV depth buffer (can be the same for both if rendered one after another) + u32 size, align; + GX2InitDepthBuffer(&tvDepthBuffer, GX2_SURFACE_DIM_2D, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 1, GX2_SURFACE_FORMAT_TCD_R32_FLOAT, tvAAMode); + tvDepthBuffer.surface.image_data = MEM1_alloc(tvDepthBuffer.surface.image_size, tvDepthBuffer.surface.align); + GX2Invalidate(GX2_INVALIDATE_CPU, tvDepthBuffer.surface.image_data, tvDepthBuffer.surface.image_size); + + //! Setup TV HiZ buffer + GX2CalcDepthBufferHiZInfo(&tvDepthBuffer, &size, &align); + tvDepthBuffer.hiZ_data = MEM1_alloc(size, align); + GX2Invalidate(GX2_INVALIDATE_CPU, tvDepthBuffer.hiZ_data, size); + GX2InitDepthBufferHiZEnable(&tvDepthBuffer, GX2_ENABLE); + + //! Setup color buffer for DRC rendering + GX2InitColorBuffer(&drcColorBuffer, GX2_SURFACE_DIM_2D, 854, 480, 1, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, drcAAMode); + drcColorBuffer.surface.image_data = MEM1_alloc(drcColorBuffer.surface.image_size, drcColorBuffer.surface.align); + GX2Invalidate(GX2_INVALIDATE_CPU, drcColorBuffer.surface.image_data, drcColorBuffer.surface.image_size); + + //! Setup DRC depth buffer (can be the same for both if rendered one after another) + GX2InitDepthBuffer(&drcDepthBuffer, GX2_SURFACE_DIM_2D, drcColorBuffer.surface.width, drcColorBuffer.surface.height, 1, GX2_SURFACE_FORMAT_TCD_R32_FLOAT, drcAAMode); + drcDepthBuffer.surface.image_data = MEM1_alloc(drcDepthBuffer.surface.image_size, drcDepthBuffer.surface.align); + GX2Invalidate(GX2_INVALIDATE_CPU, drcDepthBuffer.surface.image_data, drcDepthBuffer.surface.image_size); + + //! Setup DRC HiZ buffer + GX2CalcDepthBufferHiZInfo(&drcDepthBuffer, &size, &align); + drcDepthBuffer.hiZ_data = MEM1_alloc(size, align); + GX2Invalidate(GX2_INVALIDATE_CPU, drcDepthBuffer.hiZ_data, size); + GX2InitDepthBufferHiZEnable(&drcDepthBuffer, GX2_ENABLE); + + + //! allocate auxilary buffer last as there might not be enough MEM1 left for other stuff after that + if (tvColorBuffer.surface.aa) + { + u32 auxSize, auxAlign; + GX2CalcColorBufferAuxInfo(&tvColorBuffer, &auxSize, &auxAlign); + tvColorBuffer.aux_data = MEM1_alloc(auxSize, auxAlign); + if(!tvColorBuffer.aux_data) + tvColorBuffer.aux_data = MEM2_alloc(auxSize, auxAlign); + + tvColorBuffer.aux_size = auxSize; + memset(tvColorBuffer.aux_data, GX2_AUX_BUFFER_CLEAR_VALUE, auxSize); + GX2Invalidate(GX2_INVALIDATE_CPU, tvColorBuffer.aux_data, auxSize); + } + + if (drcColorBuffer.surface.aa) + { + u32 auxSize, auxAlign; + GX2CalcColorBufferAuxInfo(&drcColorBuffer, &auxSize, &auxAlign); + drcColorBuffer.aux_data = MEM1_alloc(auxSize, auxAlign); + if(!drcColorBuffer.aux_data) + drcColorBuffer.aux_data = MEM2_alloc(auxSize, auxAlign); + drcColorBuffer.aux_size = auxSize; + memset(drcColorBuffer.aux_data, GX2_AUX_BUFFER_CLEAR_VALUE, auxSize); + GX2Invalidate(GX2_INVALIDATE_CPU, drcColorBuffer.aux_data, auxSize ); + } + + //! allocate memory and setup context state TV + tvContextState = (GX2ContextState*)MEM2_alloc(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT); + GX2SetupContextStateEx(tvContextState, GX2_TRUE); + + //! allocate memory and setup context state DRC + drcContextState = (GX2ContextState*)MEM2_alloc(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT); + GX2SetupContextStateEx(drcContextState, GX2_TRUE); + + //! set initial context state and render buffers + GX2SetContextState(tvContextState); + GX2SetColorBuffer(&tvColorBuffer, GX2_RENDER_TARGET_0); + GX2SetDepthBuffer(&tvDepthBuffer); + + GX2SetContextState(drcContextState); + GX2SetColorBuffer(&drcColorBuffer, GX2_RENDER_TARGET_0); + GX2SetDepthBuffer(&drcDepthBuffer); + + //! set initial viewport + GX2SetViewport(0.0f, 0.0f, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 0.0f, 1.0f); + GX2SetScissor(0, 0, tvColorBuffer.surface.width, tvColorBuffer.surface.height); + + //! this is not necessary but can be used for swap counting and vsyncs + GX2SetSwapInterval(1); + + //GX2SetTVGamma(0.8f); + //GX2SetDRCGamma(0.8f); + + //! initialize perspective matrix + const float cam_X_rot = 25.0f; + + projectionMtx = glm::perspective(45.0f, 1.0f, 0.1f, 100.0f); + + viewMtx = glm::mat4(1.0f); + viewMtx = glm::translate(viewMtx, glm::vec3(0.0f, 0.0f, -2.5f)); + viewMtx = glm::rotate(viewMtx, DegToRad(cam_X_rot), glm::vec3(1.0f, 0.0f, 0.0f)); + + GX2InitSampler(&aaSampler, GX2_TEX_CLAMP_CLAMP, GX2_TEX_XY_FILTER_BILINEAR); + GX2InitTexture(&tvAaTexture, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 1, 0, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_DEFAULT); + tvAaTexture.surface.image_data = tvColorBuffer.surface.image_data; + tvAaTexture.surface.image_size = tvColorBuffer.surface.image_size; + tvAaTexture.surface.mip_data = tvColorBuffer.surface.mip_data; +} + +CVideo::~CVideo() +{ + //! flush buffers + GX2Flush(); + GX2DrawDone(); + //! shutdown + GX2Shutdown(); + //! free command buffer memory + MEM2_free(gx2CommandBuffer); + //! free scan buffers + MEMBucket_free(tvScanBuffer); + MEMBucket_free(drcScanBuffer); + //! free color buffers + MEM1_free(tvColorBuffer.surface.image_data); + MEM1_free(drcColorBuffer.surface.image_data); + //! free depth buffers + MEM1_free(tvDepthBuffer.surface.image_data); + MEM1_free(tvDepthBuffer.hiZ_data); + MEM1_free(drcDepthBuffer.surface.image_data); + MEM1_free(drcDepthBuffer.hiZ_data); + //! free context buffers + MEM2_free(tvContextState); + MEM2_free(drcContextState); + //! free aux buffer + if(tvColorBuffer.aux_data) + { + if(((u32)tvColorBuffer.aux_data & 0xF0000000) == 0xF0000000) + MEM1_free(tvColorBuffer.aux_data); + else + MEM2_free(tvColorBuffer.aux_data); + } + if(drcColorBuffer.aux_data) + { + if(((u32)drcColorBuffer.aux_data & 0xF0000000) == 0xF0000000) + MEM1_free(drcColorBuffer.aux_data); + else + MEM2_free(drcColorBuffer.aux_data); + } + //! destroy shaders + ColorShader::destroyInstance(); + FXAAShader::destroyInstance(); + Shader3D::destroyInstance(); + ShaderFractalColor::destroyInstance(); + Texture2DShader::destroyInstance(); +} + +void CVideo::renderFXAA(const GX2Texture * texture, const GX2Sampler *sampler) +{ + resolution[0] = texture->surface.width; + resolution[1] = texture->surface.height; + + GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER | GX2_INVALIDATE_TEXTURE, texture->surface.image_data, texture->surface.image_size); + + GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_ALWAYS); + FXAAShader::instance()->setShaders(); + FXAAShader::instance()->setAttributeBuffer(); + FXAAShader::instance()->setResolution(resolution); + FXAAShader::instance()->setTextureAndSampler(texture, sampler); + FXAAShader::instance()->draw(); + GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL); +} + +void* CVideo::GX2RAlloc(u32 flags, u32 size, u32 align) +{ + //! min. alignment + if (align < 4) + align = 4; + + if ((flags & 0x2040E) && !(flags & 0x40000)) + return MEM1_alloc(size, align); + else + return MEM2_alloc(size, align); +} + +void CVideo::GX2RFree(u32 flags, void* p) +{ + if ((flags & 0x2040E) && !(flags & 0x40000)) + MEM1_free(p); + else + MEM2_free(p); +} diff --git a/src/video/CVideo.h b/src/video/CVideo.h new file mode 100644 index 0000000..e9b457e --- /dev/null +++ b/src/video/CVideo.h @@ -0,0 +1,202 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef __CVIDEO_H_ +#define __CVIDEO_H_ + +#include "dynamic_libs/gx2_functions.h" +#include "shaders/Shader.h" + +class CVideo +{ +public: + CVideo(s32 forceTvScanMode = -1, s32 forceDrcScanMode = -1); + virtual ~CVideo(); + + void prepareTvRendering(void) { + currContextState = tvContextState; + currColorBuffer = &tvColorBuffer; + currDepthBuffer = &tvDepthBuffer; + prepareRendering(); + } + + void prepareDrcRendering(void) { + currContextState = drcContextState; + currColorBuffer = &drcColorBuffer; + currDepthBuffer = &drcDepthBuffer; + prepareRendering(); + } + + void prepareRendering(void) { + GX2ClearColor(currColorBuffer, 0.0f, 0.0f, 0.0f, 1.0f); + GX2ClearDepthStencilEx(currDepthBuffer, currDepthBuffer->clear_depth, currDepthBuffer->clear_stencil, GX2_CLEAR_BOTH); + + GX2SetContextState(currContextState); + GX2SetViewport(0.0f, 0.0f, currColorBuffer->surface.width, currColorBuffer->surface.height, 0.0f, 1.0f); + GX2SetScissor(0, 0, currColorBuffer->surface.width, currColorBuffer->surface.height); + + GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL); + GX2SetColorControl(GX2_LOGIC_OP_COPY, 1, GX2_DISABLE, GX2_ENABLE); + GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_SRC_ALPHA, GX2_BLEND_ONE_MINUS_SRC_ALPHA, GX2_BLEND_COMBINE_ADD, GX2_ENABLE, GX2_BLEND_SRC_ALPHA, GX2_BLEND_ONE_MINUS_SRC_ALPHA, GX2_BLEND_COMBINE_ADD); + GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, GX2_DISABLE, GX2_ENABLE); + } + + void setStencilRender(bool bEnable) + { + if(bEnable) + { + GX2SetStencilMask(0xff, 0xff, 0x01, 0xff, 0xff, 0x01); + GX2SetDepthStencilControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_LEQUAL, GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_ALWAYS, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_REPLACE, + GX2_COMPARE_ALWAYS, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_REPLACE); + } + else + { + GX2SetStencilMask(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); + GX2SetDepthStencilControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL, GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_NEVER, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, + GX2_COMPARE_NEVER, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP); + } + } + + void drcDrawDone(void) { + //! on DRC we do a hardware AA because FXAA does not look good + //renderFXAA(&drcAaTexture, &aaSampler); + GX2CopyColorBufferToScanBuffer(&drcColorBuffer, GX2_SCAN_TARGET_DRC_FIRST); + } + + void tvDrawDone(void) { + renderFXAA(&tvAaTexture, &aaSampler); + GX2CopyColorBufferToScanBuffer(&tvColorBuffer, GX2_SCAN_TARGET_TV); + GX2SwapScanBuffers(); + GX2Flush(); + } + + void waitForVSync(void) { + GX2WaitForVsync(); + frameCount++; + } + + void tvEnable(bool bEnable) { + if(tvEnabled != bEnable) + { + GX2SetTVEnable(bEnable ? GX2_ENABLE : GX2_DISABLE); + tvEnabled = bEnable; + } + } + void drcEnable(bool bEnable) { + if(drcEnabled != bEnable) + { + GX2SetDRCEnable(bEnable ? GX2_ENABLE : GX2_DISABLE); + drcEnabled = bEnable; + } + } + + u32 getFrameCount(void) const { + return frameCount; + } + + u32 getTvWidth(void) const { + return tvColorBuffer.surface.width; + } + u32 getTvHeight(void) const { + return tvColorBuffer.surface.height; + } + + u32 getDrcWidth(void) const { + return drcColorBuffer.surface.width; + } + u32 getDrcHeight(void) const { + return drcColorBuffer.surface.height; + } + + const glm::mat4 & getProjectionMtx(void) const { + return projectionMtx; + } + const glm::mat4 & getViewMtx(void) const { + return viewMtx; + } + + f32 getWidthScaleFactor(void) const { + return widthScaleFactor; + } + f32 getHeightScaleFactor(void) const { + return heightScaleFactor; + } + f32 getDepthScaleFactor(void) const { + return depthScaleFactor; + } + + void screenPosToWorldRay(f32 posX, f32 posY, glm::vec3 & rayOrigin, glm::vec3 & rayDirection) + { + //! normalize positions + posX = 2.0f * posX * getWidthScaleFactor(); + posY = 2.0f * posY * getHeightScaleFactor(); + + glm::vec4 rayStart(posX, posY, 0.0f, 1.0f); + glm::vec4 rayEnd(posX, posY, 1.0f, 1.0f); + + glm::mat4 IMV = glm::inverse(projectionMtx * viewMtx); + glm::vec4 rayStartWorld = IMV * rayStart; + rayStartWorld /= rayStartWorld.w; + + glm::vec4 rayEndWorld = IMV * rayEnd; + rayEndWorld /= rayEndWorld.w; + + glm::vec3 rayDirectionWorld(rayEndWorld - rayStartWorld); + rayDirectionWorld = glm::normalize(rayDirectionWorld); + + rayOrigin = glm::vec3(rayStartWorld); + rayDirection = glm::normalize(rayDirectionWorld); + } +private: + static void *GX2RAlloc(u32 flags, u32 size, u32 align); + static void GX2RFree(u32 flags, void* p); + + void renderFXAA(const GX2Texture * texture, const GX2Sampler *sampler); + + void *gx2CommandBuffer; + + void *tvScanBuffer; + void *drcScanBuffer; + + u32 frameCount; + f32 widthScaleFactor; + f32 heightScaleFactor; + f32 depthScaleFactor; + + bool tvEnabled; + bool drcEnabled; + + GX2ColorBuffer tvColorBuffer; + GX2DepthBuffer tvDepthBuffer; + GX2ColorBuffer drcColorBuffer; + GX2DepthBuffer drcDepthBuffer; + + GX2ContextState *tvContextState; + GX2ContextState *drcContextState; + + GX2ContextState *currContextState; + GX2ColorBuffer *currColorBuffer; + GX2DepthBuffer *currDepthBuffer; + + GX2Texture tvAaTexture; + GX2Sampler aaSampler; + + glm::mat4 projectionMtx; + glm::mat4 viewMtx; + glm::vec2 resolution; +}; + +#endif // __GX2_VIDEO_H_ diff --git a/src/video/shaders/ColorShader.cpp b/src/video/shaders/ColorShader.cpp new file mode 100644 index 0000000..d8e963e --- /dev/null +++ b/src/video/shaders/ColorShader.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include +#include "ColorShader.h" + +static const u32 cpVertexShaderProgram[] = +{ + 0x00000000,0x00008009,0x20000000,0x000078a0, + 0x3c200000,0x88060094,0x00c00000,0x88062014, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00a11f00,0xfc00620f,0x02490001,0x80000040, + 0xfd041f80,0x900c0060,0x83f9223e,0x0000803f, + 0xfe282001,0x10000040,0xfe001f80,0x00080060, + 0xfeac9f80,0xfd00624f,0xdb0f49c0,0xdb0fc940, + 0xfea81f80,0x9000e02f,0x83f9223e,0x00000000, + 0xfe041f80,0x00370000,0xffa01f00,0x80000000, + 0xff101f00,0x800c0020,0x7f041f80,0x80370000, + 0x0000103f,0x00000000,0x02c51f00,0x80000000, + 0xfea41f00,0x80000020,0xffa09f00,0x80000040, + 0xff001f80,0x800c0060,0x398ee33f,0x0000103f, + 0x02c41f00,0x9000e00f,0x02c59f01,0x80000020, + 0xfea81f00,0x80000040,0x02c19f80,0x9000e06f, + 0x398ee33f,0x00000000,0x02c11f01,0x80000000, + 0x02c49f80,0x80000060,0x02e08f01,0xfe0c620f, + 0x02c01f80,0x7f00622f,0xfe242000,0x10000000, + 0xfe20a080,0x10000020,0xf2178647,0x49c0e9fb, + 0xfbbdb2ab,0x768ac733 +}; + +static const u32 cpVertexShaderRegs[] = { + 0x00000103,0x00000000,0x00000000,0x00000001, + 0xffffff00,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0x00000000,0xfffffffc, + 0x00000002,0x00000001,0x00000000,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x00000000,0x0000000e,0x00000010 +}; + +static const u32 cpPixelShaderProgram[] = +{ + 0x20000000,0x00000ca0,0x00000000,0x88062094, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00002000,0x90000000,0x0004a000,0x90000020, + 0x00082001,0x90000040,0x000ca081,0x90000060, + 0xbb7dd898,0x9746c59c,0xc69b00e7,0x03c36218 +}; +static const u32 cpPixelShaderRegs[] = { + 0x00000001,0x00000002,0x14000001,0x00000000, + 0x00000001,0x00000100,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x0000000f,0x00000001,0x00000010, + 0x00000000 +}; + +ColorShader * ColorShader::shaderInstance = NULL; + +ColorShader::ColorShader() + : vertexShader(cuAttributeCount) +{ + //! create pixel shader + pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs)); + + colorIntensityLocation = 0; + pixelShader.addUniformVar((GX2UniformVar){ "unf_color_intensity", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff }); + + //! create vertex shader + vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs)); + + angleLocation = 0; + offsetLocation = 4; + scaleLocation = 8; + vertexShader.addUniformVar((GX2UniformVar){ "unf_angle", GX2_VAR_TYPE_FLOAT, 1, angleLocation, 0xffffffff }); + vertexShader.addUniformVar((GX2UniformVar){ "unf_offset", GX2_VAR_TYPE_VEC3, 1, offsetLocation, 0xffffffff }); + vertexShader.addUniformVar((GX2UniformVar){ "unf_scale", GX2_VAR_TYPE_VEC3, 1, scaleLocation, 0xffffffff }); + + colorLocation = 1; + positionLocation = 0; + vertexShader.addAttribVar((GX2AttribVar){ "attr_color", GX2_VAR_TYPE_VEC4, 0, colorLocation }); + vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation }); + + //! setup attribute streams + GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT); + GX2InitAttribStream(vertexShader.getAttributeBuffer(1), colorLocation, 1, 0, GX2_ATTRIB_FORMAT_8_8_8_8_UNORM); + + //! create fetch shader + fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount()); + + //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000 + positionVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, cuPositionVtxsSize); + if(positionVtxs) + { + //! position vertex structure + int i = 0; + positionVtxs[i++] = -1.0f; positionVtxs[i++] = -1.0f; positionVtxs[i++] = 0.0f; + positionVtxs[i++] = 1.0f; positionVtxs[i++] = -1.0f; positionVtxs[i++] = 0.0f; + positionVtxs[i++] = 1.0f; positionVtxs[i++] = 1.0f; positionVtxs[i++] = 0.0f; + positionVtxs[i++] = -1.0f; positionVtxs[i++] = 1.0f; positionVtxs[i++] = 0.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, positionVtxs, cuPositionVtxsSize); + } +} + +ColorShader::~ColorShader() +{ + if(positionVtxs) + { + free(positionVtxs); + positionVtxs = NULL; + } + + delete fetchShader; + fetchShader = NULL; +} diff --git a/src/video/shaders/ColorShader.h b/src/video/shaders/ColorShader.h new file mode 100644 index 0000000..35c13b6 --- /dev/null +++ b/src/video/shaders/ColorShader.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef __COLOR_SHADER_H_ +#define __COLOR_SHADER_H_ + +#include "VertexShader.h" +#include "PixelShader.h" +#include "FetchShader.h" + +class ColorShader : public Shader +{ +private: + ColorShader(); + virtual ~ColorShader(); + + static const u32 cuAttributeCount = 2; + static const u32 cuPositionVtxsSize = 4 * cuVertexAttrSize; + + static ColorShader *shaderInstance; + + FetchShader *fetchShader; + VertexShader vertexShader; + PixelShader pixelShader; + + f32 *positionVtxs; + + u32 angleLocation; + u32 offsetLocation; + u32 scaleLocation; + u32 colorLocation; + u32 colorIntensityLocation; + u32 positionLocation; +public: + static const u32 cuColorVtxsSize = 4 * cuColorAttrSize; + + static ColorShader *instance() { + if(!shaderInstance) { + shaderInstance = new ColorShader(); + } + return shaderInstance; + } + static void destroyInstance() { + if(shaderInstance) { + delete shaderInstance; + shaderInstance = NULL; + } + } + + void setShaders(void) const + { + fetchShader->setShader(); + vertexShader.setShader(); + pixelShader.setShader(); + } + + void setAttributeBuffer(const u8 * colorAttr, const f32 * posVtxs_in = NULL, const u32 & vtxCount = 0) const + { + if(posVtxs_in && vtxCount) { + VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in); + VertexShader::setAttributeBuffer(1, vtxCount * cuColorAttrSize, cuColorAttrSize, colorAttr); + } + else { + VertexShader::setAttributeBuffer(0, cuPositionVtxsSize, cuVertexAttrSize, positionVtxs); + VertexShader::setAttributeBuffer(1, cuColorVtxsSize, cuColorAttrSize, colorAttr); + } + } + + void setAngle(const float & val) + { + VertexShader::setUniformReg(angleLocation, 4, &val); + } + void setOffset(const glm::vec3 & vec) + { + VertexShader::setUniformReg(offsetLocation, 4, &vec[0]); + } + void setScale(const glm::vec3 & vec) + { + VertexShader::setUniformReg(scaleLocation, 4, &vec[0]); + } + void setColorIntensity(const glm::vec4 & vec) + { + PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]); + } +}; + +#endif // __COLOR_SHADER_H_ diff --git a/src/video/shaders/FXAAShader.cpp b/src/video/shaders/FXAAShader.cpp new file mode 100644 index 0000000..f86087b --- /dev/null +++ b/src/video/shaders/FXAAShader.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include +#include "FXAAShader.h" + +static const u32 cpVertexShaderProgram[] = +{ + 0x00000000,0x00008009,0x20000000,0x000004a0, + 0x3ca00000,0x88060094,0x00400000,0xff0f2094, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0xfd001f80,0x900c2060,0x0000803f,0x00000000, + 0xc1a229f5,0xd0eddc33,0x426618fd,0x8509cfe7 +}; + +static const u32 cpVertexShaderRegs[] = { + 0x00000102,0x00000000,0x00000000,0x00000001, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0x00000000,0xfffffffe, + 0x00000001,0x00000000,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x00000000,0x0000000e,0x00000010 +}; + +static const u32 cpPixelShaderProgram[] = +{ + 0x20000000,0x00003ca0,0xa0000000,0x000c8080, + 0x30000000,0x000010a1,0xa8000000,0x0010c080, + 0x75000000,0x000088a0,0x00800100,0x88062094, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00241f02,0x1000e00f,0x00241f00,0x1000e02f, + 0x00201f02,0x00000040,0x00201f00,0x00000060, + 0x00011f80,0x10332060,0xff000000,0xff102200, + 0xfd001f00,0x900cc020,0xffc09f01,0x90004040, + 0xffc01f01,0x90000060,0x00051f80,0x1033a040, + 0x0000803f,0x00000000,0xffe00f00,0x90004000, + 0xff008000,0xff102220,0xffe08f00,0x90000440, + 0x010c0000,0x010c4660,0xff008080,0xff004220, + 0x01a01f00,0x00280000,0x01a49f00,0x00280020, + 0x01a81f01,0x00280040,0xfd0c1f00,0x1028e06f, + 0x00208081,0x90002000,0x8716993e,0xa245163f, + 0xd578e93d,0x00000080,0x03a01f00,0x00280000, + 0x03a49f00,0x00280020,0x03a81f01,0x1028e04f, + 0xfd0c1f00,0x00280060,0x00a40081,0x90002020, + 0x8716993e,0xa245163f,0xd578e93d,0x00000080, + 0x04a01f00,0x00280000,0x04a49f00,0x1028a02f, + 0x04a81f01,0x00280040,0xfd0c1f00,0x00280060, + 0x7fcc1f80,0x1000c02f,0x8716993e,0xa245163f, + 0xd578e93d,0x00000080,0x02a01f00,0x1028e00f, + 0x02a49f00,0x00280020,0x02a81f01,0x00280040, + 0xfd0c1f00,0x00280060,0x7fcc1f80,0x1000e02f, + 0x8716993e,0xa245163f,0xd578e93d,0x00000080, + 0x7dc41f00,0x00020000,0x7fec0f01,0x00020020, + 0x7fc81f00,0x00000040,0x7dc41f00,0x00000060, + 0x7fec0f81,0x9001802f,0xfef88f00,0x1000e00f, + 0xfedc8f00,0x00000420,0x7de40f00,0x80010040, + 0x7ec49f01,0x00001060,0xfec41f80,0x10024060, + 0xfed49f00,0x80020000,0xfe141f00,0x900c802f, + 0xfeac1f00,0x80000040,0xfec01f02,0x80020060, + 0x7cc41f81,0x90010060,0x0000003d,0x00000000, + 0xfd001f00,0x900c6000,0xfea89f00,0x80010020, + 0xfec09f81,0x00020040,0x0000803f,0x0000003e, + 0xfec41f81,0x00000020,0xfe041f80,0x00330000, + 0x7fe01f00,0x80000040,0x7ce41f80,0x80000060, + 0xfea81f00,0x80010000,0xfeac1f80,0x80010020, + 0x000000c1,0x00000000,0xfea01f00,0x00020040, + 0xfea41f80,0x00020060,0x00000041,0x00000000, + 0x05c81f01,0x9000e00f,0x01cc9f81,0x9000e06f, + 0xfeac1f00,0x01004200,0xfea01f00,0x01044220, + 0xfeac9f00,0x01002240,0xfea09f00,0x01042260, + 0xfe8c1f80,0x01008600,0xacaa2a3e,0xaaaa2abe, + 0x7f9c1f00,0x0100a200,0x7f801f00,0x01048220, + 0x7f901f80,0x0104a240,0x02080001,0x7000a00f, + 0x02000000,0x7000c04f,0x02048000,0x7000e06f, + 0x01a81f80,0x9000e00f,0xd578e93d,0x00000000, + 0x04a80001,0x1000c00f,0x04a48000,0x00000020, + 0x04a00000,0x00000040,0xfe081f00,0xe00c0060, + 0xfe0c1f80,0xe00c0000,0x01a41f00,0x7f00620f, + 0xfea89f00,0xfe0c822f,0xfea49f00,0xff00a24f, + 0x7d001f80,0xe00c0060,0xa245163f,0x0000803e, + 0x7ea01f00,0xfe0ce20f,0x01a09f80,0xfe006a4f, + 0x0000803e,0x8716993e,0xfe088001,0x9001c00f, + 0xfe488001,0x1002e44f,0xfea01f80,0x80000000, + 0xd578e93d,0x00000000,0x7ca41f00,0x00280000, + 0x7da89f00,0x00280020,0xff201f00,0x00280040, + 0xfd081f80,0x00280060,0x8716993e,0xa245163f, + 0x00000080,0x00000000,0x7fc81f00,0x80060000, + 0xfec00f80,0x80060060,0xfec09f81,0xfb80634f, + 0xfe888f00,0x7e886300,0xfea80f01,0x7f8c6320, + 0xfee80f00,0x7d806340,0xfe680080,0x06846f60, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x10000100,0x01101df0,0x00008010,0xecdfea0d, + 0x10000200,0x03101df0,0x00002050,0xecdfea0d, + 0x10000000,0x04101df0,0x00003071,0xecdfea0d, + 0x10000200,0x02101df0,0x0000b070,0xecdfea0d, + 0x10000200,0x02101df0,0x00008010,0xecdfea0d, + 0x10000100,0x00101df0,0x0000a051,0xecdfea0d, + 0x10000400,0x04101df0,0x00008010,0xecdfea0d, + 0x10000500,0x05101df0,0x00000011,0xecdfea0d, + 0x10000100,0x01101df0,0x00008010,0xecdfea0d, + 0xfe2e963a,0x0269a9a3,0x38f88096,0x400cf48b +}; +static const u32 cpPixelShaderRegs[] = { + 0x00000007,0x00000002,0x04000101,0x00000000, + 0x00000001,0x00000100,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x0000000f,0x00000001,0x00000010, + 0x00000000 +}; + +FXAAShader * FXAAShader::shaderInstance = NULL; + +FXAAShader::FXAAShader() + : vertexShader(cuAttributeCount) +{ + //! create pixel shader + pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs)); + + resolutionLocation = 0; + pixelShader.addUniformVar((GX2UniformVar){ "unf_resolution", GX2_VAR_TYPE_VEC2, 1, resolutionLocation, 0xffffffff }); + + samplerLocation = 0; + pixelShader.addSamplerVar((GX2SamplerVar){ "sampl_texture", GX2_SAMPLER_TYPE_2D, samplerLocation }); + + //! create vertex shader + vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs)); + + positionLocation = 0; + texCoordLocation = 1; + vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation }); + vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation }); + + //! setup attribute streams + GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT); + GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT); + + //! create fetch shader + fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount()); + + //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000 + posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize); + texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize); + + //! position vertex structure and texture coordinate vertex structure + int i = 0; + posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize); + + i = 0; + texCoords[i++] = 0.0f; texCoords[i++] = 1.0f; + texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; + texCoords[i++] = 1.0f; texCoords[i++] = 0.0f; + texCoords[i++] = 0.0f; texCoords[i++] = 0.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize); +} + +FXAAShader::~FXAAShader() +{ + if(posVtxs) + { + free(posVtxs); + posVtxs = NULL; + } + if(texCoords) + { + free(texCoords); + texCoords = NULL; + } + + delete fetchShader; + fetchShader = NULL; +} diff --git a/src/video/shaders/FXAAShader.h b/src/video/shaders/FXAAShader.h new file mode 100644 index 0000000..b7604bc --- /dev/null +++ b/src/video/shaders/FXAAShader.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef __FXAA_SHADER_H_ +#define __FXAA_SHADER_H_ + +#include "VertexShader.h" +#include "PixelShader.h" +#include "FetchShader.h" + +class FXAAShader : public Shader +{ +public: + static FXAAShader *instance() { + if(!shaderInstance) { + shaderInstance = new FXAAShader(); + } + return shaderInstance; + } + static void destroyInstance() { + if(shaderInstance) { + delete shaderInstance; + shaderInstance = NULL; + } + } + + void setShaders(void) const + { + fetchShader->setShader(); + vertexShader.setShader(); + pixelShader.setShader(); + } + + void setAttributeBuffer() const + { + VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs); + VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords); + } + + void setResolution(const glm::vec2 & vec) + { + PixelShader::setUniformReg(resolutionLocation, 4, &vec[0]); + } + + void setTextureAndSampler(const GX2Texture *texture, const GX2Sampler *sampler) const { + GX2SetPixelTexture(texture, samplerLocation); + GX2SetPixelSampler(sampler, samplerLocation); + } + +private: + FXAAShader(); + virtual ~FXAAShader(); + + static const u32 cuAttributeCount = 2; + static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize; + static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize; + + static FXAAShader *shaderInstance; + + FetchShader *fetchShader; + VertexShader vertexShader; + PixelShader pixelShader; + + f32 *posVtxs; + f32 *texCoords; + + u32 samplerLocation; + u32 positionLocation; + u32 texCoordLocation; + u32 resolutionLocation; +}; + +#endif // __FXAA_SHADER_H_ diff --git a/src/video/shaders/FetchShader.h b/src/video/shaders/FetchShader.h new file mode 100644 index 0000000..292052f --- /dev/null +++ b/src/video/shaders/FetchShader.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef FETCH_SHADER_H +#define FETCH_SHADER_H + +#include "Shader.h" + +class FetchShader : public Shader +{ +public: + FetchShader(GX2AttribStream * attributes, u32 attrCount, s32 type = GX2_FETCH_SHADER_TESSELATION_NONE, s32 tess = GX2_TESSELLATION_MODE_DISCRETE) + : fetchShader(NULL) + , fetchShaderProgramm(NULL) + { + u32 shaderSize = GX2CalcFetchShaderSizeEx(attrCount, type, tess); + fetchShaderProgramm = memalign(GX2_SHADER_ALIGNMENT, shaderSize); + if(fetchShaderProgramm) + { + fetchShader = new GX2FetchShader; + GX2InitFetchShaderEx(fetchShader, fetchShaderProgramm, attrCount, attributes, type, tess); + GX2Invalidate(GX2_INVALIDATE_CPU_SHADER, fetchShaderProgramm, shaderSize); + } + } + virtual ~FetchShader() { + if(fetchShaderProgramm) + free(fetchShaderProgramm); + if(fetchShader) + delete fetchShader; + } + + GX2FetchShader *getFetchShader() const { + return fetchShader; + } + + void setShader(void) const { + GX2SetFetchShader(fetchShader); + } + +protected: + GX2FetchShader *fetchShader; + void *fetchShaderProgramm; +}; + +#endif // FETCH_SHADER_H diff --git a/src/video/shaders/PixelShader.h b/src/video/shaders/PixelShader.h new file mode 100644 index 0000000..a1fa76b --- /dev/null +++ b/src/video/shaders/PixelShader.h @@ -0,0 +1,150 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef PIXEL_SHADER_H +#define PIXEL_SHADER_H + +#include "Shader.h" + +class PixelShader : public Shader +{ +public: + PixelShader() + : pixelShader((GX2PixelShader*) memalign(0x40, sizeof(GX2PixelShader))) + { + if(pixelShader) + { + memset(pixelShader, 0, sizeof(GX2PixelShader)); + pixelShader->shader_mode = GX2_SHADER_MODE_UNIFORM_REGISTER; + } + } + virtual ~PixelShader() + { + if(pixelShader) + { + if(pixelShader->shader_data) + free(pixelShader->shader_data); + + for(u32 i = 0; i < pixelShader->uniform_blocks_count; i++) + free((void*)pixelShader->uniform_block[i].name); + + if(pixelShader->uniform_block) + free((void*)pixelShader->uniform_block); + + for(u32 i = 0; i < pixelShader->uniform_vars_count; i++) + free((void*)pixelShader->uniform_var[i].name); + + if(pixelShader->uniform_var) + free((void*)pixelShader->uniform_var); + + if(pixelShader->initial_value) + free((void*)pixelShader->initial_value); + + for(u32 i = 0; i < pixelShader->sampler_vars_count; i++) + free((void*)pixelShader->sampler_var[i].name); + + if(pixelShader->sampler_var) + free((void*)pixelShader->sampler_var); + + if(pixelShader->loops_data) + free((void*)pixelShader->loops_data); + + free(pixelShader); + } + } + + void setProgram(const u32 * program, const u32 & programSize, const u32 * regs, const u32 & regsSize) + { + if(!pixelShader) + return; + + //! this must be moved into an area where the graphic engine has access to and must be aligned to 0x100 + pixelShader->shader_size = programSize; + pixelShader->shader_data = memalign(GX2_SHADER_ALIGNMENT, pixelShader->shader_size); + if(pixelShader->shader_data) + { + memcpy(pixelShader->shader_data, program, pixelShader->shader_size); + GX2Invalidate(GX2_INVALIDATE_CPU_SHADER, pixelShader->shader_data, pixelShader->shader_size); + } + + memcpy(pixelShader->regs, regs, regsSize); + } + + void addUniformVar(const GX2UniformVar & var) + { + if(!pixelShader) + return; + + u32 idx = pixelShader->uniform_vars_count; + + GX2UniformVar* newVar = (GX2UniformVar*) malloc((pixelShader->uniform_vars_count + 1) * sizeof(GX2UniformVar)); + if(newVar) + { + if(pixelShader->uniform_var) + { + memcpy(newVar, pixelShader->uniform_var, pixelShader->uniform_vars_count * sizeof(GX2UniformVar)); + free(pixelShader->uniform_var); + } + pixelShader->uniform_var = newVar; + + memcpy(pixelShader->uniform_var + idx, &var, sizeof(GX2UniformVar)); + pixelShader->uniform_var[idx].name = (char*) malloc(strlen(var.name) + 1); + strcpy((char*)pixelShader->uniform_var[idx].name, var.name); + + pixelShader->uniform_vars_count++; + } + } + + void addSamplerVar(const GX2SamplerVar & var) + { + if(!pixelShader) + return; + + u32 idx = pixelShader->sampler_vars_count; + + GX2SamplerVar* newVar = (GX2SamplerVar*) malloc((pixelShader->sampler_vars_count + 1) * sizeof(GX2SamplerVar)); + if(newVar) + { + if(pixelShader->sampler_var) + { + memcpy(newVar, pixelShader->sampler_var, pixelShader->sampler_vars_count * sizeof(GX2SamplerVar)); + free(pixelShader->sampler_var); + } + pixelShader->sampler_var = newVar; + + memcpy(pixelShader->sampler_var + idx, &var, sizeof(GX2SamplerVar)); + pixelShader->sampler_var[idx].name = (char*) malloc(strlen(var.name) + 1); + strcpy((char*)pixelShader->sampler_var[idx].name, var.name); + + pixelShader->sampler_vars_count++; + } + } + GX2PixelShader * getPixelShader() const { + return pixelShader; + } + + void setShader(void) const { + GX2SetPixelShader(pixelShader); + } + + static inline void setUniformReg(u32 location, u32 size, const void * reg) { + GX2SetPixelUniformReg(location, size, reg); + } +protected: + GX2PixelShader *pixelShader; +}; + +#endif // PIXEL_SHADER_H diff --git a/src/video/shaders/Shader.h b/src/video/shaders/Shader.h new file mode 100644 index 0000000..93741d5 --- /dev/null +++ b/src/video/shaders/Shader.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef SHADER_H_ +#define SHADER_H_ + +#include "glm/glm.hpp" +#include "glm/gtc/matrix_transform.hpp" +#include "dynamic_libs/gx2_functions.h" +#include "utils/utils.h" + +class Shader +{ +protected: + Shader() {} + virtual ~Shader() {} +public: + static const u16 cuVertexAttrSize = sizeof(f32) * 3; + static const u16 cuTexCoordAttrSize = sizeof(f32) * 2; + static const u16 cuColorAttrSize = sizeof(u8) * 4; + + static void setLineWidth(const f32 & width) { + GX2SetLineWidth(width); + } + + static void draw(s32 primitive = GX2_PRIMITIVE_QUADS, u32 vtxCount = 4) + { + switch(primitive) + { + default: + case GX2_PRIMITIVE_QUADS: + { + GX2DrawEx(GX2_PRIMITIVE_QUADS, vtxCount, 0, 1); + break; + } + case GX2_PRIMITIVE_TRIANGLES: + { + GX2DrawEx(GX2_PRIMITIVE_TRIANGLES, vtxCount, 0, 1); + break; + } + case GX2_PRIMITIVE_TRIANGLE_FAN: + { + GX2DrawEx(GX2_PRIMITIVE_TRIANGLE_FAN, vtxCount, 0, 1); + break; + } + case GX2_PRIMITIVE_LINES: + { + GX2DrawEx(GX2_PRIMITIVE_LINES, vtxCount, 0, 1); + break; + } + case GX2_PRIMITIVE_LINE_STRIP: + { + GX2DrawEx(GX2_PRIMITIVE_LINE_STRIP, vtxCount, 0, 1); + break; + } + //! TODO: add other primitives later + }; + } +}; + +#endif // SHADER_H_ diff --git a/src/video/shaders/Shader3D.cpp b/src/video/shaders/Shader3D.cpp new file mode 100644 index 0000000..6857cd1 --- /dev/null +++ b/src/video/shaders/Shader3D.cpp @@ -0,0 +1,266 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include +#include "Shader3D.h" + +static const u32 cpVertexShaderProgram[] = +{ + 0x00000000,0x00008009,0x20000000,0x0000e4a1, + 0x00c00100,0x88048093,0x01c00300,0x98060014, + 0x9a000000,0x000058a0,0x3c200200,0x88062094, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x0765a101,0x9000e00f,0x0761a101,0x9000e02f, + 0x01081f00,0x900ce040,0x01041f00,0x900ce060, + 0x01001f80,0x900ce000,0x02001f00,0x900c6000, + 0x02041f00,0x900c6020,0x076da101,0x9000e04f, + 0x0769a181,0x9000e06f,0x0745a101,0x9000c00f, + 0x0741a181,0x9000c02f,0x074da101,0x9000c04f, + 0x0749a181,0x9000c06f,0x0bc9a000,0x7f00e20f, + 0x0bc92080,0x7f04e22f,0x0bc9a001,0x7f08e24f, + 0x0bc92081,0x7f0ce26f,0x0725a101,0x9000a00f, + 0x0721a181,0x9000a02f,0x072da101,0x9000a04f, + 0x0729a181,0x9000a06f,0x0ac9a000,0x7e00c20f, + 0x0ac92080,0x7e04c22f,0x0ac9a001,0x7e08c24f, + 0x0ac92081,0x7e0cc26f,0x0ba5a000,0x7f00e20f, + 0x0ba52080,0x7f04e22f,0x0ba5a001,0x7f08e24f, + 0x0ba52081,0x7f0ce26f,0x08eda000,0x9000800f, + 0x08ed2080,0x9000802f,0x08eda001,0x9000804f, + 0x08ed2081,0x9000806f,0x09c9a000,0x7d00a20f, + 0x09c92080,0x7d04a22f,0x09c9a001,0x7d08a24f, + 0x09c92081,0x7d0ca26f,0x0aa5a000,0x7e00c20f, + 0x0aa52080,0x7e04c22f,0x0aa5a001,0x7e08c24f, + 0x0aa52081,0x7e0cc26f,0x0b81a000,0x7f004200, + 0x0b812080,0x7f044220,0x0b81a001,0x7f082240, + 0x0b812081,0x7f0c0260,0x08c9a000,0x7c00820f, + 0x08c92080,0x7c04822f,0x08c9a001,0x7c08824f, + 0x08c92081,0x7c0c826f,0x09a5a000,0x7d00a20f, + 0x09a52080,0x7d04a22f,0x09a5a001,0x7d08a24f, + 0x09a52081,0x7d0ca26f,0x0a81a000,0x7e000200, + 0x0a812080,0x7e040220,0x0a81a001,0x7e080240, + 0x0a812081,0x7e0c2260,0x0240a001,0x9000c00f, + 0x0244a001,0x9000c02f,0x0148a001,0x9000c04f, + 0x004ca001,0x9000c06f,0x0264a081,0x9000e02f, + 0x0260a001,0x9000e00f,0x0224a001,0x90002020, + 0x0168a001,0x9000e04f,0x006ca001,0x9000e06f, + 0x0220a081,0x90002000,0x08a5a000,0x7c00820f, + 0x08a52080,0x7c04822f,0x08a5a001,0x7c08824f, + 0x08a52081,0x7c0c826f,0x0981a000,0x7d008200, + 0x09812080,0x7d048220,0x0981a001,0x7d084240, + 0x09812081,0x7d0c4260,0x02090000,0x7e00c20f, + 0x02098000,0x7e04c22f,0x0128a001,0x9000a04f, + 0x002ca001,0x9000c06f,0x02298081,0x7e0caa6f, + 0x03090000,0x7f00e20f,0x03098000,0x7f04e22f, + 0x02090001,0x7e08f64f,0x03298001,0x7f0ce26f, + 0x03090081,0x7f08ca4f,0x0881a000,0x7c00c200, + 0x08812080,0x7c04e220,0x0881a001,0x7c08a240, + 0x08812081,0x7c0c8260,0x0200a001,0x9000800f, + 0x0204a001,0x9000802f,0x0108a001,0x9000804f, + 0x000ca001,0x9000806f,0x01098080,0x0104aa2f, + 0x01090000,0x0100a20f,0x02858000,0x7e04c22f, + 0x01090001,0x7d08a24f,0x01298081,0x7e0cc26f, + 0x02850000,0x7e00f60f,0x03858000,0x7f04622f, + 0x02450001,0x7f08e24f,0x02458001,0x7d0ca26f, + 0x03850080,0x7f00ca0f,0x00090000,0x7c004200, + 0x00098000,0x7c04b220,0x03450001,0x7e08c24f, + 0x03458001,0x7f0ce26f,0x03e18080,0xfe042620, + 0x01850000,0x7d00a200,0x01858000,0x7d04622f, + 0x00090001,0x7c086240,0x00298081,0x7c0c0260, + 0x02c10000,0x7f000200,0x02e18000,0x7e040620, + 0x01450001,0x7d088240,0x01458001,0x7e0c6260, + 0x01e18080,0xfe04c620,0x03c10000,0x7e002200, + 0x03818001,0x7f0c4220,0x02a10001,0x7f081640, + 0x02818001,0x7d0c3660,0x03a10081,0x7e082a40, + 0x07080000,0x0100c20f,0x07088000,0x0104622f, + 0x00458001,0x000cea4f,0x07288081,0x0204f66f, + 0x00850000,0x0200620f,0x00858000,0x05046a2f, + 0x07080001,0x0108c24f,0x01818001,0x030c726f, + 0x07cc8080,0xfe04c22f,0x01c10000,0x0500660f, + 0x00e18000,0xfe04622f,0x00450001,0x0308624f, + 0x07cc9f01,0x7f0ce26f,0x00c10080,0xfe00e60f, + 0x07cc1f00,0x7e00660f,0x00a10001,0xfe08c22f, + 0x01a10001,0x0408624f,0x00818001,0x7f086a6f, + 0x07c09f80,0x7e048200,0x07e00f00,0xfe008220, + 0x07cc1f01,0x7e086a4f,0x07c09f81,0x7f0c8240, + 0x07c08f80,0xfe088260,0x2c34800d,0xe3b4f15e, + 0x7642ed30,0x7408600d +}; + +static const u32 cpVertexShaderRegs[] = { + 0x00000108,0x00000000,0x00000002,0x00000001, + 0xffff0001,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0x00000000,0xfffffffc, + 0x00000002,0x00000000,0x00000001,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x00000000,0x0000000e,0x00000010 +}; + +static const u32 cPixelShaderProgram[] = +{ + 0x20000000,0x000008a4,0x03000000,0x01004085, + 0x23000000,0x000044a8,0x35000000,0x000000a4, + 0x06000000,0x01004085,0x36000000,0x00002ca8, + 0x50000000,0x0000c080,0x42000000,0x00001ca0, + 0x00800000,0x88062094,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0xfd001f80,0x900c0060,0x0000803f,0x00000000, + 0x02011f80,0x8c110000,0xf8402000,0x9006a00f, + 0x02552001,0x00000020,0x01248082,0x80020060, + 0xfe3c1f00,0x1000e04f,0xfe041f80,0x1033c00f, + 0xfe482081,0x80060020,0xfee40f81,0x0289e30f, + 0x02c51f80,0x80060060,0xfeec0f80,0x0285634f, + 0xfec80f80,0x80000060,0xfe4ca081,0x9000e04f, + 0xfe281f00,0x80060000,0xf8c01f81,0x9006e02f, + 0xfee00f81,0xfd80636f,0x0000803f,0x00000000, + 0x7fc49f81,0xf880e34f,0xfe381f80,0x00000000, + 0x7de00f81,0xfe800360,0x01011f80,0x8c100000, + 0x00a81f00,0x9000e02f,0x00000082,0x80020060, + 0x00002040,0x00000000,0xfeac9f80,0xfd00624f, + 0x3333333f,0x00002040,0xfee88f80,0x0101620f, + 0x00cc1f80,0x9000e06f,0xf8c09f01,0x80060020, + 0xfe2c1f80,0x9006e04f,0xfee48f81,0xf880630f, + 0x7fc81f80,0xfd800360,0x0000803f,0x00000000, + 0x000ca001,0x80000000,0x00091f00,0x800c0020, + 0x00051f00,0x800c0040,0x00011f80,0x800c0060, + 0xfe2c0000,0x90002000,0xfe288000,0x90002020, + 0xfe240001,0x90002040,0xfe208081,0x90002060, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x10000100,0x01100df0,0x00008010,0xecdfea0d, + 0x99720984,0x041cab0d,0xa28a9ccd,0x95d199a5 +}; +static const u32 cPixelShaderRegs[] = { + 0x00000102,0x00000002,0x14000002,0x00000000, + 0x00000002,0x00000100,0x00000101,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x0000000f,0x00000001,0x00000010, + 0x00000000 +}; + +Shader3D * Shader3D::shaderInstance = NULL; + +Shader3D::Shader3D() + : vertexShader(cuAttributeCount) +{ + //! create pixel shader + pixelShader.setProgram(cPixelShaderProgram, sizeof(cPixelShaderProgram), cPixelShaderRegs, sizeof(cPixelShaderRegs)); + + colorIntensityLocation = 0; + fadeDistanceLocation = 4; + fadeOutLocation = 8; + pixelShader.addUniformVar((GX2UniformVar){ "unf_color_intensity", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff }); + pixelShader.addUniformVar((GX2UniformVar){ "unf_fade_distance", GX2_VAR_TYPE_FLOAT, 1, fadeDistanceLocation, 0xffffffff }); + pixelShader.addUniformVar((GX2UniformVar){ "unf_fade_out_alpha", GX2_VAR_TYPE_VEC4, 1, fadeOutLocation, 0xffffffff }); + + samplerLocation = 0; + pixelShader.addSamplerVar((GX2SamplerVar){ "sampl_texture", GX2_SAMPLER_TYPE_2D, samplerLocation }); + + //! create vertex shader + vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs)); + + modelMatrixLocation = 0; + projectionMatrixLocation = 16; + viewMatrixLocation = 32; + vertexShader.addUniformVar((GX2UniformVar){ "modelMatrix", GX2_VAR_TYPE_MAT4, 1, modelMatrixLocation, 0xffffffff }); + vertexShader.addUniformVar((GX2UniformVar){ "viewMatrix", GX2_VAR_TYPE_MAT4, 1, projectionMatrixLocation, 0xffffffff }); + vertexShader.addUniformVar((GX2UniformVar){ "projectionMatrix", GX2_VAR_TYPE_MAT4, 1, viewMatrixLocation, 0xffffffff }); + + positionLocation = 0; + texCoordLocation = 1; + vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation }); + vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation }); + + //! setup attribute streams + GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT); + GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT); + + //! create fetch shader + fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount()); + + //! initialize default quad texture vertexes as those are very commonly used + //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000 + posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize); + texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize); + + //! position vertex structure and texture coordinate vertex structure + int i = 0; + posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize); + + i = 0; + texCoords[i++] = 0.0f; texCoords[i++] = 1.0f; + texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; + texCoords[i++] = 1.0f; texCoords[i++] = 0.0f; + texCoords[i++] = 0.0f; texCoords[i++] = 0.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize); +} + +Shader3D::~Shader3D() +{ + if(posVtxs) + { + free(posVtxs); + posVtxs = NULL; + } + if(texCoords) + { + free(texCoords); + texCoords = NULL; + } + + delete fetchShader; + fetchShader = NULL; +} diff --git a/src/video/shaders/Shader3D.h b/src/video/shaders/Shader3D.h new file mode 100644 index 0000000..7289152 --- /dev/null +++ b/src/video/shaders/Shader3D.h @@ -0,0 +1,119 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef SHADER_3D_H_ +#define SHADER_3D_H_ + +#include "VertexShader.h" +#include "PixelShader.h" +#include "FetchShader.h" + +class Shader3D : public Shader +{ +private: + Shader3D(); + virtual ~Shader3D(); + + static Shader3D * shaderInstance; + + static const unsigned char cuAttributeCount = 2; + static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize; + static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize; + + FetchShader *fetchShader; + VertexShader vertexShader; + PixelShader pixelShader; + + f32 *posVtxs; + f32 *texCoords; + + u32 modelMatrixLocation; + u32 viewMatrixLocation; + u32 projectionMatrixLocation; + u32 positionLocation; + u32 texCoordLocation; + + u32 colorIntensityLocation; + u32 fadeDistanceLocation; + u32 fadeOutLocation; + u32 samplerLocation; +public: + static Shader3D *instance() { + if(!shaderInstance) { + shaderInstance = new Shader3D(); + } + return shaderInstance; + } + static void destroyInstance() { + if(shaderInstance) { + delete shaderInstance; + shaderInstance = NULL; + } + } + + void setShaders(void) const + { + fetchShader->setShader(); + vertexShader.setShader(); + pixelShader.setShader(); + } + + void setAttributeBuffer(const u32 & vtxCount = 0, const f32 * posVtxs_in = NULL, const f32 * texCoords_in = NULL) const + { + if(posVtxs_in && texCoords_in && vtxCount) + { + VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in); + VertexShader::setAttributeBuffer(1, vtxCount * cuTexCoordAttrSize, cuTexCoordAttrSize, texCoords_in); + } + else { + //! use default quad vertex and texture coordinates if nothing is passed + VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs); + VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords); + } + } + + void setProjectionMtx(const glm::mat4 & mtx) + { + VertexShader::setUniformReg(projectionMatrixLocation, 16, &mtx[0][0]); + } + void setViewMtx(const glm::mat4 & mtx) + { + VertexShader::setUniformReg(viewMatrixLocation, 16, &mtx[0][0]); + } + void setModelViewMtx(const glm::mat4 & mtx) + { + VertexShader::setUniformReg(modelMatrixLocation, 16, &mtx[0][0]); + } + void setColorIntensity(const glm::vec4 & vec) + { + PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]); + } + void setAlphaFadeOut(const glm::vec4 & vec) + { + PixelShader::setUniformReg(fadeOutLocation, 4, &vec[0]); + } + void setDistanceFadeOut(const float & value) + { + PixelShader::setUniformReg(fadeDistanceLocation, 4, &value); + } + + void setTextureAndSampler(const GX2Texture *texture, const GX2Sampler *sampler) const { + GX2SetPixelTexture(texture, samplerLocation); + GX2SetPixelSampler(sampler, samplerLocation); + } +}; + +#endif // SHADER_3D_H_ diff --git a/src/video/shaders/ShaderFractalColor.cpp b/src/video/shaders/ShaderFractalColor.cpp new file mode 100644 index 0000000..7e8624c --- /dev/null +++ b/src/video/shaders/ShaderFractalColor.cpp @@ -0,0 +1,373 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include +#include "ShaderFractalColor.h" + +static const u32 cpVertexShaderProgram[] = +{ + 0x00000000,0x00008009,0x20000000,0x0000eca1, + 0x00c00000,0x88068093,0x01400200,0x9a048013, + 0x9c000000,0x000044a0,0x3c200000,0x88060094, + 0x02400000,0x88062014,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x0765a101,0x9000e00f,0x0761a101,0x9000e02f, + 0x03001f00,0x900c8040,0x03041f80,0x900c8060, + 0x076da101,0x9000e04f,0x0769a181,0x9000e06f, + 0x0745a101,0x9000c00f,0x0741a181,0x9000c02f, + 0x074da101,0x9000c04f,0x0749a181,0x9000c06f, + 0x0bc9a000,0x7f00e20f,0x0bc92080,0x7f04e22f, + 0x0bc9a001,0x7f08e24f,0x0bc92081,0x7f0ce26f, + 0x0725a101,0x9000a00f,0x0721a181,0x9000a02f, + 0x072da101,0x9000a04f,0x0729a181,0x9000a06f, + 0x0ac9a000,0x7e00c20f,0x0ac92080,0x7e04c22f, + 0x0ac9a001,0x7e08c24f,0x0ac92081,0x7e0cc26f, + 0x0ba5a000,0x7f00e20f,0x0ba52080,0x7f04e22f, + 0x0ba5a001,0x7f08e24f,0x0ba52081,0x7f0ce26f, + 0x08eda000,0x9000800f,0x08ed2080,0x9000802f, + 0x08eda001,0x9000804f,0x08ed2081,0x9000806f, + 0x09c9a000,0x7d00a20f,0x09c92080,0x7d04a22f, + 0x09c9a001,0x7d08a24f,0x09c92081,0x7d0ca26f, + 0x0aa5a000,0x7e00c20f,0x0aa52080,0x7e04c22f, + 0x0aa5a001,0x7e08c24f,0x0aa52081,0x7e0cc26f, + 0x0b81a000,0x7f006200,0x0b812080,0x7f046220, + 0x0b81a001,0x7f080240,0x0b812081,0x7f0c0260, + 0x08c9a000,0x7c00820f,0x08c92080,0x7c04822f, + 0x08c9a001,0x7c08824f,0x08c92081,0x7c0c826f, + 0x09a5a000,0x7d00a20f,0x09a52080,0x7d04a22f, + 0x09a5a001,0x7d08a24f,0x09a52081,0x7d0ca26f, + 0x0a81a000,0x7e008200,0x0a812080,0x7e048220, + 0x0a81a001,0x7e086240,0x0a812081,0x7e0c4260, + 0x0340a001,0x9000c00f,0x0344a001,0x9000c02f, + 0x0048a001,0x9000c04f,0x004ca001,0x9000c06f, + 0x0364a081,0x9000e02f,0x0360a001,0x9000e00f, + 0x0324a001,0x90000020,0x0068a001,0x9000e04f, + 0x006ca001,0x9000e06f,0x0320a081,0x90000000, + 0x08a5a000,0x7c00820f,0x08a52080,0x7c04822f, + 0x08a5a001,0x7c08824f,0x08a52081,0x7c0c826f, + 0x0981a000,0x7d00a200,0x09812080,0x7d04a220, + 0x0981a001,0x7d08a240,0x09812081,0x7d0c6260, + 0x02890000,0x7e00c20f,0x02898000,0x7e04c22f, + 0x0028a001,0x9000a04f,0x002ca001,0x9000c06f, + 0x02498081,0x7e0caa6f,0x03890000,0x7f00e20f, + 0x03898000,0x7f04e22f,0x02690001,0x7e08f64f, + 0x03498001,0x7f0ce26f,0x03690081,0x7f08ca4f, + 0x0881a000,0x7c00c200,0x08812080,0x7c04c220, + 0x0881a001,0x7c08e240,0x08812081,0x7c0ca260, + 0x0300a001,0x9000800f,0x0304a001,0x9000802f, + 0x0008a001,0x9000804f,0x000ca001,0x9000806f, + 0x01898080,0x0004aa2f,0x01890000,0x0000a20f, + 0x02a58000,0x7e04c22f,0x01690001,0x7d08a24f, + 0x01498081,0x7e0cc26f,0x02a50000,0x7e00f60f, + 0x03a58000,0x7f04622f,0x02a50001,0x7f08e24f, + 0x02658001,0x7d0ca26f,0x03a50080,0x7f00ca0f, + 0x00890000,0x7c00820f,0x00898000,0x7c049220, + 0x03a50001,0x7e08c24f,0x03658001,0x7f0ce26f, + 0x03c18080,0xfe04862f,0x01a50000,0x7d008200, + 0x01a58000,0x7d04622f,0x00690001,0x7c086240, + 0x00498081,0x7c0c4260,0x02c10000,0x7f00e20f, + 0x02c18000,0x7e04c62f,0x01a50001,0x7d080240, + 0x01658001,0x7e0c0260,0x01c18080,0xfe040620, + 0x03c10000,0x7e00620f,0x03a18001,0x7f0c622f, + 0x02e10001,0x7f08764f,0x02a18001,0x7d0c766f, + 0x03e10081,0x7e084a0f,0x02e80f00,0xfe000e00, + 0x02c88f00,0x7c046220,0x02c81f01,0xff00c240, + 0x02c89f01,0xfe04c260,0x00a50080,0x7c00aa00, + 0x01c10000,0x0400760f,0x00a58000,0x0404622f, + 0x00a50001,0x0308e24f,0x00658001,0x020c626f, + 0x00c10080,0x0500ea0f,0x02c41f00,0x0000620f, + 0x00c18000,0xfe04c22f,0x01e10001,0x0008624f, + 0x01a18001,0x000c666f,0x00a18081,0xfe0ce66f, + 0x00e10001,0x7f08620f,0x02048000,0x03046a2f, + 0x02c41f01,0x06086a4f,0x02c49f01,0x060c6a6f, + 0x02e00f80,0xfe000220,0x02c08f00,0xfe040200, + 0x02e08f01,0xfe0c0240,0x02c01f80,0xfe080260, + 0x8aa480ad,0x2bfc5ca6,0xb5e05b5b,0xd48dc71c +}; + +static const u32 cpVertexShaderRegs[] = { + 0x00000108,0x00000000,0x00000004,0x00000001, + 0xff000201,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0x00000000,0xfffffff8, + 0x00000003,0x00000001,0x00000000,0x00000002, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x00000000,0x0000000e,0x00000010 +}; + +static const u32 cpPixelShaderProgram[] = +{ + 0x20000000,0x000008a4,0x04000000,0x01004085, + 0x23000000,0x0000eca1,0x9f000000,0x0000e0a8, + 0xd8000000,0x000000a4,0x07000000,0x01004085, + 0xd9000000,0x000048a8,0xec000000,0x000000a4, + 0x0a000000,0x01004085,0xed000000,0x000050a8, + 0x02010000,0x000030a0,0x00000000,0x88062094, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0xfd001f80,0x900c0060,0x0000803f,0x00000000, + 0x03011f80,0x8c210000,0xfd001f00,0x900c0000, + 0xfd001f00,0x900ca02f,0x00000002,0x80020040, + 0x00048002,0x80020060,0xf8001f80,0x900cc04f, + 0x0000803f,0x00000000,0xfea81f00,0x9000e00f, + 0xfeac1f00,0x9000e02f,0xf8001f00,0x900c804f, + 0xf8001f80,0x900ca06f,0x00000040,0x00000000, + 0xfea01f00,0x00280000,0xfea41f00,0x00280020, + 0xfe041f00,0x00280040,0xfd041f80,0x00280060, + 0xaf67bb3e,0x00000080,0x7fc41f00,0x00000000, + 0x7fc01f80,0x00000020,0xfe041f00,0x100ac00f, + 0xfe001f80,0x100ac02f,0xfea01f00,0x00280000, + 0xfea41f00,0x00280020,0xfe041f00,0x00280040, + 0xfd041f00,0x1028e06f,0x7fc01f82,0x00000000, + 0x8c65583e,0x00000080,0x7ea41f00,0x80000000, + 0x7ea01f00,0x80000020,0xfee01f00,0x10006040, + 0x7fc48f82,0x00000860,0xa7c4623b,0x00000000, + 0xfea81f00,0x1000e00f,0x7fcc9f01,0x10006020, + 0xfe001f00,0x000a0040,0xfe041f00,0x000a0060, + 0xfea89f80,0x10008040,0x8c65583e,0x3acd13bf, + 0xfeb81f00,0x7e04c20f,0xfebc1f00,0x7e00822f, + 0x03c89f00,0x80060040,0xfea49f00,0x1000e06f, + 0xfea41f81,0x10006060,0x00809043,0x8c65583e, + 0x3acd13bf,0x00000000,0xfea81f00,0xf880a30f, + 0xfe001f00,0x900ca02f,0x7dc41f00,0x1000e04f, + 0xfe081f00,0xfd80636f,0x04081f80,0x900c800f, + 0x0000803f,0x00000000,0xfea81f00,0xf900620f, + 0xfea41f00,0xf900622f,0xfe0c1f00,0x900ca04f, + 0xfec00f00,0x1000c46f,0xfefc0f80,0x10006000, + 0x00000842,0x00000000,0xfeac1f00,0xf900620f, + 0x7fc81f00,0x9000c02f,0x7dc49f00,0x9000e04f, + 0x7df08f01,0x10008060,0x030c1f80,0x900ca02f, + 0x00000842,0x00000000,0xfea41f00,0x80000000, + 0x7ecc1f00,0x9000e02f,0x7e688000,0x80000040, + 0xfea81f00,0x80000060,0x7d6c8081,0x80000000, + 0xa7c4623b,0x00000000,0xfe001f00,0x000a0000, + 0xfe0c1f00,0x000a0020,0xfea41f00,0x80000040, + 0x03648000,0xfe08626f,0x7d648081,0xff00420f, + 0xa7c4623b,0x00000000,0xfeb01f00,0x7e04620f, + 0xfeb41f00,0x7f08662f,0x7c800001,0xff006e4f, + 0xfe081f00,0x000a0060,0x03680081,0xfe0c4e0f, + 0x00809043,0x00000000,0xfebc1f00,0x7f04620f, + 0x7cc41f00,0x00000020,0x7cc49f00,0x1000e04f, + 0xff901f00,0x00000060,0xfe981f80,0x00000000, + 0x00809043,0x00000000,0xfea81f00,0xf900620f, + 0x7cc41f00,0x00000020,0x00c09f00,0x1000c04f, + 0xfe0c1f00,0x80010060,0xff001f80,0x80010000, + 0x00000842,0x00000000,0xfea81f00,0xf900620f, + 0xfecc9f01,0x80000020,0x7fc81f00,0x9000e04f, + 0x7dc89f00,0x1000c86f,0xffe01f80,0x80000000, + 0x00000842,0x00000000,0xfeac1f00,0xf900620f, + 0x7ec81f00,0x9000802f,0xfec49f00,0x9000a040, + 0xfea89f00,0x80000060,0xffe01f80,0x9000a060, + 0x00000842,0xa7c4623b,0xfea41f00,0x80000000, + 0x7ecc1f00,0x9000e02f,0xfe0c1f00,0x000a0040, + 0x7c888081,0x80000000,0xa7c4623b,0x00000000, + 0xfe001f00,0x000a0000,0xfeb81f00,0x7f08622f, + 0xfea49f00,0x80000040,0x048c8081,0xff00420f, + 0x00809043,0xa7c4623b,0xfeb01f00,0x7c04620f, + 0x03600000,0xff00622f,0xfea49f00,0x80000040, + 0xfe081f80,0x000a0060,0x00809043,0x0ccec73c, + 0xfebc1f00,0x7f040200,0xfea09f00,0x90000020, + 0xfe941f00,0x10000040,0xfe081f80,0x30080060, + 0x00809043,0x0ccec73c,0x00041f00,0x20080000, + 0x00a01f00,0x80000020,0x002c1f02,0x1000e04f, + 0x00081f80,0x80010060,0x0ccec73c,0x00000000, + 0xfe201f02,0x1000800f,0xfec81f03,0x80020020, + 0xfe041f00,0x20080040,0xfe881f00,0x00000060, + 0xfecc9f81,0x9000a06f,0xfe0c1f00,0x000a0000, + 0xfe801f00,0x00000020,0xfec01f02,0x80020040, + 0xfe281f02,0x1000c06f,0xfe841f82,0x1000804f, + 0xfe041f00,0x000a0000,0x7fc81f02,0x00000020, + 0xfe8c1f00,0x00000040,0xfecc9f03,0x80020060, + 0xfe881f82,0x1000a00f,0x7cc01f02,0x00000000, + 0xfe8c1f02,0x1000e02f,0xfec49f00,0x80000040, + 0xfe081f00,0x000a0060,0x03c89f80,0x9000e04f, + 0x7ecc9f03,0x00000000,0xfec01f00,0x80000020, + 0x04c81f00,0x80000040,0x7c880f01,0xfe086a6f, + 0x7dac8f81,0x9000800f,0x7da00f00,0xfe04620f, + 0xfec01f00,0x80000020,0x03c01f00,0x80000840, + 0x03ac0f00,0xfe08c66f,0xfebc9f80,0xfd00420f, + 0xe07be53f,0x5c8e5a3f,0xfeb09f00,0xfd00620f, + 0x05e81f00,0x9000f02f,0x7fe48f00,0xfe04624f, + 0x04ec8f00,0xfe08626f,0x03840f81,0x7f08a20f, + 0xe07be53f,0x5c8e5a3f,0x7e0c1f00,0x900ce00f, + 0xfe0c1f00,0x900c802f,0x05cc1f00,0x9000e84f, + 0xfeb89f80,0xfd00626f,0xe07be53f,0x5c8e5a3f, + 0x7cc09f81,0x80000020,0x7fa40f00,0x00280000, + 0xfe848f00,0x00280020,0x7fe80f00,0x00280440, + 0xfd001f80,0x00280060,0x00000080,0x00000000, + 0xfdc01f80,0xf800620f,0x00000243,0x00000000, + 0xfea01f80,0x90000060,0x5555d53f,0x00000000, + 0x02011f80,0x8c110000,0x02448002,0x80020000, + 0xf8402000,0x9006a02f,0x02552081,0x00000040, + 0xfe301f00,0x1000e06f,0xfe081f80,0x1033c02f, + 0xfe4c2081,0x80060040,0xfee88f81,0x0289e32f, + 0x02c59f80,0x80060000,0xfee08f80,0x0285636f, + 0xfecc8f80,0x80000000,0xfe40a081,0x80000060, + 0x00cc9f81,0x9000e04f,0xfe281f00,0x80060000, + 0xf8c01f81,0x9006c02f,0xfee00f81,0xfd80636f, + 0x0000803f,0x00000000,0x7ec49f81,0xf880e34f, + 0xfe381f80,0x00000000,0x7de40f81,0xfe800360, + 0x00011f80,0x8c100000,0xf8001f00,0x900ce00f, + 0x00311f00,0x1000e02f,0x02a41f00,0xf910624f, + 0x02a01f00,0xf910626f,0x00011f80,0x1033e04f, + 0x00000040,0x00000000,0xfecc9f03,0x80020000, + 0xfec81f83,0x80020060,0x7fd49f01,0x00000020, + 0x7fd41f80,0x00000040,0xfe081f00,0x80010000, + 0xfe041f80,0x80010060,0xfee00f01,0x80000000, + 0xfeec0f81,0x80000020,0xfec01f00,0x00280000, + 0xfec49f00,0x00280020,0x7fe00f00,0x00280040, + 0xfd001f80,0x00280060,0x00000080,0x00000000, + 0xfe001f80,0x00350000,0x00ec1f82,0x000c0260, + 0x01011f00,0x800c0000,0x01051f00,0x800c0020, + 0x002c1f00,0x80060040,0xf8008001,0x9006e06f, + 0x01091f80,0x800c0000,0x01c01f00,0x90000000, + 0xfe088001,0xfd80632f,0x01e81f00,0x90000040, + 0x01c49f80,0x90000020,0x0000803f,0x00000000, + 0x7fcc9f80,0xf880630f,0xfe20a081,0x80000000, + 0x01cc1f80,0x90000060,0xc21e82a7,0x62ccc547, + 0x1708607c,0x73ea57a6 +}; +static const u32 cpPixelShaderRegs[] = { + 0x00000106,0x00000002,0x14000003,0x00000000, + 0x00000003,0x00000100,0x00000101,0x00000102, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x0000000f,0x00000001,0x00000010, + 0x00000000 +}; + +ShaderFractalColor * ShaderFractalColor::shaderInstance = NULL; + +ShaderFractalColor::ShaderFractalColor() + : vertexShader(cuAttributeCount) +{ + //! create pixel shader + pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs)); + + blurLocation = 0; + colorIntensityLocation = 4; + fadeOutLocation = 8; + fractalLocation = 12; + pixelShader.addUniformVar((GX2UniformVar){ "unf_blur_border", GX2_VAR_TYPE_FLOAT, 1, blurLocation, 0xffffffff }); + pixelShader.addUniformVar((GX2UniformVar){ "unf_color_intensity", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff }); + pixelShader.addUniformVar((GX2UniformVar){ "unf_fade_out_alpha", GX2_VAR_TYPE_VEC4, 1, fadeOutLocation, 0xffffffff }); + pixelShader.addUniformVar((GX2UniformVar){ "unf_fract_alpha", GX2_VAR_TYPE_INT, 1, fractalLocation, 0xffffffff }); + + //! create vertex shader + vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs)); + + modelMatrixLocation = 0; + projectionMatrixLocation = 16; + viewMatrixLocation = 32; + vertexShader.addUniformVar((GX2UniformVar){ "modelMatrix", GX2_VAR_TYPE_MAT4, 1, modelMatrixLocation, 0xffffffff }); + vertexShader.addUniformVar((GX2UniformVar){ "projectionMatrix", GX2_VAR_TYPE_MAT4, 1, projectionMatrixLocation, 0xffffffff }); + vertexShader.addUniformVar((GX2UniformVar){ "viewMatrix", GX2_VAR_TYPE_MAT4, 1, viewMatrixLocation, 0xffffffff }); + + positionLocation = 0; + colorLocation = 1; + texCoordLocation = 2; + vertexShader.addAttribVar((GX2AttribVar){ "attr_colors", GX2_VAR_TYPE_VEC4, 0, colorLocation }); + vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation }); + vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation }); + + //! setup attribute streams + GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT); + GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT); + GX2InitAttribStream(vertexShader.getAttributeBuffer(2), colorLocation, 2, 0, GX2_ATTRIB_FORMAT_8_8_8_8_UNORM); + + //! create fetch shader + fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount()); + + //! initialize default quad texture vertexes as those are very commonly used + //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000 + posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize); + texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize); + colorVtxs = (u8*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciColorVtxsSize); + + //! position vertex structure and texture coordinate vertex structure + int i = 0; + posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize); + + i = 0; + texCoords[i++] = 0.0f; texCoords[i++] = 1.0f; + texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; + texCoords[i++] = 1.0f; texCoords[i++] = 0.0f; + texCoords[i++] = 0.0f; texCoords[i++] = 0.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize); + + + for(i = 0; i < (int)ciColorVtxsSize; i++) + colorVtxs[i] = 0xff; + + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, colorVtxs, ciColorVtxsSize); +} + +ShaderFractalColor::~ShaderFractalColor() +{ + if(posVtxs) + { + free(posVtxs); + posVtxs = NULL; + } + if(texCoords) + { + free(texCoords); + texCoords = NULL; + } + if(colorVtxs) + { + free(colorVtxs); + colorVtxs = NULL; + } + + delete fetchShader; + fetchShader = NULL; +} diff --git a/src/video/shaders/ShaderFractalColor.h b/src/video/shaders/ShaderFractalColor.h new file mode 100644 index 0000000..d3d8355 --- /dev/null +++ b/src/video/shaders/ShaderFractalColor.h @@ -0,0 +1,124 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef SHADER_FRACTAL_COLOR_H_ +#define SHADER_FRACTAL_COLOR_H_ + +#include "VertexShader.h" +#include "PixelShader.h" +#include "FetchShader.h" + +class ShaderFractalColor : public Shader +{ +private: + ShaderFractalColor(); + virtual ~ShaderFractalColor(); + + static ShaderFractalColor * shaderInstance; + + static const unsigned char cuAttributeCount = 3; + static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize; + static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize; + static const u32 ciColorVtxsSize = 4 * cuColorAttrSize; + + FetchShader *fetchShader; + VertexShader vertexShader; + PixelShader pixelShader; + + f32 *posVtxs; + f32 *texCoords; + u8 *colorVtxs; + + u32 modelMatrixLocation; + u32 viewMatrixLocation; + u32 projectionMatrixLocation; + u32 positionLocation; + u32 colorLocation; + u32 texCoordLocation; + + u32 blurLocation; + u32 colorIntensityLocation; + u32 fadeOutLocation; + u32 fractalLocation; +public: + static ShaderFractalColor *instance() { + if(!shaderInstance) { + shaderInstance = new ShaderFractalColor(); + } + return shaderInstance; + } + static void destroyInstance() { + if(shaderInstance) { + delete shaderInstance; + shaderInstance = NULL; + } + } + + void setShaders(void) const + { + fetchShader->setShader(); + vertexShader.setShader(); + pixelShader.setShader(); + } + + void setAttributeBuffer(const u32 & vtxCount = 0, const f32 * posVtxs_in = NULL, const f32 * texCoords_in = NULL, const u8 * colorVtxs_in = NULL) const + { + if(posVtxs_in && texCoords_in && vtxCount) + { + VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in); + VertexShader::setAttributeBuffer(1, vtxCount * cuTexCoordAttrSize, cuTexCoordAttrSize, texCoords_in); + VertexShader::setAttributeBuffer(2, vtxCount * cuColorAttrSize, cuColorAttrSize, colorVtxs_in); + } + else { + //! use default quad vertex and texture coordinates if nothing is passed + VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs); + VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords); + VertexShader::setAttributeBuffer(2, ciColorVtxsSize, cuColorAttrSize, colorVtxs); + } + } + + void setProjectionMtx(const glm::mat4 & mtx) + { + VertexShader::setUniformReg(projectionMatrixLocation, 16, &mtx[0][0]); + } + void setViewMtx(const glm::mat4 & mtx) + { + VertexShader::setUniformReg(viewMatrixLocation, 16, &mtx[0][0]); + } + void setModelViewMtx(const glm::mat4 & mtx) + { + VertexShader::setUniformReg(modelMatrixLocation, 16, &mtx[0][0]); + } + + void setBlurBorder(const float & blurBorderSize) + { + PixelShader::setUniformReg(blurLocation, 4, &blurBorderSize); + } + void setColorIntensity(const glm::vec4 & vec) + { + PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]); + } + void setAlphaFadeOut(const glm::vec4 & vec) + { + PixelShader::setUniformReg(fadeOutLocation, 4, &vec[0]); + } + void setFractalColor(const int & fractalColorEnable) + { + PixelShader::setUniformReg(fractalLocation, 4, &fractalColorEnable); + } +}; + +#endif // SHADER_FRACTAL_COLOR_H_ diff --git a/src/video/shaders/Texture2DShader.cpp b/src/video/shaders/Texture2DShader.cpp new file mode 100644 index 0000000..ad7ac52 --- /dev/null +++ b/src/video/shaders/Texture2DShader.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#include +#include +#include "Texture2DShader.h" + +static const u32 cpVertexShaderProgram[] = +{ + 0x00000000,0x00008009,0x20000000,0x000080a0, + 0x3c200100,0x88060094,0x00400000,0x88042014, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x02290001,0x80000000,0x02041f00,0x900c0020, + 0x00a11f00,0xfc00624f,0xfd041f00,0x900c4060, + 0x02001f80,0x900c0000,0x83f9223e,0x0000803f, + 0xfe081f00,0x00080020,0xfe202081,0x10004040, + 0xfea49f80,0xfd00620f,0xdb0f49c0,0xdb0fc940, + 0xfea01f80,0x9000e06f,0x83f9223e,0x00000000, + 0xfe0c1f80,0x00370000,0xffa01f00,0x80000040, + 0xff101f00,0x800c0060,0x7f0c1f80,0x80370040, + 0x0000103f,0x00000000,0xffa01f00,0x80000000, + 0xff001f00,0x800c0020,0x02c51f01,0x80000040, + 0xfeac9f80,0x80000060,0x0000103f,0x398ee33f, + 0xfea01f00,0x80000000,0x02c19f01,0x9000e02f, + 0x01c41f01,0x9000e04f,0x02c59f80,0x80000060, + 0x398ee33f,0x00000000,0x01c49f01,0x80000020, + 0x02c11f80,0x80000040,0x01e08f00,0xfe04624f, + 0x01c01f81,0x7f08626f,0xfe2c2000,0x10004000, + 0xfe28a080,0x10004020,0xeb825790,0xb6f711be, + 0x7c0e2df2,0x81173cfa +}; + +static const u32 cpVertexShaderRegs[] = { + 0x00000103,0x00000000,0x00000000,0x00000001, + 0xffffff00,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff, + 0xffffffff,0xffffffff,0x00000000,0xfffffffc, + 0x00000002,0x00000000,0x00000001,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x000000ff,0x000000ff,0x000000ff, + 0x000000ff,0x00000000,0x0000000e,0x00000010 +}; + +static const u32 cPixelShaderProgram[] = +{ + 0x20000000,0x00000ca4,0x0b000000,0x00000085, + 0x24000000,0x000050a0,0xb0000000,0x000cc080, + 0x39000000,0x00005ca0,0xb8000000,0x000cc080, + 0x51000000,0x000078a0,0xc0000000,0x000cc080, + 0x70000000,0x000064a0,0xc8000000,0x0008c080, + 0x8a000000,0x00005ca0,0x0e000000,0x01008086, + 0xce000000,0x0000c080,0xa2000000,0x00000ca8, + 0x00800000,0x88062094,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00051f00,0x80060000,0x00011f80,0x80060040, + 0xfec81f80,0xfb802320,0x01041f80,0x8c220000, + 0x00a41f00,0xfc10620f,0x010d1f00,0x900c0021, + 0x00091f00,0x80060040,0x00a01f80,0xfc10626f, + 0x00000040,0x00000000,0xfe080000,0xfe8cc300, + 0xfe088080,0xfe80c320,0x00a11f00,0xfe000200, + 0x00a51f00,0xfe040220,0x00a19f00,0xfe000240, + 0x00a59f00,0xfe040260,0x00a11f81,0xfe002600, + 0x4260e5bc,0xa69bc4bc,0x0ad7a3bc,0x00000000, + 0x00a11f00,0x06004200,0x00a59f00,0x06042220, + 0x00a51f00,0x06044240,0x00a11f01,0x06008260, + 0x00a51f81,0x06048620,0x6f1283bc,0x0ad7a3bc, + 0xa69b44bc,0x00000000,0x00a41f00,0x80000000, + 0x00a01f00,0x80000020,0x00ac1f00,0x80000040, + 0x00a81f00,0x80000060,0x00a19f80,0x06000600, + 0xcac3123c,0x6f1203bc,0x03a41f00,0xfe00620f, + 0x03a01f00,0xfe04622f,0x03ac1f00,0xfe08624f, + 0x03a81f00,0xfe0c626f,0x00a59f80,0x06040620, + 0xcc28913b,0x6f1203bc,0x01a41f00,0xfe00620f, + 0x01a01f00,0xfe04622f,0x01ac1f00,0xfe08624f, + 0x01a81f00,0xfe0c626f,0x00a19f80,0x06002600, + 0xe8eab03c,0x6f1283bb,0x02ac1f00,0xfe084200, + 0x02a81f00,0xfe0c4220,0x02a41f00,0xfe004240, + 0x02a01f00,0xfe044260,0x00a59f80,0x06042620, + 0x92bb353d,0x6f1283bb,0x04a81f00,0x0204620f, + 0x04ac1f00,0x0200662f,0x04a41f00,0x0208624f, + 0x04a01f00,0x020c626f,0x00a19f80,0x06004600, + 0xc4139f3d,0x6f12833b,0x00a41f00,0xfe08620f, + 0x00a01f00,0xfe0c622f,0x00ac1f00,0xfe04624f, + 0x00a81f00,0xfe00626f,0x00a59f80,0x06044620, + 0xb950ed3d,0x6f12833b,0x01a41f00,0xfe00620f, + 0x01a01f00,0xfe04622f,0x01ac1f00,0xfe08624f, + 0x01a81f00,0xfe0c626f,0x00a19f80,0x06002600, + 0xecd7163e,0x6f12033c,0x03a41f00,0xfe000200, + 0x03a01f00,0xfe040220,0x03ac1f00,0xfe082240, + 0x03a81f00,0xfe0c2260,0x00a59f80,0x06042620, + 0x2168233e,0x6f12033c,0x00a11f00,0x06006200, + 0x00a51f00,0x06046220,0x00a19f00,0x06006240, + 0x00a59f00,0x06046260,0x00a11f81,0x0600e600, + 0xa69b443c,0x6f12833c,0x0ad7a33c,0x00000000, + 0x02ac1f00,0x0108620f,0x02a81f00,0x010c622f, + 0x02a41f00,0x0000624f,0x02a01f00,0x0004666f, + 0x00a59f80,0x0604e620,0xecd7163e,0x0ad7a33c, + 0x04a81f00,0xfe04620f,0x04ac1f00,0xfe00622f, + 0x04a41f00,0xfe08624f,0x04a01f00,0xfe0c626f, + 0x00a19f80,0x06008600,0xb950ed3d,0xa69bc43c, + 0x05a41f00,0xfe08620f,0x05a01f00,0xfe0c622f, + 0x05ac1f00,0xfe04624f,0x05a81f00,0xfe00626f, + 0x00a59f80,0x06048620,0xc4139f3d,0xa69bc43c, + 0x03a41f00,0xfe00a200,0x03a01f00,0xfe04a220, + 0x03ac1f00,0xfe086240,0x03a81f00,0xfe0c6260, + 0x00a19f80,0x06006600,0x92bb353d,0x4260e53c, + 0x00a51f80,0x06046220,0x4260e53c,0x00000000, + 0x07ac1f00,0x0308620f,0x07a81f00,0x030c622f, + 0x07a41f00,0x0500624f,0x07a01f80,0x0504626f, + 0xe8eab03c,0x00000000,0x04a81f00,0xfe04620f, + 0x04ac1f00,0xfe00622f,0x04a41f00,0xfe08624f, + 0x04a01f80,0xfe0c626f,0xcac3123c,0x00000000, + 0x06a41f00,0xfe08620f,0x06a01f00,0xfe0c622f, + 0x06ac1f00,0xfe04624f,0x06a81f80,0xfe00626f, + 0xcc28913b,0x00000000,0xfe20a000,0x9000e00f, + 0xfe242000,0x9000e02f,0xfe28a001,0x9000e04f, + 0xfe2c2081,0x9000e06f,0xfe28a081,0x80060020, + 0xfee48f00,0x7f842300,0xfee40f00,0x7f802320, + 0xfee48f01,0x7f8c2340,0xfee40f81,0x08842b60, + 0x00202000,0x90002000,0x0024a000,0x90002020, + 0x00282001,0x90002040,0x002ca081,0x90002060, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x10000000,0x03100df0,0x00008010,0xecdfea0d, + 0x10000000,0x00100df0,0x0000a051,0xecdfea0d, + 0x10000100,0x01100df0,0x00008010,0xecdfea0d, + 0x10000200,0x02100df0,0x00000011,0xecdfea0d, + 0x10000400,0x04100df0,0x0000b070,0xecdfea0d, + 0x10000000,0x00100df0,0x00008010,0xecdfea0d, + 0x10000100,0x01100df0,0x00008010,0xecdfea0d, + 0x10000600,0x03100df0,0x00008010,0xecdfea0d, + 0x10000200,0x02100df0,0x00008010,0xecdfea0d, + 0x10000100,0x04100df0,0x00008010,0xecdfea0d, + 0x10000300,0x05100df0,0x00008010,0xecdfea0d, + 0x10000300,0x03100df0,0x0000a051,0xecdfea0d, + 0x10000700,0x07100df0,0x00008010,0xecdfea0d, + 0x10000400,0x04100df0,0x00008010,0xecdfea0d, + 0x10000300,0x06100df0,0x00008010,0xecdfea0d, + 0x10000000,0x00100df0,0x00008010,0xecdfea0d, + 0xc8581837,0x22740275,0x281eddcc,0xfa8b9b65 +}; +static const u32 cPixelShaderRegs[] = { + 0x00000109,0x00000002,0x14000001,0x00000000, + 0x00000001,0x00000100,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x0000000f,0x00000001,0x00000010, + 0x00000000 +}; + +Texture2DShader * Texture2DShader::shaderInstance = NULL; + +Texture2DShader::Texture2DShader() + : vertexShader(cuAttributeCount) +{ + //! create pixel shader + pixelShader.setProgram(cPixelShaderProgram, sizeof(cPixelShaderProgram), cPixelShaderRegs, sizeof(cPixelShaderRegs)); + + blurLocation = 0; + colorIntensityLocation = 4; + pixelShader.addUniformVar((GX2UniformVar){ "unf_blur_texture_direction", GX2_VAR_TYPE_VEC3, 1, blurLocation, 0xffffffff }); + pixelShader.addUniformVar((GX2UniformVar){ "unf_color_intensity", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff }); + + samplerLocation = 0; + pixelShader.addSamplerVar((GX2SamplerVar){ "sampl_texture", GX2_SAMPLER_TYPE_2D, samplerLocation }); + + //! create vertex shader + vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs)); + + angleLocation = 0; + offsetLocation = 4; + scaleLocation = 8; + vertexShader.addUniformVar((GX2UniformVar){ "unf_angle", GX2_VAR_TYPE_FLOAT, 1, angleLocation, 0xffffffff }); + vertexShader.addUniformVar((GX2UniformVar){ "unf_offset", GX2_VAR_TYPE_VEC3, 1, offsetLocation, 0xffffffff }); + vertexShader.addUniformVar((GX2UniformVar){ "unf_scale", GX2_VAR_TYPE_VEC3, 1, scaleLocation, 0xffffffff }); + + positionLocation = 0; + texCoordLocation = 1; + vertexShader.addAttribVar((GX2AttribVar){ "attr_position", GX2_VAR_TYPE_VEC3, 0, positionLocation }); + vertexShader.addAttribVar((GX2AttribVar){ "attr_texture_coord", GX2_VAR_TYPE_VEC2, 0, texCoordLocation }); + + //! setup attribute streams + GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT); + GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT); + + //! create fetch shader + fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount()); + + //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000 + posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize); + texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize); + + //! defaults for normal square + //! position vertex structure and texture coordinate vertex structure + int i = 0; + posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = 1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = 1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; + posVtxs[i++] = -1.0f; posVtxs[i++] = 1.0f; posVtxs[i++] = 0.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize); + + i = 0; + texCoords[i++] = 0.0f; texCoords[i++] = 1.0f; + texCoords[i++] = 1.0f; texCoords[i++] = 1.0f; + texCoords[i++] = 1.0f; texCoords[i++] = 0.0f; + texCoords[i++] = 0.0f; texCoords[i++] = 0.0f; + GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize); +} + +Texture2DShader::~Texture2DShader() +{ + if(posVtxs) + { + free(posVtxs); + posVtxs = NULL; + } + if(texCoords) + { + free(texCoords); + texCoords = NULL; + } + + delete fetchShader; + fetchShader = NULL; +} diff --git a/src/video/shaders/Texture2DShader.h b/src/video/shaders/Texture2DShader.h new file mode 100644 index 0000000..cddeee0 --- /dev/null +++ b/src/video/shaders/Texture2DShader.h @@ -0,0 +1,112 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef __TEXTURE_2D_SHADER_H_ +#define __TEXTURE_2D_SHADER_H_ + +#include "VertexShader.h" +#include "PixelShader.h" +#include "FetchShader.h" + +class Texture2DShader : public Shader +{ +private: + Texture2DShader(); + virtual ~Texture2DShader(); + + static const u32 cuAttributeCount = 2; + static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize; + static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize; + + static Texture2DShader *shaderInstance; + + FetchShader *fetchShader; + VertexShader vertexShader; + PixelShader pixelShader; + + f32 *posVtxs; + f32 *texCoords; + + u32 angleLocation; + u32 offsetLocation; + u32 scaleLocation; + u32 colorIntensityLocation; + u32 blurLocation; + u32 samplerLocation; + u32 positionLocation; + u32 texCoordLocation; +public: + static Texture2DShader *instance() { + if(!shaderInstance) { + shaderInstance = new Texture2DShader(); + } + return shaderInstance; + } + static void destroyInstance() { + if(shaderInstance) { + delete shaderInstance; + shaderInstance = NULL; + } + } + + void setShaders(void) const + { + fetchShader->setShader(); + vertexShader.setShader(); + pixelShader.setShader(); + } + + void setAttributeBuffer(const f32 * texCoords_in = NULL, const f32 * posVtxs_in = NULL, const u32 & vtxCount = 0) const + { + if(posVtxs_in && texCoords_in && vtxCount) + { + VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in); + VertexShader::setAttributeBuffer(1, vtxCount * cuTexCoordAttrSize, cuTexCoordAttrSize, texCoords_in); + } + else { + VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs); + VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords); + } + } + + void setAngle(const float & val) + { + VertexShader::setUniformReg(angleLocation, 4, &val); + } + void setOffset(const glm::vec3 & vec) + { + VertexShader::setUniformReg(offsetLocation, 4, &vec[0]); + } + void setScale(const glm::vec3 & vec) + { + VertexShader::setUniformReg(scaleLocation, 4, &vec[0]); + } + void setColorIntensity(const glm::vec4 & vec) + { + PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]); + } + void setBlurring(const glm::vec3 & vec) + { + PixelShader::setUniformReg(blurLocation, 4, &vec[0]); + } + + void setTextureAndSampler(const GX2Texture *texture, const GX2Sampler *sampler) const { + GX2SetPixelTexture(texture, samplerLocation); + GX2SetPixelSampler(sampler, samplerLocation); + } +}; + +#endif // __TEXTURE_2D_SHADER_H_ diff --git a/src/video/shaders/VertexShader.h b/src/video/shaders/VertexShader.h new file mode 100644 index 0000000..18dc0fe --- /dev/null +++ b/src/video/shaders/VertexShader.h @@ -0,0 +1,178 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * 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 . + ****************************************************************************/ +#ifndef VERTEX_SHADER_H +#define VERTEX_SHADER_H + +#include +#include "Shader.h" + +class VertexShader : public Shader +{ +public: + VertexShader(u32 numAttr) + : attributesCount( numAttr ) + , attributes( new GX2AttribStream[attributesCount] ) + , vertexShader( (GX2VertexShader*) memalign(0x40, sizeof(GX2VertexShader)) ) + { + if(vertexShader) + { + memset(vertexShader, 0, sizeof(GX2VertexShader)); + vertexShader->shader_mode = GX2_SHADER_MODE_UNIFORM_REGISTER; + } + } + + virtual ~VertexShader() { + delete [] attributes; + + if(vertexShader) + { + if(vertexShader->shader_data) + free(vertexShader->shader_data); + + for(u32 i = 0; i < vertexShader->uniform_blocks_count; i++) + free((void*)vertexShader->uniform_block[i].name); + + if(vertexShader->uniform_block) + free((void*)vertexShader->uniform_block); + + for(u32 i = 0; i < vertexShader->uniform_vars_count; i++) + free((void*)vertexShader->uniform_var[i].name); + + if(vertexShader->uniform_var) + free((void*)vertexShader->uniform_var); + + if(vertexShader->initial_value) + free((void*)vertexShader->initial_value); + + for(u32 i = 0; i < vertexShader->sampler_vars_count; i++) + free((void*)vertexShader->sampler_var[i].name); + + if(vertexShader->sampler_var) + free((void*)vertexShader->sampler_var); + + for(u32 i = 0; i < vertexShader->attribute_vars_count; i++) + free((void*)vertexShader->attribute_var[i].name); + + if(vertexShader->attribute_var) + free((void*)vertexShader->attribute_var); + + if(vertexShader->loops_data) + free((void*)vertexShader->loops_data); + + free(vertexShader); + } + } + + void setProgram(const u32 * program, const u32 & programSize, const u32 * regs, const u32 & regsSize) + { + if(!vertexShader) + return; + + //! this must be moved into an area where the graphic engine has access to and must be aligned to 0x100 + vertexShader->shader_size = programSize; + vertexShader->shader_data = memalign(GX2_SHADER_ALIGNMENT, vertexShader->shader_size); + if(vertexShader->shader_data) + { + memcpy(vertexShader->shader_data, program, vertexShader->shader_size); + GX2Invalidate(GX2_INVALIDATE_CPU_SHADER, vertexShader->shader_data, vertexShader->shader_size); + } + + memcpy(vertexShader->regs, regs, regsSize); + } + + void addUniformVar(const GX2UniformVar & var) + { + if(!vertexShader) + return; + + u32 idx = vertexShader->uniform_vars_count; + + GX2UniformVar* newVar = (GX2UniformVar*) malloc((vertexShader->uniform_vars_count + 1) * sizeof(GX2UniformVar)); + if(newVar) + { + if(vertexShader->uniform_vars_count > 0) + { + memcpy(newVar, vertexShader->uniform_var, vertexShader->uniform_vars_count * sizeof(GX2UniformVar)); + free(vertexShader->uniform_var); + } + vertexShader->uniform_var = newVar; + + memcpy(vertexShader->uniform_var + idx, &var, sizeof(GX2UniformVar)); + vertexShader->uniform_var[idx].name = (char*) malloc(strlen(var.name) + 1); + strcpy((char*)vertexShader->uniform_var[idx].name, var.name); + + vertexShader->uniform_vars_count++; + } + } + + void addAttribVar(const GX2AttribVar & var) + { + if(!vertexShader) + return; + + u32 idx = vertexShader->attribute_vars_count; + + GX2AttribVar* newVar = (GX2AttribVar*) malloc((vertexShader->attribute_vars_count + 1) * sizeof(GX2AttribVar)); + if(newVar) + { + if(vertexShader->attribute_vars_count > 0) + { + memcpy(newVar, vertexShader->attribute_var, vertexShader->attribute_vars_count * sizeof(GX2AttribVar)); + free(vertexShader->attribute_var); + } + vertexShader->attribute_var = newVar; + + memcpy(vertexShader->attribute_var + idx, &var, sizeof(GX2AttribVar)); + vertexShader->attribute_var[idx].name = (char*) malloc(strlen(var.name) + 1); + strcpy((char*)vertexShader->attribute_var[idx].name, var.name); + + vertexShader->attribute_vars_count++; + } + } + + static inline void setAttributeBuffer(u32 bufferIdx, u32 bufferSize, u32 stride, const void * buffer) { + GX2SetAttribBuffer(bufferIdx, bufferSize, stride, buffer); + } + + GX2VertexShader *getVertexShader() const { + return vertexShader; + } + + void setShader(void) const { + GX2SetVertexShader(vertexShader); + } + + GX2AttribStream * getAttributeBuffer(u32 idx = 0) const { + if(idx >= attributesCount) { + return NULL; + } + return &attributes[idx]; + } + u32 getAttributesCount() const { + return attributesCount; + } + + static void setUniformReg(u32 location, u32 size, const void * reg) { + GX2SetVertexUniformReg(location, size, reg); + } +protected: + u32 attributesCount; + GX2AttribStream *attributes; + GX2VertexShader *vertexShader; +}; + +#endif // VERTEX_SHADER_H