commit 6498401a161bb2438f8bf0809501011a55ddfa06 Author: BullyWiiPlaza Date: Mon Feb 27 16:23:31 2017 +0100 Initial commit 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..3d3789c --- /dev/null +++ b/Makefile @@ -0,0 +1,218 @@ +#--------------------------------------------------------------------------------- +# 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 := tcpgecko +BUILD := build +BUILD_DBG := $(TARGET)_dbg +SOURCES := src \ + src/dynamic_libs \ + src/game \ + src/fs \ + src/kernel \ + src/patcher \ + src/system \ + src/utils +DATA := + +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 := -lz + +#--------------------------------------------------------------------------------- +# 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 \ + $(PORTLIBS) + +#--------------------------------------------------------------------------------- +# 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 +#--------------------------------------------------------------------------------- +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..775aabd --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# What is this? +This is the official TCP Gecko Installer of the [JGecko U](https://github.com/BullyWiiPlaza/JGeckoU) client. You will only receive support if you use the latest versions of both. + +# How do I use this? +This is an app for the [Homebrew Launcher](https://github.com/dimok789/homebrew_launcher). Make sure to read the [setup guide](https://gbatemp.net/threads/jgecko-u-setup-guide.426292/). + +# Can I use TCP Gecko.NET? +No, you will run into incompatibility problems. It's not supported anymore but for what do you still need it? Submit a feature request and it might happen. + +# Does this support [DiiBugger](https://github.com/Kinnay/DiiBugger)? +No. Both projects are fundamentally different. + +# How do I compile? +Just like described [here](https://github.com/dimok789/homebrew_launcher/blob/master/README.md#building-the-homebrew-launcher). + +# Credits +**dimok** for Homebrew Launcher project engine/base +**BullyWiiPlaza** for further development of advanced/efficient features +**wj44** for porting [`pyGecko`](https://github.com/wiiudev/pyGecko) to the Homebrew Launcher and some development +**Marionumber1** for exploit development and TCP Gecko Installer contributions +**NWPlayer123** for the `pyGecko` client library +**Chadderz** for the original `TCP Gecko Installer` +**Kinnay** for some `DiiBugger` code this project made use of \ No newline at end of file diff --git a/codehandler.bin b/codehandler.bin new file mode 100644 index 0000000..7d96429 Binary files /dev/null and b/codehandler.bin differ diff --git a/meta/icon.png b/meta/icon.png new file mode 100644 index 0000000..add83d8 Binary files /dev/null and b/meta/icon.png differ diff --git a/meta/meta.xml b/meta/meta.xml new file mode 100644 index 0000000..5138f7a --- /dev/null +++ b/meta/meta.xml @@ -0,0 +1,14 @@ + + + TCPgecko + Wj44 + 1.1 + 20160503120400 + WiiU RAM Hacking + A memory editor that does magical things to your games. In order to apply Cafe Codes (real-time cheats) use JGecko U. +Special Thanks to: +Chadderz, Marionumber1 - TCPGecko codehandler +pwsincd - icon and xml +CosmoCortney - codehandler for cheat codes, xml + + diff --git a/src/common/common.h b/src/common/common.h new file mode 100644 index 0000000..9d0dae4 --- /dev/null +++ b/src/common/common.h @@ -0,0 +1,74 @@ +#ifndef COMMON_H +#define COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "os_defs.h" + +#define CODE_HANDLER_INSTALL_ADDRESS 0x010F4000 + +#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 + +#define RESTORE_INSTR_MAGIC 0xC001C0DE +#define RESTORE_INSTR_ADDR ((restore_instructions_t*)(MEM_BASE + 0x1600)) + +typedef struct _restore_instructions_t { + unsigned int magic; + unsigned int instr_count; + struct { + unsigned int addr; + unsigned int instr; + } data[0]; +} restore_instructions_t; + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_H */ + diff --git a/src/common/fs_defs.h b/src/common/fs_defs.h new file mode 100644 index 0000000..0b71bb3 --- /dev/null +++ b/src/common/fs_defs.h @@ -0,0 +1,69 @@ +#ifndef FS_DEFS_H +#define FS_DEFS_H + +#include "types.h" + +#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_STATUS_EXISTS -5 +#define FS_STATUS_STORAGE_FULL -12 +#define FS_STATUS_JOURNAL_FULL -13 + +#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_SOURCETYPE_HFIO 1 +/* FS data buffer alignment */ +#define FS_IO_BUFFER_ALIGN 64 + +#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/common/kernel_defs.h b/src/common/kernel_defs.h new file mode 100644 index 0000000..d199c96 --- /dev/null +++ b/src/common/kernel_defs.h @@ -0,0 +1,116 @@ +#ifndef __KERNEL_DEFS_H_ +#define __KERNEL_DEFS_H_ + +#include "types.h" +#include "fs_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// original structure in the kernel that is originally 0x1270 long +typedef struct +{ + uint32_t version_cos_xml; // version tag from cos.xml + uint64_t os_version; // os_version from app.xml + uint64_t title_id; // title_id tag from app.xml + uint32_t app_type; // app_type tag from app.xml + uint32_t cmdFlags; // unknown tag as it is always 0 (might be cmdFlags from cos.xml but i am not sure) + char rpx_name[0x1000]; // rpx name from cos.xml + uint32_t unknown2; // 0x050B8304 in mii maker and system menu (looks a bit like permissions complex that got masked!?) + uint32_t unknown3[63]; // those were all zeros, but its probably connected with unknown2 + uint32_t max_size; // max_size in cos.xml which defines the maximum amount of memory reserved for the app + uint32_t avail_size; // avail_size or codegen_size in cos.xml (seems to mostly be 0?) + uint32_t codegen_size; // codegen_size or avail_size in cos.xml (seems to mostly be 0?) + uint32_t codegen_core; // codegen_core in cos.xml (seems to mostly be 1?) + uint32_t max_codesize; // max_codesize in cos.xml + uint32_t overlay_arena; // overlay_arena in cos.xml + uint32_t unknown4[59]; // all zeros it seems + uint32_t default_stack0_size; // not sure because always 0 but very likely + uint32_t default_stack1_size; // not sure because always 0 but very likely + uint32_t default_stack2_size; // not sure because always 0 but very likely + uint32_t default_redzone0_size; // not sure because always 0 but very likely + uint32_t default_redzone1_size; // not sure because always 0 but very likely + uint32_t default_redzone2_size; // not sure because always 0 but very likely + uint32_t exception_stack0_size; // from cos.xml, 0x1000 on mii maker + uint32_t exception_stack1_size; // from cos.xml, 0x1000 on mii maker + uint32_t exception_stack2_size; // from cos.xml, 0x1000 on mii maker + uint32_t sdk_version; // from app.xml, 20909 (0x51AD) on mii maker + uint32_t title_version; // from app.xml, 0x32 on mii maker + /* + // --------------------------------------------------------------------------------------------------------------------------------------------- + // the next part might be changing from title to title?! I don't think its important but nice to know maybe.... + // --------------------------------------------------------------------------------------------------------------------------------------------- + char mlc[4]; // string "mlc" on mii maker and sysmenu + uint32_t unknown5[7]; // all zeros on mii maker and sysmenu + uint32_t unknown6_one; // 0x01 on mii maker and sysmenu + // --------------------------------------------------------------------------------------------------------------------------------------------- + char ACP[4]; // string "ACP" on mii maker and sysmenu + uint32_t unknown7[15]; // all zeros on mii maker and sysmenu + uint32_t unknown8_5; // 0x05 on mii maker and sysmenu + uint32_t unknown9_zero; // 0x00 on mii maker and sysmenu + uint32_t unknown10_ptr; // 0xFF23DD0C pointer on mii maker and sysmenu + // --------------------------------------------------------------------------------------------------------------------------------------------- + char UVD[4]; // string "UVD" on mii maker and sysmenu + uint32_t unknown11[15]; // all zeros on mii maker and sysmenu + uint32_t unknown12_5; // 0x05 on mii maker and sysmenu + uint32_t unknown13_zero; // 0x00 on mii maker and sysmenu + uint32_t unknown14_ptr; // 0xFF23EFC8 pointer on mii maker and sysmenu + // --------------------------------------------------------------------------------------------------------------------------------------------- + char SND[4]; // string "SND" on mii maker and sysmenu + uint32_t unknown15[15]; // all zeros on mii maker and sysmenu + uint32_t unknown16_5; // 0x05 on mii maker and sysmenu + uint32_t unknown17_zero; // 0x00 on mii maker and sysmenu + uint32_t unknown18_ptr; // 0xFF23F014 pointer on mii maker and sysmenu + // --------------------------------------------------------------------------------------------------------------------------------------------- + uint32_t unknown19; // 0x02 on miimaker, 0x0F on system menu + */ + // after that only zeros follow +} __attribute__((packed)) CosAppXmlInfo; + + +// Our own cos/app.xml struct which uses only uses as much memory as really needed, since many things are just zeros in the above structure +// This structure is only 0x64 bytes long + RPX name length (dynamic up to 0x1000 theoretically) +typedef struct +{ + uint32_t version_cos_xml; // version tag from cos.xml + uint64_t os_version; // os_version from app.xml + uint64_t title_id; // title_id tag from app.xml + uint32_t app_type; // app_type tag from app.xml + uint32_t cmdFlags; // unknown tag as it is always 0 (might be cmdFlags from cos.xml but i am not sure) + uint32_t max_size; // max_size in cos.xml which defines the maximum amount of memory reserved for the app + uint32_t avail_size; // avail_size or codegen_size in cos.xml (seems to mostly be 0?) + uint32_t codegen_size; // codegen_size or avail_size in cos.xml (seems to mostly be 0?) + uint32_t codegen_core; // codegen_core in cos.xml (seems to mostly be 1?) + uint32_t max_codesize; // max_codesize in cos.xml + uint32_t overlay_arena; // overlay_arena in cos.xml + uint32_t default_stack0_size; // not sure because always 0 but very likely + uint32_t default_stack1_size; // not sure because always 0 but very likely + uint32_t default_stack2_size; // not sure because always 0 but very likely + uint32_t default_redzone0_size; // not sure because always 0 but very likely + uint32_t default_redzone1_size; // not sure because always 0 but very likely + uint32_t default_redzone2_size; // not sure because always 0 but very likely + uint32_t exception_stack0_size; // from cos.xml, 0x1000 on mii maker + uint32_t exception_stack1_size; // from cos.xml, 0x1000 on mii maker + uint32_t exception_stack2_size; // from cos.xml, 0x1000 on mii maker + uint32_t sdk_version; // from app.xml, 20909 (0x51AD) on mii maker + uint32_t title_version; // from app.xml, 0x32 on mii maker + char rpx_name[FS_MAX_ENTNAME_SIZE]; // rpx name from cos.xml, length 256 as it can't get bigger from FS anyway +} __attribute__((packed)) ReducedCosAppXmlInfo; + +typedef struct _bat_t +{ + u32 h; + u32 l; +} bat_t; + +typedef struct _bat_table_t +{ + bat_t bat[8]; +} bat_table_t; + +#ifdef __cplusplus +} +#endif + +#endif // __KERNEL_DEFS_H_ diff --git a/src/common/loader_defs.h b/src/common/loader_defs.h new file mode 100644 index 0000000..97c237c --- /dev/null +++ b/src/common/loader_defs.h @@ -0,0 +1,40 @@ +#ifndef __LOADER_DEFS_H_ +#define __LOADER_DEFS_H_ + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// struct holding the globals of the loader (there are actually more but we don't need others) +typedef struct _loader_globals_t +{ + int sgIsLoadingBuffer; + int sgFileType; + int sgProcId; + int sgGotBytes; + int sgFileOffset; + int sgBufferNumber; + int sgBounceError; + char sgLoadName[0x1000]; +} __attribute__((packed)) loader_globals_t; + +typedef struct _loader_globals_550_t +{ + int sgFinishedLoadingBuffer; + int sgFileType; + int sgProcId; + int sgGotBytes; + int sgTotalBytes; + int sgFileOffset; + int sgBufferNumber; + int sgBounceError; + char sgLoadName[0x1000]; +} __attribute__((packed)) loader_globals_550_t; + +#ifdef __cplusplus +} +#endif + +#endif // __LOADER_DEFS_H_ diff --git a/src/common/os_defs.h b/src/common/os_defs.h new file mode 100644 index 0000000..d171c3d --- /dev/null +++ b/src/common/os_defs.h @@ -0,0 +1,125 @@ +#ifndef __OS_DEFS_H_ +#define __OS_DEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*struct OSThread; + +struct OSThreadLink { + OSThread *next; + OSThread *prev; +}; + +struct OSThreadQueue { + OSThread *head; + OSThread *tail; + void *parentStruct; + u32 reserved; +}; + +struct OSMessage { + u32 message; + u32 data0; + u32 data1; + u32 data2; +}; + +struct OSMessageQueue { + u32 tag; + char *name; + u32 reserved; + + OSThreadQueue sendQueue; + OSThreadQueue recvQueue; + OSMessage *messages; + int msgCount; + int firstIndex; + int usedCount; +}; + +struct OSContext { + char tag[8]; + + u32 gpr[32]; + + u32 cr; + u32 lr; + u32 ctr; + u32 xer; + + u32 srr0; + u32 srr1; + + u32 ex0; + u32 ex1; + + u32 exception_type; + u32 reserved; + + double fpscr; + double fpr[32]; + + u16 spinLockCount; + u16 state; + + u32 gqr[8]; + u32 pir; + double psf[32]; + + u64 coretime[3]; + u64 starttime; + + u32 error; + u32 attributes; + + u32 pmc1; + u32 pmc2; + u32 pmc3; + u32 pmc4; + u32 mmcr0; + u32 mmcr1; +}; + +typedef int (*ThreadFunc)(int argc, void *argv); + +struct OSThread { + OSContext context; + + u32 txtTag; + u8 state; + u8 attr; + + short threadId; + int suspend; + int priority; + + char _[0x394 - 0x330]; + + void *stackBase; + void *stackEnd; + + ThreadFunc entryPoint; + + char _3A0[0x6A0 - 0x3A0]; +};*/ + +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/retain_vars.c b/src/common/retain_vars.c new file mode 100644 index 0000000..36e1192 --- /dev/null +++ b/src/common/retain_vars.c @@ -0,0 +1,11 @@ +#include +u8 gSettingLaunchPyGecko __attribute__((section(".data"))) = 0; +u8 gSettingUseUpdatepath __attribute__((section(".data"))) = 0; +u8 gSettingPadconMode __attribute__((section(".data"))) = 0; +u8 gCursorInitDone __attribute__((section(".data"))) = 0; +u8 gPatchSDKDone __attribute__((section(".data"))) = 0; +u8 gHIDPADEnabled __attribute__((section(".data"))) = 0; +u8 gEnableDLC __attribute__((section(".data"))) = 0; +u32 gLoaderPhysicalBufferAddr __attribute__((section(".data"))) = 0; +u32 gLogUDP __attribute__((section(".data"))) = 0; +char gServerIP[16] __attribute__((section(".data"))); diff --git a/src/common/retain_vars.h b/src/common/retain_vars.h new file mode 100644 index 0000000..9a50978 --- /dev/null +++ b/src/common/retain_vars.h @@ -0,0 +1,15 @@ +#ifndef RETAINS_VARS_H_ +#define RETAINS_VARS_H_ +#include + +extern u8 gSettingLaunchPyGecko; +extern u8 gSettingUseUpdatepath; +extern u8 gSettingPadconMode; +extern u8 gCursorInitDone; +extern u8 gPatchSDKDone; +extern u8 gHIDPADEnabled; +extern u8 gEnableDLC; +extern u32 gLoaderPhysicalBufferAddr; +extern char gServerIP[16]; + +#endif // RETAINS_VARS_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/aoc_functions.c b/src/dynamic_libs/aoc_functions.c new file mode 100644 index 0000000..e3449e7 --- /dev/null +++ b/src/dynamic_libs/aoc_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" + +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); + +void InitAocFunctionPointers(void) +{ + unsigned int aoc_handle = 0; + OSDynLoad_Acquire("nn_aoc.rpl", &aoc_handle); + + 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); +} + diff --git a/src/dynamic_libs/aoc_functions.h b/src/dynamic_libs/aoc_functions.h new file mode 100644 index 0000000..9eff6b1 --- /dev/null +++ b/src/dynamic_libs/aoc_functions.h @@ -0,0 +1,46 @@ +/**************************************************************************** + * 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 + +#define AOC_TITLE_SIZE 104 + +void InitAocFunctionPointers(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); + +#ifdef __cplusplus +} +#endif + +#endif // __SYS_FUNCTIONS_H_ diff --git a/src/dynamic_libs/ax_functions.c b/src/dynamic_libs/ax_functions.c new file mode 100644 index 0000000..d84d6f8 --- /dev/null +++ b/src/dynamic_libs/ax_functions.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * 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 "ax_functions.h" + +EXPORT_DECL(void, AXInitWithParams, u32 * params); +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 InitAXFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + unsigned int sound_handle; + OSDynLoad_Acquire("sndcore2.rpl", &sound_handle); + + OS_FIND_EXPORT(sound_handle, AXInitWithParams); + OS_FIND_EXPORT(sound_handle, AXQuit); + OS_FIND_EXPORT(sound_handle, AXGetInputSamplesPerSec); + 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); +} + diff --git a/src/dynamic_libs/ax_functions.h b/src/dynamic_libs/ax_functions.h new file mode 100644 index 0000000..df9647c --- /dev/null +++ b/src/dynamic_libs/ax_functions.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * 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 + +void InitAXFunctionPointers(void); + +extern void (* AXInitWithParams)(u32 * params); +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/fs_functions.c b/src/dynamic_libs/fs_functions.c new file mode 100644 index 0000000..9ae7996 --- /dev/null +++ b/src/dynamic_libs/fs_functions.c @@ -0,0 +1,167 @@ +/**************************************************************************** + * 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" +#include "utils/utils.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); + +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); +} diff --git a/src/dynamic_libs/fs_functions.h b/src/dynamic_libs/fs_functions.h new file mode 100644 index 0000000..6d67123 --- /dev/null +++ b/src/dynamic_libs/fs_functions.h @@ -0,0 +1,135 @@ +/**************************************************************************** + * 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 "common/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); + +#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..b9bf671 --- /dev/null +++ b/src/dynamic_libs/gx2_functions.c @@ -0,0 +1,162 @@ +/**************************************************************************** + * 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" +#include "utils/utils.h" + +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, 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*)); + + +void InitGX2FunctionPointers(void) +{ + unsigned int *funcPointer = 0; + unsigned int gx2_handle; + OSDynLoad_Acquire("gx2.rpl", &gx2_handle); + + 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); +} diff --git a/src/dynamic_libs/gx2_functions.h b/src/dynamic_libs/gx2_functions.h new file mode 100644 index 0000000..1737833 --- /dev/null +++ b/src/dynamic_libs/gx2_functions.h @@ -0,0 +1,205 @@ +/**************************************************************************** + * 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" + +void InitGX2FunctionPointers(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 (* 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*)); + +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..2ea232d --- /dev/null +++ b/src/dynamic_libs/os_functions.c @@ -0,0 +1,383 @@ +/**************************************************************************** + * 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 = 0; +// unsigned int zlib_handle = 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); + +EXPORT_DECL(void, __OSSetCoreTrace, int core); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! 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, OSGetCurrentThread, void); + +EXPORT_DECL(int, OSResumeThread, void *thread); + +EXPORT_DECL(int, OSSleepThread, void *thread); + +EXPORT_DECL(int, OSGetDefaultThread, int core); + +EXPORT_DECL(int, OSWakeupThread, void *thread); + +EXPORT_DECL(int, OSYieldThread, void); + +EXPORT_DECL(void, OSSetThreadName, void *thread, const char *name); + +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); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! 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, __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, OSIsAddressValid, const void*); + +EXPORT_DECL(int, __OSValidateAddressSpaceRange, int, void*, int); + +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(void, OSScreenShutdown, 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); + +EXPORT_DECL(int, OSAllocFromSystem, unsigned int size, unsigned int align); + +EXPORT_DECL(int, OSFreeToSystem, void* ptr); + +EXPORT_DECL(void, DisassemblePPCRange, void *, void *, DisasmReport, DisasmGetSym, u32); + +EXPORT_DECL(bool, DisassemblePPCOpcode, u32 *, char *, u32, DisasmGetSym, u32); + +EXPORT_DECL(void*, OSGetSymbolName, u32, u8*, u32); + +EXPORT_DECL(int, OSIsDebuggerInitialized, void); + +// EXPORT_DECL(int, compress2, char *, int*, const char *, int, int); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! 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); + +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); + // OSDynLoad_Acquire("zlib125.rpl", &zlib_handle); +} + +void InitOSFunctionPointers(void) { + unsigned int *funcPointer = 0; + + InitAcquireOS(); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! Security functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSGetSecurityLevel); + OS_FIND_EXPORT(coreinit_handle, __OSSetCoreTrace); + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! System functions + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSFatal); + OS_FIND_EXPORT(coreinit_handle, OSGetTitleID); + 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, OSIsAddressValid); + OS_FIND_EXPORT(coreinit_handle, __OSValidateAddressSpaceRange); + // OS_FIND_EXPORT(coreinit_handle, ); + OS_FIND_EXPORT(coreinit_handle, __os_snprintf); + OS_FIND_EXPORT(coreinit_handle, __gh_errno_ptr); + OS_FIND_EXPORT(coreinit_handle, OSAllocFromSystem); + OS_FIND_EXPORT(coreinit_handle, OSFreeToSystem); + OS_FIND_EXPORT(coreinit_handle, DisassemblePPCRange); + OS_FIND_EXPORT(coreinit_handle, DisassemblePPCOpcode); + OS_FIND_EXPORT(coreinit_handle, OSGetSymbolName); + OS_FIND_EXPORT(coreinit_handle, OSIsDebuggerInitialized); + // OS_FIND_EXPORT(zlib_handle, compress2); + + OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &__Exit); + + OS_FIND_EXPORT(coreinit_handle, OSScreenInit); + OS_FIND_EXPORT(coreinit_handle, OSScreenShutdown); + 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, OSGetCurrentThread); + OS_FIND_EXPORT(coreinit_handle, OSCreateThread); + OS_FIND_EXPORT(coreinit_handle, OSResumeThread); + OS_FIND_EXPORT(coreinit_handle, OSSleepThread); + OS_FIND_EXPORT(coreinit_handle, OSGetDefaultThread); + OS_FIND_EXPORT(coreinit_handle, OSWakeupThread); + OS_FIND_EXPORT(coreinit_handle, OSSetThreadName); + OS_FIND_EXPORT(coreinit_handle, OSYieldThread); + 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); + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! 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); + + //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //! 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..2839bc8 --- /dev/null +++ b/src/dynamic_libs/os_functions.h @@ -0,0 +1,275 @@ +/**************************************************************************** + * 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" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Disassembler */ +typedef void (*DisasmReport)(char *outputBuffer, ...); + +typedef void *(*DisasmGetSym)(u32 addr, u8 *symbolName, u32 nameBufSize); + +#define PPC_DISASM_MAX_BUFFER 64 + +#define PPC_DISASM_DEFAULT 0x00000000 // use defaults +#define PPC_DISASM_SIMPLIFY 0x00000001 // use simplified mnemonics +#define PPC_DISASM_REG_SPACES 0x00000020 // emit spaces between registers +#define PPC_DISASM_EMIT_DISASM 0x00000040 // emit only disassembly +#define PPC_DISASM_EMIT_ADDR 0x00000080 // emit only addresses + disassembly +#define PPC_DISASM_EMIT_FUNCS 0x00000100 // emit function names before and during disassembly + +/* zlib */ + +/*#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6)*/ + +#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); + +extern void (*__OSSetCoreTrace)(int core); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Thread functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +// +// Thread attributes +// +// Threads lacking an affinity bit are affinitized to the +// core on which they are created +// + +#define OS_THREAD_ATTR_AFFINITY_NONE 0x0007u // affinity to run on every core +#define OS_THREAD_ATTR_AFFINITY_CORE0 0x0001u // run only on core0 +#define OS_THREAD_ATTR_AFFINITY_CORE1 0x0002u // run only on core1 +#define OS_THREAD_ATTR_AFFINITY_CORE2 0x0004u // run only on core2 +#define OS_THREAD_ATTR_DETACH 0x0008u // detached +#define OS_THREAD_ATTR_PINNED_AFFINITY 0x0010u // pinned (affinitized) to a single core +#define OS_THREAD_ATTR_CHECK_STACK_USE 0x0040u // check for stack usage +#define OS_THREAD_ATTR_NAME_SENT 0x0080u // debugger has seen the name +#define OS_THREAD_ATTR_LAST (OS_THREAD_ATTR_DETACH | OS_THREAD_ATTR_PINNED_AFFINITY | OS_THREAD_ATTR_AFFINITY_NONE) + +extern int +(*OSCreateThread)(void *thread, s32 (*callback)(s32, void *), s32 argc, void *args, u32 stack, u32 stack_size, + s32 priority, u32 attr); + +extern int (*OSGetCurrentThread)(void); + +extern int (*OSResumeThread)(void *thread); + +extern int (*OSSleepThread)(void *thread); + +extern int (*OSWakeupThread)(void *thread); + +extern void (*OSSetThreadName)(void *thread, const char *name); + +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); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! 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 (*__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 (*OSIsAddressValid)(const void *); + +extern int (*__OSValidateAddressSpaceRange)(int dummyTrue, void *address, int size); + +extern int (*__os_snprintf)(char *buffer, int length, 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); + +extern int (*OSAllocFromSystem)(unsigned int size, unsigned int align); + +extern int (*OSFreeToSystem)(void *aPtr); + +extern void +(*DisassemblePPCRange)(void *rangeStart, void *rangeEnd, DisasmReport disasmReport, DisasmGetSym disasmGetSym, + u32 disasmOptions); + +extern bool +(*DisassemblePPCOpcode)(u32 *opcode, char *outputBuffer, u32 bufferSize, DisasmGetSym disasmGetSym, u32 disasmOptions); + +extern void *(*OSGetSymbolName)(u32 addr, u8 *symbolName, u32 nameBufSize); + +extern int (*OSIsDebuggerInitialized)(void); + +// extern int (*compress2)(char *dest, int *destLen, const char *source, int sourceLen, int level); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! 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); + +#ifdef __cplusplus +} +#endif + +#endif // __OS_FUNCTIONS_H_ + diff --git a/src/dynamic_libs/padscore_functions.c b/src/dynamic_libs/padscore_functions.c new file mode 100644 index 0000000..c51764f --- /dev/null +++ b/src/dynamic_libs/padscore_functions.c @@ -0,0 +1,50 @@ +/**************************************************************************** + * 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" + +EXPORT_DECL(void, KPADInit, 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); + +void InitPadScoreFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + unsigned int padscore_handle; + OSDynLoad_Acquire("padscore.rpl", &padscore_handle); + + 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); + + 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..26eda1a --- /dev/null +++ b/src/dynamic_libs/padscore_functions.h @@ -0,0 +1,122 @@ +/**************************************************************************** + * 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 + +#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 + +void InitPadScoreFunctionPointers(void); + + +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 unused_4[1]; + + 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; + + u32 unused_6[20]; + }; + u32 unused_7[16]; +} KPADData; + +typedef void (* wpad_connect_callback_t)(s32 chan, s32 status); + +extern void (* KPADInit)(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); + +#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..697bfb2 --- /dev/null +++ b/src/dynamic_libs/socket_functions.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * 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; + +EXPORT_DECL(int, socket_lib_init, void); +EXPORT_DECL(int, socket_lib_finish, 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, 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); + +void InitSocketFunctionPointers(void) +{ + unsigned int nsysnet_handle; + unsigned int *funcPointer = 0; + OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle); + + unsigned int nn_ac_handle; + int(*ACInitialize)(); + int(*ACGetStartupId) (unsigned int *id); + int(*ACConnectWithConfigId) (unsigned int id); + int(*ACGetAssignedAddress) (u32 * ip); + OSDynLoad_Acquire("nn_ac.rpl", &nn_ac_handle); + OSDynLoad_FindExport(nn_ac_handle, 0, "ACInitialize", &ACInitialize); + OSDynLoad_FindExport(nn_ac_handle, 0, "ACGetStartupId", &ACGetStartupId); + OSDynLoad_FindExport(nn_ac_handle, 0, "ACConnectWithConfigId",&ACConnectWithConfigId); + OSDynLoad_FindExport(nn_ac_handle, 0, "ACGetAssignedAddress",&ACGetAssignedAddress); + + OS_FIND_EXPORT(nsysnet_handle, socket_lib_init); + OS_FIND_EXPORT(nsysnet_handle, socket_lib_finish); + 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, sendto); + OS_FIND_EXPORT(nsysnet_handle, setsockopt); + OS_FIND_EXPORT(nsysnet_handle, inet_ntoa); + OS_FIND_EXPORT(nsysnet_handle, inet_aton); + + unsigned int nn_startupid; + ACInitialize(); + ACGetStartupId(&nn_startupid); + ACConnectWithConfigId(nn_startupid); + ACGetAssignedAddress(&hostIpAddress); + + 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..eef0bdd --- /dev/null +++ b/src/dynamic_libs/socket_functions.h @@ -0,0 +1,96 @@ +/**************************************************************************** + * 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 + +#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 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); + +extern int (*socket_lib_init)(void); +extern int (*socket_lib_finish)(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 (*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 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..b2a1d89 --- /dev/null +++ b/src/dynamic_libs/sys_functions.c @@ -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. + ***************************************************************************/ +#include "os_functions.h" + +EXPORT_DECL(void, _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); + +void InitSysFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + unsigned int sysapp_handle; + OSDynLoad_Acquire("sysapp.rpl", &sysapp_handle); + + OS_FIND_EXPORT(sysapp_handle, _SYSLaunchTitleByPathFromLauncher); + OS_FIND_EXPORT(sysapp_handle, SYSRelaunchTitle); + OS_FIND_EXPORT(sysapp_handle, SYSLaunchMenu); + OS_FIND_EXPORT(sysapp_handle, SYSCheckTitleExists); +} + diff --git a/src/dynamic_libs/sys_functions.h b/src/dynamic_libs/sys_functions.h new file mode 100644 index 0000000..5bd2119 --- /dev/null +++ b/src/dynamic_libs/sys_functions.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * 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 + +void InitSysFunctionPointers(void); + +extern void(*_SYSLaunchTitleByPathFromLauncher)(const char* path, int len, int zero); +extern int (* SYSRelaunchTitle)(int argc, char* argv); +extern int (* SYSLaunchMenu)(void); +extern int (* SYSCheckTitleExists)(u64 titleId); + + +#ifdef __cplusplus +} +#endif + +#endif // __SYS_FUNCTIONS_H_ diff --git a/src/dynamic_libs/vpad_functions.c b/src/dynamic_libs/vpad_functions.c new file mode 100644 index 0000000..a2d8e3f --- /dev/null +++ b/src/dynamic_libs/vpad_functions.c @@ -0,0 +1,39 @@ +/**************************************************************************** + * 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" + +EXPORT_DECL(void, VPADInit, void); +EXPORT_DECL(void, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error); + +void InitVPadFunctionPointers(void) +{ + unsigned int *funcPointer = 0; + unsigned int vpad_handle; + OSDynLoad_Acquire("vpad.rpl", &vpad_handle); + + OS_FIND_EXPORT(vpad_handle, VPADInit); + OS_FIND_EXPORT(vpad_handle, VPADRead); +} + diff --git a/src/dynamic_libs/vpad_functions.h b/src/dynamic_libs/vpad_functions.h new file mode 100644 index 0000000..00f7983 --- /dev/null +++ b/src/dynamic_libs/vpad_functions.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * 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 + +#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 + + +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); + +extern void (* VPADInit)(void); +extern void (* VPADRead)(int chan, VPADData *buffer, u32 buffer_size, s32 *error); + +#ifdef __cplusplus +} +#endif + +#endif // __VPAD_FUNCTIONS_H_ diff --git a/src/entry.c b/src/entry.c new file mode 100644 index 0000000..69a48f8 --- /dev/null +++ b/src/entry.c @@ -0,0 +1,27 @@ +#include +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/gx2_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "common/common.h" +#include "pygecko.h" +#include "main.h" + +int __entry_menu(int argc, char **argv) { + if (OSGetTitleID != 0 && + OSGetTitleID() != 0x000500101004A200 && // mii maker eur + OSGetTitleID() != 0x000500101004A100 && // mii maker usa + OSGetTitleID() != 0x000500101004A000) // mii maker jpn) + { + InitOSFunctionPointers(); + InitSocketFunctionPointers(); + InitGX2FunctionPointers(); + + start_pygecko(); + return EXIT_RELAUNCH_ON_LOAD; + } + + //! ******************************************************************* + //! * Jump to our application * + //! ******************************************************************* + return Menu_Main(); +} \ No newline at end of file diff --git a/src/fs/CFile.cpp b/src/fs/CFile.cpp new file mode 100644 index 0000000..161b980 --- /dev/null +++ b/src/fs/CFile.cpp @@ -0,0 +1,197 @@ +#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..1580eb3 --- /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..2f1a211 --- /dev/null +++ b/src/fs/DirList.cpp @@ -0,0 +1,224 @@ +/**************************************************************************** + * 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; + + // Don't list hidden OS X files + if(filename[0] == '.' && filename[1] == '_') + 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; + + return strcasecmp(f1.FilePath, f2.FilePath) <= 0; +} + +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..efa2e55 --- /dev/null +++ b/src/fs/fs_utils.c @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include "common/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/memory_area_table.c b/src/game/memory_area_table.c new file mode 100644 index 0000000..20ea351 --- /dev/null +++ b/src/game/memory_area_table.c @@ -0,0 +1,1729 @@ +/**************************************************************************** + * 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 +#include "common/common.h" +#include "memory_area_table.h" + +typedef struct _memory_values_t +{ + unsigned int start_address; + unsigned int end_address; +} memory_values_t; + +static const memory_values_t mem_vals_500[] = +{ + // TODO: Check which of those areas are usable +// { 0xB801308C, 0xB801701C } // size 16276 (15 kB) (0 MB) +// { 0xB80170B8, 0xB801B00C } // size 16216 (15 kB) (0 MB) +// { 0xB801B0B8, 0xB801F01C } // size 16232 (15 kB) (0 MB) +// { 0xB801F0C4, 0xB8023014 } // size 16212 (15 kB) (0 MB) +// { 0xB80230C4, 0xB8026EFC } // size 15932 (15 kB) (0 MB) +// { 0xB80270C4, 0xB802B014 } // size 16212 (15 kB) (0 MB) +// { 0xB802B0C4, 0xB802F014 } // size 16212 (15 kB) (0 MB) +// { 0xB802F0C4, 0xB8032E14 } // size 15700 (15 kB) (0 MB) +// { 0xB80330C4, 0xB8037014 } // size 16212 (15 kB) (0 MB) +// { 0xB803B068, 0xB803BC68 } // size 3076 (3 kB) (0 MB) +// { 0xB8043168, 0xB8044364 } // size 4608 (4 kB) (0 MB) +// { 0xB8045AF0, 0xB804E09C } // size 34224 (33 kB) (0 MB) +// { 0xB804E3D4, 0xB8050B24 } // size 10068 (9 kB) (0 MB) +// { 0xB8051940, 0xB805287C } // size 3904 (3 kB) (0 MB) +// { 0xB8052930, 0xB80538D4 } // size 4008 (3 kB) (0 MB) +// { 0xB8053934, 0xB805487C } // size 3916 (3 kB) (0 MB) +// { 0xB80566EC, 0xB8058664 } // size 8060 (7 kB) (0 MB) +// { 0xB80586EC, 0xB805A664 } // size 8060 (7 kB) (0 MB) +// { 0xB805A6EC, 0xB805C664 } // size 8060 (7 kB) (0 MB) +// { 0xB805CB90, 0xB805DC78 } // size 4332 (4 kB) (0 MB) +// { 0xB805E40C, 0xB805ECF0 } // size 2280 (2 kB) (0 MB) +// { 0xB8060044, 0xB8060F8C } // size 3916 (3 kB) (0 MB) +// { 0xB8061040, 0xB806203C } // size 4096 (4 kB) (0 MB) +// { 0xB8062DB4, 0xB806EE3C } // size 49292 (48 kB) (0 MB) +// { 0xB806EE84, 0xB8070DC4 } // size 8004 (7 kB) (0 MB) +// { 0xB8070E84, 0xB8072CFC } // size 7804 (7 kB) (0 MB) +// { 0xB8072E84, 0xB8074DC4 } // size 8004 (7 kB) (0 MB) +// { 0xB8076A30, 0xB807745C } // size 2608 (2 kB) (0 MB) +// { 0xB807FAF8, 0xB8081350 } // size 6236 (6 kB) (0 MB) +// { 0xB8081358, 0xB808228C } // size 3896 (3 kB) (0 MB) +// { 0xB8082358, 0xB808328C } // size 3896 (3 kB) (0 MB) +// { 0xB8083358, 0xB808428C } // size 3896 (3 kB) (0 MB) +// { 0xB80858E4, 0xB808787C } // size 8092 (7 kB) (0 MB) +// { 0xB80878F8, 0xB808B8A4 } // size 16304 (15 kB) (0 MB) +// { 0xB808C240, 0xB80901BC } // size 16256 (15 kB) (0 MB) +// { 0xB8090278, 0xB8092888 } // size 9748 (9 kB) (0 MB) +// { 0xB8092890, 0xB8097744 } // size 20152 (19 kB) (0 MB) +// { 0xB8097888, 0xB80A37E4 } // size 48992 (47 kB) (0 MB) +// { 0xB80A3818, 0xB80AF848 } // size 49204 (48 kB) (0 MB) +// { 0xB80AFAA0, 0xB80B0310 } // size 2164 (2 kB) (0 MB) +// { 0xB80B0320, 0xB80B16BC } // size 5024 (4 kB) (0 MB) +// { 0xB80B16C4, 0xB80B262C } // size 3948 (3 kB) (0 MB) +// { 0xB80B26C0, 0xB80B3B3C } // size 5248 (5 kB) (0 MB) +// { 0xB80B4200, 0xB80B5900 } // size 5892 (5 kB) (0 MB) +// { 0xB80B5934, 0xB80B713C } // size 6156 (6 kB) (0 MB) +// { 0xB80B8910, 0xB80BC074 } // size 14184 (13 kB) (0 MB) +// { 0xB80BC138, 0xB80BD13C } // size 4104 (4 kB) (0 MB) +// { 0xB80BD144, 0xB80C1084 } // size 16196 (15 kB) (0 MB) +// { 0xB80C1144, 0xB80C4E84 } // size 15684 (15 kB) (0 MB) +// { 0xB80C5144, 0xB80C9084 } // size 16196 (15 kB) (0 MB) +// { 0xB80CC780, 0xB80CCFA4 } // size 2088 (2 kB) (0 MB) +// { 0xB80CDEE4, 0xB80CE6E4 } // size 2052 (2 kB) (0 MB) +// { 0xB80CF600, 0xB80D707C } // size 31360 (30 kB) (0 MB) +// { 0xB80D719C, 0xB80DC3FC } // size 21092 (20 kB) (0 MB) +// { 0xB80DC61C, 0xB81748FC } // size 623332 (608 kB) (0 MB) +// { 0xB817552C, 0xB817B534 } // size 24588 (24 kB) (0 MB) +// { 0xB817BD38, 0xB818037C } // size 17992 (17 kB) (0 MB) +// { 0xB81804E0, 0xB81C037C } // size 261792 (255 kB) (0 MB) +// { 0xB81C14E8, 0xB81C85FC } // size 28952 (28 kB) (0 MB) +// { 0xB81C881C, 0xB81C97C0 } // size 4008 (3 kB) (0 MB) +// { 0xB81C981C, 0xB81CA7C0 } // size 4008 (3 kB) (0 MB) +// { 0xB81CA81C, 0xB81CB7C0 } // size 4008 (3 kB) (0 MB) +// { 0xB81CB81C, 0xB81CC7C0 } // size 4008 (3 kB) (0 MB) +// { 0xB81CC81C, 0xB81CD7C0 } // size 4008 (3 kB) (0 MB) +// { 0xB81CD9C0, 0xB81CE7C0 } // size 3588 (3 kB) (0 MB) +// { 0xB81CE870, 0xB81CF7C0 } // size 3924 (3 kB) (0 MB) +// { 0xB81CF870, 0xB81D07C0 } // size 3924 (3 kB) (0 MB) +// { 0xB81D0870, 0xB81D17C0 } // size 3924 (3 kB) (0 MB) +// { 0xB81D1870, 0xB81D27C0 } // size 3924 (3 kB) (0 MB) +// { 0xB81D296C, 0xB81D37C0 } // size 3672 (3 kB) (0 MB) +// { 0xB81D3ABC, 0xB81D47C0 } // size 3336 (3 kB) (0 MB) +// { 0xB81D481C, 0xB81D57C0 } // size 4008 (3 kB) (0 MB) +// { 0xB81D581C, 0xB81D67C0 } // size 4008 (3 kB) (0 MB) +// { 0xB81D6A68, 0xB81D77C0 } // size 3420 (3 kB) (0 MB) +// { 0xB81D796C, 0xB81D87C0 } // size 3672 (3 kB) (0 MB) +// { 0xB81D89C0, 0xB81D97C0 } // size 3588 (3 kB) (0 MB) +// { 0xB81D9870, 0xB81DA7C0 } // size 3924 (3 kB) (0 MB) +// { 0xB81DA81C, 0xB81DB7C0 } // size 4008 (3 kB) (0 MB) +// { 0xB81DB96C, 0xB81DC7C0 } // size 3672 (3 kB) (0 MB) +// { 0xB81DC9C0, 0xB81DD7C0 } // size 3588 (3 kB) (0 MB) +// { 0xB81DD870, 0xB81DE7C0 } // size 3924 (3 kB) (0 MB) +// { 0xB81DE81C, 0xB81DF7C0 } // size 4008 (3 kB) (0 MB) +// { 0xB81DF96C, 0xB81E07C0 } // size 3672 (3 kB) (0 MB) +// { 0xB81E09C0, 0xB81E17C0 } // size 3588 (3 kB) (0 MB) +// { 0xB81E1870, 0xB81E27C0 } // size 3924 (3 kB) (0 MB) +// { 0xB81E281C, 0xB820863C } // size 155172 (151 kB) (0 MB) +// { 0xB820B7C4, 0xB821063C } // size 20092 (19 kB) (0 MB) +// { 0xB8229490, 0xB822A4EC } // size 4192 (4 kB) (0 MB) +// { 0xB822F48C, 0xB823153C } // size 8372 (8 kB) (0 MB) +// { 0xB82327E4, 0xB8233060 } // size 2176 (2 kB) (0 MB) +// { 0xB8234080, 0xB824B340 } // size 94916 (92 kB) (0 MB) +// { 0xB824D8C0, 0xB828D880 } // size 262084 (255 kB) (0 MB) +// { 0xB82A8DE0, 0xB82B64FC } // size 55072 (53 kB) (0 MB) +// { 0xB82BC624, 0xB82C63FC } // size 40412 (39 kB) (0 MB) +// { 0xB82C642C, 0xB82CA42C } // size 16388 (16 kB) (0 MB) +// { 0xB82CBB6C, 0xB82CDB80 } // size 8216 (8 kB) (0 MB) +// { 0xB82CF708, 0xB82D0790 } // size 4236 (4 kB) (0 MB) +// { 0xB82D38FC, 0xB82D4A0C } // size 4372 (4 kB) (0 MB) +// { 0xB82EDF80, 0xB82EF77C } // size 6144 (6 kB) (0 MB) +// { 0xB82F6CA4, 0xB82F7820 } // size 2944 (2 kB) (0 MB) +// { 0xB82F79B0, 0xB82F861C } // size 3184 (3 kB) (0 MB) +// { 0xB82F8FB0, 0xB82FA080 } // size 4308 (4 kB) (0 MB) +// { 0xB8302A78, 0xB830428C } // size 6168 (6 kB) (0 MB) +// { 0xB8333434, 0xB8337D0C } // size 18652 (18 kB) (0 MB) +// { 0xB8338ED0, 0xB83396DC } // size 2064 (2 kB) (0 MB) +// { 0xB833C5E0, 0xB8340EAC } // size 18640 (18 kB) (0 MB) +// { 0xB834DB34, 0xB834EB40 } // size 4112 (4 kB) (0 MB) +// { 0xB83542F0, 0xB8356344 } // size 8280 (8 kB) (0 MB) +// { 0xB83574B0, 0xB83583FC } // size 3920 (3 kB) (0 MB) +// { 0xB8358A80, 0xB835A430 } // size 6580 (6 kB) (0 MB) +// { 0xB835AA08, 0xB8366884 } // size 48768 (47 kB) (0 MB) +// { 0xB8366B04, 0xB836DEE8 } // size 29672 (28 kB) (0 MB) +// { 0xB836E0DC, 0xB8378E3C } // size 44388 (43 kB) (0 MB) +// { 0xB8378E44, 0xB837CC6C } // size 15916 (15 kB) (0 MB) +// { 0xB837D5E4, 0xB8381524 } // size 16196 (15 kB) (0 MB) +// { 0xB83A3AE4, 0xB83A5308 } // size 6184 (6 kB) (0 MB) +// { 0xB83A73DC, 0xB84D2AE4 } // size 1226508 (1197 kB) (1 MB) +// { 0xB84D2F80, 0xB84D393C } // size 2496 (2 kB) (0 MB) +// { 0xB84D43C0, 0xB84D513C } // size 3456 (3 kB) (0 MB) +// { 0xB84D604C, 0xB84D6F68 } // size 3872 (3 kB) (0 MB) +// { 0xB84D7730, 0xB85021FC } // size 174800 (170 kB) (0 MB) +// { 0xB8583B7C, 0xB8584538 } // size 2496 (2 kB) (0 MB) +// { 0xB8585F34, 0xB858937C } // size 13388 (13 kB) (0 MB) +// { 0xB8589A88, 0xB858DC3C } // size 16824 (16 kB) (0 MB) +// { 0xB858DC64, 0xB859B40C } // size 55212 (53 kB) (0 MB) +// { 0xB85A8728, 0xB85A90A4 } // size 2432 (2 kB) (0 MB) +// { 0xB85A90BC, 0xB85B3448 } // size 41872 (40 kB) (0 MB) +// { 0xB85B3488, 0xB85C626C } // size 77288 (75 kB) (0 MB) +// { 0xB85C6314, 0xB85C7874 } // size 5476 (5 kB) (0 MB) +// { 0xB85CF8DC, 0xB85D147C } // size 7076 (6 kB) (0 MB) +// { 0xB85D1484, 0xB85E1284 } // size 65028 (63 kB) (0 MB) +// { 0xB85E1484, 0xB85ED094 } // size 48148 (47 kB) (0 MB) +// { 0xB85ED1E4, 0xB85EECFC } // size 6940 (6 kB) (0 MB) +// { 0xB85EF1C8, 0xB85F02DC } // size 4376 (4 kB) (0 MB) +// { 0xB85F1484, 0xB8601284 } // size 65028 (63 kB) (0 MB) +// { 0xB8601480, 0xB8604FFC } // size 15232 (14 kB) (0 MB) +// { 0xB8608F18, 0xB86147F8 } // size 47332 (46 kB) (0 MB) +// { 0xB8615000, 0xB8615FFC } // size 4096 (4 kB) (0 MB) +// { 0xB861CA00, 0xB861DF40 } // size 5444 (5 kB) (0 MB) +// { 0xB861F3E4, 0xB8632B00 } // size 79648 (77 kB) (0 MB) +// { 0xB8639790, 0xB8649BC0 } // size 66612 (65 kB) (0 MB) +// { 0xB86502E0, 0xB865EE00 } // size 60196 (58 kB) (0 MB) +// { 0xB86601FC, 0xB8667EE0 } // size 31976 (31 kB) (0 MB) +// { 0xB866A894, 0xB866B6C0 } // size 3632 (3 kB) (0 MB) +// { 0xB866BF58, 0xB86745A0 } // size 34380 (33 kB) (0 MB) +// { 0xB86807B4, 0xB868D680 } // size 52944 (51 kB) (0 MB) +// { 0xB8690D2C, 0xB86B3CA0 } // size 143224 (139 kB) (0 MB) +// { 0xB86C45F8, 0xB86D2900 } // size 58124 (56 kB) (0 MB) +// { 0xB86D7AA4, 0xB86EEB80 } // size 94432 (92 kB) (0 MB) +// { 0xB86F0700, 0xB86F1FC0 } // size 6340 (6 kB) (0 MB) +// { 0xB86F21A0, 0xB86F2BB8 } // size 2588 (2 kB) (0 MB) +// { 0xB86F3290, 0xB86F73A0 } // size 16660 (16 kB) (0 MB) +// { 0xB86F740C, 0xB8702DC0 } // size 47544 (46 kB) (0 MB) +// { 0xB8704880, 0xB871E3C0 } // size 105284 (102 kB) (0 MB) +// { 0xB87202F0, 0xB8720D80 } // size 2708 (2 kB) (0 MB) +// { 0xB8721978, 0xB872AD80 } // size 37900 (37 kB) (0 MB) +// { 0xB873B684, 0xB874C180 } // size 68352 (66 kB) (0 MB) +// { 0xB8751354, 0xB8769780 } // size 99376 (97 kB) (0 MB) +// { 0xB876CC88, 0xB876D5C8 } // size 2372 (2 kB) (0 MB) +// { 0xB87768AC, 0xB877BF7C } // size 22228 (21 kB) (0 MB) +// { 0xB877C238, 0xB8788B40 } // size 51468 (50 kB) (0 MB) +// { 0xB8789618, 0xB878A67C } // size 4200 (4 kB) (0 MB) +// { 0xB878A684, 0xB878B6FC } // size 4220 (4 kB) (0 MB) +// { 0xB878B798, 0xB878C7FC } // size 4200 (4 kB) (0 MB) +// { 0xB878C804, 0xB878D87C } // size 4220 (4 kB) (0 MB) +// { 0xB878D918, 0xB878E97C } // size 4200 (4 kB) (0 MB) +// { 0xB878E984, 0xB878F9FC } // size 4220 (4 kB) (0 MB) +// { 0xB878FA98, 0xB8790AFC } // size 4200 (4 kB) (0 MB) +// { 0xB8790B04, 0xB8791B7C } // size 4220 (4 kB) (0 MB) +// { 0xB8791C18, 0xB8792C7C } // size 4200 (4 kB) (0 MB) +// { 0xB8792C84, 0xB8793CFC } // size 4220 (4 kB) (0 MB) +// { 0xB8793D98, 0xB8794DFC } // size 4200 (4 kB) (0 MB) +// { 0xB8794E04, 0xB8795E7C } // size 4220 (4 kB) (0 MB) +// { 0xB8795F18, 0xB8796F7C } // size 4200 (4 kB) (0 MB) +// { 0xB8796F84, 0xB8797FFC } // size 4220 (4 kB) (0 MB) +// { 0xB8798098, 0xB87990FC } // size 4200 (4 kB) (0 MB) +// { 0xB8799104, 0xB879A17C } // size 4220 (4 kB) (0 MB) +// { 0xB879A218, 0xB879B27C } // size 4200 (4 kB) (0 MB) +// { 0xB879B284, 0xB879C2FC } // size 4220 (4 kB) (0 MB) +// { 0xB879C398, 0xB879D3FC } // size 4200 (4 kB) (0 MB) +// { 0xB879D404, 0xB879E47C } // size 4220 (4 kB) (0 MB) +// { 0xB879E518, 0xB879F57C } // size 4200 (4 kB) (0 MB) +// { 0xB879F584, 0xB87A05FC } // size 4220 (4 kB) (0 MB) +// { 0xB87A0698, 0xB87A16FC } // size 4200 (4 kB) (0 MB) +// { 0xB87A1704, 0xB87A277C } // size 4220 (4 kB) (0 MB) +// { 0xB87A2818, 0xB87A387C } // size 4200 (4 kB) (0 MB) +// { 0xB87A3884, 0xB87A48FC } // size 4220 (4 kB) (0 MB) +// { 0xB87A4998, 0xB87A59FC } // size 4200 (4 kB) (0 MB) +// { 0xB87A5A04, 0xB87A6A7C } // size 4220 (4 kB) (0 MB) +// { 0xB87A6B18, 0xB87A7B7C } // size 4200 (4 kB) (0 MB) +// { 0xB87A7B84, 0xB87A8BFC } // size 4220 (4 kB) (0 MB) +// { 0xB87A8C98, 0xB87A9CFC } // size 4200 (4 kB) (0 MB) +// { 0xB87A9D04, 0xB87AAD7C } // size 4220 (4 kB) (0 MB) +// { 0xB87AAE18, 0xB87ABE7C } // size 4200 (4 kB) (0 MB) +// { 0xB87ABE84, 0xB87ACEFC } // size 4220 (4 kB) (0 MB) +// { 0xB87AD004, 0xB87ADFFC } // size 4092 (3 kB) (0 MB) +// { 0xB87AE004, 0xB87AF07C } // size 4220 (4 kB) (0 MB) +// { 0xB87AF118, 0xB87B017C } // size 4200 (4 kB) (0 MB) +// { 0xB87B0184, 0xB87B11FC } // size 4220 (4 kB) (0 MB) +// { 0xB87B1298, 0xB87B22FC } // size 4200 (4 kB) (0 MB) +// { 0xB87B2304, 0xB87B337C } // size 4220 (4 kB) (0 MB) +// { 0xB87B3418, 0xB87B447C } // size 4200 (4 kB) (0 MB) +// { 0xB87B474C, 0xB87B54FC } // size 3508 (3 kB) (0 MB) +// { 0xB87B5598, 0xB87B65FC } // size 4200 (4 kB) (0 MB) +// { 0xB87B6684, 0xB87B767C } // size 4092 (3 kB) (0 MB) +// { 0xB87B7718, 0xB87B877C } // size 4200 (4 kB) (0 MB) +// { 0xB87B8784, 0xB87B97FC } // size 4220 (4 kB) (0 MB) +// { 0xB87B9898, 0xB87BA8FC } // size 4200 (4 kB) (0 MB) +// { 0xB87BA904, 0xB87BB97C } // size 4220 (4 kB) (0 MB) +// { 0xB87BBA18, 0xB87BCA7C } // size 4200 (4 kB) (0 MB) +// { 0xB87BCA84, 0xB87BDAFC } // size 4220 (4 kB) (0 MB) +// { 0xB87BDB98, 0xB87BEBFC } // size 4200 (4 kB) (0 MB) +// { 0xB87BEC04, 0xB87BFC7C } // size 4220 (4 kB) (0 MB) +// { 0xB87BFD18, 0xB87C0D7C } // size 4200 (4 kB) (0 MB) +// { 0xB87C0D84, 0xB87C1DFC } // size 4220 (4 kB) (0 MB) +// { 0xB87C1E98, 0xB87C2EFC } // size 4200 (4 kB) (0 MB) +// { 0xB87C2F04, 0xB87C3F7C } // size 4220 (4 kB) (0 MB) +// { 0xB87C4018, 0xB87C507C } // size 4200 (4 kB) (0 MB) +// { 0xB87C5084, 0xB87C60FC } // size 4220 (4 kB) (0 MB) +// { 0xB87C6198, 0xB87C71FC } // size 4200 (4 kB) (0 MB) +// { 0xB87C7204, 0xB87C827C } // size 4220 (4 kB) (0 MB) +// { 0xB87C8318, 0xB87C937C } // size 4200 (4 kB) (0 MB) +// { 0xB87C9384, 0xB87CA3FC } // size 4220 (4 kB) (0 MB) +// { 0xB87CA498, 0xB87CB4FC } // size 4200 (4 kB) (0 MB) +// { 0xB87CB504, 0xB87CC57C } // size 4220 (4 kB) (0 MB) +// { 0xB87CC618, 0xB87CD67C } // size 4200 (4 kB) (0 MB) +// { 0xB87CD684, 0xB87CE6FC } // size 4220 (4 kB) (0 MB) +// { 0xB87CE798, 0xB87CF7FC } // size 4200 (4 kB) (0 MB) +// { 0xB87CF804, 0xB87D087C } // size 4220 (4 kB) (0 MB) +// { 0xB87D0918, 0xB87D197C } // size 4200 (4 kB) (0 MB) +// { 0xB87D1984, 0xB87D29FC } // size 4220 (4 kB) (0 MB) +// { 0xB87D2A98, 0xB87D3AFC } // size 4200 (4 kB) (0 MB) +// { 0xB87D3B04, 0xB87D4B7C } // size 4220 (4 kB) (0 MB) +// { 0xB87D4C18, 0xB87D5C7C } // size 4200 (4 kB) (0 MB) +// { 0xB87D5C84, 0xB87D6CFC } // size 4220 (4 kB) (0 MB) +// { 0xB87D6D98, 0xB87D7DFC } // size 4200 (4 kB) (0 MB) +// { 0xB87D7E04, 0xB87D8EFC } // size 4348 (4 kB) (0 MB) +// { 0xB87D8F18, 0xB87D9F7C } // size 4200 (4 kB) (0 MB) +// { 0xB87D9F84, 0xB87DB07C } // size 4348 (4 kB) (0 MB) +// { 0xB87DB098, 0xB87DC0FC } // size 4200 (4 kB) (0 MB) +// { 0xB87DC104, 0xB87DD17C } // size 4220 (4 kB) (0 MB) +// { 0xB87DD284, 0xB87DE27C } // size 4092 (3 kB) (0 MB) +// { 0xB87DE284, 0xB87DF37C } // size 4348 (4 kB) (0 MB) +// { 0xB87DF398, 0xB87E03FC } // size 4200 (4 kB) (0 MB) +// { 0xB87E06CC, 0xB87E147C } // size 3508 (3 kB) (0 MB) +// { 0xB87E1518, 0xB87E257C } // size 4200 (4 kB) (0 MB) +// { 0xB87E2604, 0xB87E35FC } // size 4092 (3 kB) (0 MB) +// { 0xB87E3698, 0xB87E46FC } // size 4200 (4 kB) (0 MB) +// { 0xB87E4704, 0xB87E577C } // size 4220 (4 kB) (0 MB) +// { 0xB87E5818, 0xB87E687C } // size 4200 (4 kB) (0 MB) +// { 0xB87E6884, 0xB87E78FC } // size 4220 (4 kB) (0 MB) +// { 0xB87E7998, 0xB87E89FC } // size 4200 (4 kB) (0 MB) +// { 0xB87E8A04, 0xB87E9A7C } // size 4220 (4 kB) (0 MB) +// { 0xB87E9B18, 0xB87EAB7C } // size 4200 (4 kB) (0 MB) +// { 0xB87EAB84, 0xB87EBBFC } // size 4220 (4 kB) (0 MB) +// { 0xB87EBC98, 0xB87ECCFC } // size 4200 (4 kB) (0 MB) +// { 0xB87ECD04, 0xB87EDD7C } // size 4220 (4 kB) (0 MB) +// { 0xB87EDE18, 0xB87EEE7C } // size 4200 (4 kB) (0 MB) +// { 0xB87EEE84, 0xB87EFEFC } // size 4220 (4 kB) (0 MB) +// { 0xB87EFF98, 0xB87F0FFC } // size 4200 (4 kB) (0 MB) +// { 0xB87F1004, 0xB87F207C } // size 4220 (4 kB) (0 MB) +// { 0xB87F2118, 0xB87F317C } // size 4200 (4 kB) (0 MB) +// { 0xB87F3184, 0xB87F41FC } // size 4220 (4 kB) (0 MB) +// { 0xB87F4298, 0xB87F52FC } // size 4200 (4 kB) (0 MB) +// { 0xB87F5304, 0xB87F637C } // size 4220 (4 kB) (0 MB) +// { 0xB87F6418, 0xB87F747C } // size 4200 (4 kB) (0 MB) +// { 0xB87F7484, 0xB87F84FC } // size 4220 (4 kB) (0 MB) +// { 0xB87F8598, 0xB87F95FC } // size 4200 (4 kB) (0 MB) +// { 0xB87F9604, 0xB87FA67C } // size 4220 (4 kB) (0 MB) +// { 0xB87FA718, 0xB87FB77C } // size 4200 (4 kB) (0 MB) +// { 0xB87FB784, 0xB87FC7FC } // size 4220 (4 kB) (0 MB) +// { 0xB87FC898, 0xB87FD8FC } // size 4200 (4 kB) (0 MB) +// { 0xB87FD904, 0xB87FE97C } // size 4220 (4 kB) (0 MB) +// { 0xB87FEA18, 0xB87FFA7C } // size 4200 (4 kB) (0 MB) +// { 0xB87FFA84, 0xB8800AFC } // size 4220 (4 kB) (0 MB) +// { 0xB8800B98, 0xB8801BFC } // size 4200 (4 kB) (0 MB) +// { 0xB8801C04, 0xB8802C7C } // size 4220 (4 kB) (0 MB) +// { 0xB8802D18, 0xB8803D7C } // size 4200 (4 kB) (0 MB) +// { 0xB8803D84, 0xB8804E7C } // size 4348 (4 kB) (0 MB) +// { 0xB8804E98, 0xB8805EFC } // size 4200 (4 kB) (0 MB) +// { 0xB8805F04, 0xB8806FFC } // size 4348 (4 kB) (0 MB) +// { 0xB8807018, 0xB880807C } // size 4200 (4 kB) (0 MB) +// { 0xB8808084, 0xB88090FC } // size 4220 (4 kB) (0 MB) +// { 0xB8809204, 0xB880A1FC } // size 4092 (3 kB) (0 MB) +// { 0xB880A204, 0xB880B2FC } // size 4348 (4 kB) (0 MB) +// { 0xB880B318, 0xB880C37C } // size 4200 (4 kB) (0 MB) +// { 0xB880C64C, 0xB880D3FC } // size 3508 (3 kB) (0 MB) +// { 0xB880D498, 0xB880E4FC } // size 4200 (4 kB) (0 MB) +// { 0xB880E584, 0xB880F57C } // size 4092 (3 kB) (0 MB) +// { 0xB880F584, 0xB881183C } // size 8892 (8 kB) (0 MB) +// { 0xB8811844, 0xB881B680 } // size 40512 (39 kB) (0 MB) +// { 0xB882058C, 0xB882F6E0 } // size 61784 (60 kB) (0 MB) +// { 0xB8832638, 0xB883AA40 } // size 33804 (33 kB) (0 MB) +// { 0xB883ECDC, 0xB883F900 } // size 3112 (3 kB) (0 MB) +// { 0xB8840298, 0xB8847BC0 } // size 31020 (30 kB) (0 MB) +// { 0xB88485D0, 0xB88565BC } // size 57328 (55 kB) (0 MB) +// { 0xB88565D8, 0xB88626D4 } // size 49408 (48 kB) (0 MB) +// { 0xB88627DC, 0xB8872900 } // size 65832 (64 kB) (0 MB) +// { 0xB8875AE0, 0xB8883100 } // size 54820 (53 kB) (0 MB) +// { 0xB888482C, 0xB8885EBC } // size 5780 (5 kB) (0 MB) +// { 0xB8885ED8, 0xB888B100 } // size 21036 (20 kB) (0 MB) +// { 0xB888D590, 0xB8891F40 } // size 18868 (18 kB) (0 MB) +// { 0xB88954F8, 0xB8895CF8 } // size 2052 (2 kB) (0 MB) +// { 0xB8897854, 0xB8898054 } // size 2052 (2 kB) (0 MB) +// { 0xB88998F4, 0xB889C350 } // size 10848 (10 kB) (0 MB) +// { 0xB889C35C, 0xB889D780 } // size 5160 (5 kB) (0 MB) +// { 0xB889DA80, 0xB88A9A80 } // size 49156 (48 kB) (0 MB) +// { 0xB88A9A88, 0xB88B5C88 } // size 49668 (48 kB) (0 MB) +// { 0xB88B5C90, 0xB88C1E90 } // size 49668 (48 kB) (0 MB) +// { 0xB88C1E98, 0xB88EB09C } // size 168456 (164 kB) (0 MB) +// { 0xB88EB0A4, 0xB88EEC10 } // size 15216 (14 kB) (0 MB) +// { 0xB88EEC30, 0xB8B06E94 } // size 2196072 (2144 kB) (2 MB) +// { 0xB8B06EC4, 0xB8B930C0 } // size 573952 (560 kB) (0 MB) +// { 0xB8BA1868, 0xB8BC22A0 } // size 133692 (130 kB) (0 MB) +// { 0xB8BC47F0, 0xB8BDEC80 } // size 107668 (105 kB) (0 MB) +// { 0xB8BDFBF4, 0xB8BE2640 } // size 10832 (10 kB) (0 MB) +// { 0xB8BE2C7C, 0xB8BE3D8C } // size 4372 (4 kB) (0 MB) +// { 0xB8BE3DC0, 0xB8C02280 } // size 124100 (121 kB) (0 MB) +// { 0xB8C02FC8, 0xB8C19920 } // size 92508 (90 kB) (0 MB) +// { 0xB8C2D35C, 0xB8C3DDC0 } // size 68200 (66 kB) (0 MB) +// { 0xB8C48654, 0xB8C6E2E0 } // size 154768 (151 kB) (0 MB) +// { 0xB8C80608, 0xB8C87040 } // size 27196 (26 kB) (0 MB) +// { 0xB8C8C694, 0xB8C8F3C0 } // size 11568 (11 kB) (0 MB) +// { 0xB8C90734, 0xB8C94904 } // size 16852 (16 kB) (0 MB) +// { 0xB8C94970, 0xB8CA1500 } // size 52116 (50 kB) (0 MB) +// { 0xB8CA28B8, 0xB8CA5080 } // size 10188 (9 kB) (0 MB) +// { 0xB8CA50C4, 0xB8CA6E94 } // size 7636 (7 kB) (0 MB) +// { 0xB8CA7104, 0xB8CA88AC } // size 6060 (5 kB) (0 MB) +// { 0xB8CA9144, 0xB8CAAF14 } // size 7636 (7 kB) (0 MB) +// { 0xB8CAB180, 0xB8CAD180 } // size 8196 (8 kB) (0 MB) +// { 0xB8CADB7C, 0xB8CAEFC0 } // size 5192 (5 kB) (0 MB) +// { 0xB8CF81C0, 0xB8CF8F3C } // size 3456 (3 kB) (0 MB) +// { 0xB8CF8F44, 0xB8CF9E8C } // size 3916 (3 kB) (0 MB) +// { 0xB8CFA100, 0xB8CFA9C4 } // size 2248 (2 kB) (0 MB) +// { 0xB8CFB940, 0xB8CFCD30 } // size 5108 (4 kB) (0 MB) +// { 0xB8CFDD40, 0xB8CFECFC } // size 4032 (3 kB) (0 MB) +// { 0xB8CFEEE0, 0xB8CFFEFC } // size 4128 (4 kB) (0 MB) +// { 0xB8CFFF38, 0xB8D021FC } // size 8904 (8 kB) (0 MB) +// { 0xB8D0221C, 0xB8D035FC } // size 5092 (4 kB) (0 MB) +// { 0xB8D04E04, 0xB8D36934 } // size 203572 (198 kB) (0 MB) +// { 0xB8D3C194, 0xB8D3CE30 } // size 3232 (3 kB) (0 MB) +// { 0xB8D3CF44, 0xB8D3DBE0 } // size 3232 (3 kB) (0 MB) +// { 0xB8D3DCF4, 0xB8D3E990 } // size 3232 (3 kB) (0 MB) +// { 0xB8D3EAA4, 0xB8D3F740 } // size 3232 (3 kB) (0 MB) +// { 0xB8D3F850, 0xB8D404F0 } // size 3236 (3 kB) (0 MB) +// { 0xB8D40600, 0xB8D412A0 } // size 3236 (3 kB) (0 MB) +// { 0xB8D413B0, 0xB8D42050 } // size 3236 (3 kB) (0 MB) +// { 0xB8D47148, 0xB8D485C0 } // size 5244 (5 kB) (0 MB) +// { 0xB8D488D4, 0xB8D49D40 } // size 5232 (5 kB) (0 MB) +// { 0xB8D49FE4, 0xB8D4B440 } // size 5216 (5 kB) (0 MB) +// { 0xB8D4B7EC, 0xB8D4CC40 } // size 5208 (5 kB) (0 MB) +// { 0xB8D81D64, 0xB8D8FF8C } // size 57900 (56 kB) (0 MB) +// { 0xB8D954E0, 0xB8D9634C } // size 3696 (3 kB) (0 MB) +// { 0xB8D9A238, 0xB8D9C1CC } // size 8088 (7 kB) (0 MB) +// { 0xB8D9D258, 0xB8D9F1EC } // size 8088 (7 kB) (0 MB) +// { 0xB8D9FF20, 0xB8DA1EB4 } // size 8088 (7 kB) (0 MB) +// { 0xB8DB58E0, 0xB8DB74C0 } // size 7140 (6 kB) (0 MB) +// { 0xB8DB7E4C, 0xB8DB8C1C } // size 3540 (3 kB) (0 MB) +// { 0xB8DB95A8, 0xB8DBAA3C } // size 5272 (5 kB) (0 MB) +// { 0xB8DC6A0C, 0xB8E14284 } // size 317564 (310 kB) (0 MB) +// { 0xB8E142B0, 0xB8E152B0 } // size 4100 (4 kB) (0 MB) +// { 0xB8E15554, 0xB8E16360 } // size 3600 (3 kB) (0 MB) +// { 0xB8E18548, 0xB8E19544 } // size 4096 (4 kB) (0 MB) +// { 0xB8E1A1E0, 0xB8E1C1DC } // size 8192 (8 kB) (0 MB) +// { 0xB8E1D200, 0xB8E1F1FC } // size 8192 (8 kB) (0 MB) +// { 0xB8E1FEC8, 0xB8E21EC4 } // size 8192 (8 kB) (0 MB) +// { 0xB8E21ED4, 0xB8EC8294 } // size 680900 (664 kB) (0 MB) +// { 0xB8EC82C0, 0xB8EC92C0 } // size 4100 (4 kB) (0 MB) +// { 0xB8EC9380, 0xB8ECA370 } // size 4084 (3 kB) (0 MB) +// { 0xB8ECE1F0, 0xB8ED01EC } // size 8192 (8 kB) (0 MB) +// { 0xB8ED1210, 0xB8ED320C } // size 8192 (8 kB) (0 MB) +// { 0xB8ED3ED8, 0xB8ED5ED4 } // size 8192 (8 kB) (0 MB) +// { 0xB8ED9AE8, 0xB8EDC63C } // size 11096 (10 kB) (0 MB) +// { 0xB8EDC678, 0xB8EDCF34 } // size 2240 (2 kB) (0 MB) +// { 0xB8EDDC7C, 0xB8F7C2A4 } // size 648748 (633 kB) (0 MB) +// { 0xB8F7C2D0, 0xB8F7D2D0 } // size 4100 (4 kB) (0 MB) +// { 0xB8F7D574, 0xB8F7E380 } // size 3600 (3 kB) (0 MB) +// { 0xB8F80568, 0xB8F81564 } // size 4096 (4 kB) (0 MB) +// { 0xB8F82200, 0xB8F841FC } // size 8192 (8 kB) (0 MB) +// { 0xB8F85220, 0xB8F8721C } // size 8192 (8 kB) (0 MB) +// { 0xB8F87EE8, 0xB8F89EE4 } // size 8192 (8 kB) (0 MB) +// { 0xB8F89EF4, 0xB90302B4 } // size 680900 (664 kB) (0 MB) +// { 0xB9030800, 0xB93F69FC } // size 3957248 (3864 kB) (3 MB) +// { 0xB94128D4, 0xB94179C0 } // size 20720 (20 kB) (0 MB) +// { 0xB942587C, 0xB94307FC } // size 44932 (43 kB) (0 MB) +// { 0xB96CE000, 0xB96E0A9C } // size 76448 (74 kB) (0 MB) +// { 0xB970200C, 0xB98B9C54 } // size 1801292 (1759 kB) (1 MB) +// { 0xB98E9794, 0xB98F1794 } // size 32772 (32 kB) (0 MB) +// { 0xB9F13600, 0xB9F175FC } // size 16384 (16 kB) (0 MB) +// { 0xB9F17658, 0xB9F67658 } // size 327684 (320 kB) (0 MB) +// { 0xB9F6779C, 0xB9FB779C } // size 327684 (320 kB) (0 MB) +// { 0xB9FB78E0, 0xBA0078E0 } // size 327684 (320 kB) (0 MB) +// { 0xBA007A24, 0xBA057A24 } // size 327684 (320 kB) (0 MB) +// { 0xBA057B68, 0xBA1B9578 } // size 1448468 (1414 kB) (1 MB) +// { 0xBA1BA20C, 0xBA1BBFF8 } // size 7664 (7 kB) (0 MB) +// { 0xBA1BC04C, 0xBA1BDFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA1BE0DC, 0xBA1BFFFC } // size 7972 (7 kB) (0 MB) +// { 0xBA1C7028, 0xBA1C7FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA1CA23C, 0xBA1CBFF8 } // size 7616 (7 kB) (0 MB) +// { 0xBA1CC044, 0xBA1CDFFC } // size 8124 (7 kB) (0 MB) +// { 0xBA1CE2E4, 0xBA1CFFFC } // size 7452 (7 kB) (0 MB) +// { 0xBA1D4028, 0xBA1D5FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA1DA698, 0xBA1DBFFC } // size 6504 (6 kB) (0 MB) +// { 0xBA1E02D0, 0xBA1E1FFC } // size 7472 (7 kB) (0 MB) +// { 0xBA1E6028, 0xBA1E7FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA1EC028, 0xBA1EDFFC } // size 8152 (7 kB) (0 MB) +// { 0xBA1F2028, 0xBA1F3FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA1F8028, 0xBA1F9FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA1FE028, 0xBA1FFFFC } // size 8152 (7 kB) (0 MB) +// { 0xBA204674, 0xBA205FFC } // size 6540 (6 kB) (0 MB) +// { 0xBA20A028, 0xBA20BFFC } // size 8152 (7 kB) (0 MB) +// { 0xBA210028, 0xBA211FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA234050, 0xBA235FFC } // size 8112 (7 kB) (0 MB) +// { 0xBA2360AC, 0xBA236FFC } // size 3924 (3 kB) (0 MB) +// { 0xBA2587BC, 0xBA259FF8 } // size 6208 (6 kB) (0 MB) +// { 0xBA25A04C, 0xBA25BFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA25C07C, 0xBA25CFFC } // size 3972 (3 kB) (0 MB) +// { 0xBA26109C, 0xBA261FF8 } // size 3936 (3 kB) (0 MB) +// { 0xBA262054, 0xBA263FFC } // size 8108 (7 kB) (0 MB) +// { 0xBA2643C8, 0xBA265FFC } // size 7224 (7 kB) (0 MB) +// { 0xBA26E028, 0xBA26EFFC } // size 4056 (3 kB) (0 MB) +// { 0xBA271028, 0xBA271FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA274028, 0xBA2751FC } // size 4568 (4 kB) (0 MB) +// { 0xBA2752C0, 0xBA275FFC } // size 3392 (3 kB) (0 MB) +// { 0xBA276028, 0xBA277FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA27C028, 0xBA27E1FC } // size 8664 (8 kB) (0 MB) +// { 0xBA282028, 0xBA282FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA285028, 0xBA285FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA2A0154, 0xBA2A1FFC } // size 7852 (7 kB) (0 MB) +// { 0xBA2A6504, 0xBA2A81FC } // size 7420 (7 kB) (0 MB) +// { 0xBA2AC028, 0xBA2ADFFC } // size 8152 (7 kB) (0 MB) +// { 0xBA2B249C, 0xBA2B3FF8 } // size 7008 (6 kB) (0 MB) +// { 0xBA2B4044, 0xBA2B5FFC } // size 8124 (7 kB) (0 MB) +// { 0xBA2F0AFC, 0xBA2F1FF8 } // size 5376 (5 kB) (0 MB) +// { 0xBA2F2068, 0xBA2F3FFC } // size 8088 (7 kB) (0 MB) +// { 0xBA2F412C, 0xBA2F5FFC } // size 7892 (7 kB) (0 MB) +// { 0xBA2F67FC, 0xBA2F7FF8 } // size 6144 (6 kB) (0 MB) +// { 0xBA2F804C, 0xBA2F9FFC } // size 8116 (7 kB) (0 MB) +// { 0xBA2FA2C8, 0xBA2FBFFC } // size 7480 (7 kB) (0 MB) +// { 0xBA2FC294, 0xBA2FE1FC } // size 8044 (7 kB) (0 MB) +// { 0xBA302028, 0xBA3041FC } // size 8664 (8 kB) (0 MB) +// { 0xBA318828, 0xBA319FFC } // size 6104 (5 kB) (0 MB) +// { 0xBA31E1A0, 0xBA31FFFC } // size 7776 (7 kB) (0 MB) +// { 0xBA3227F0, 0xBA323FFC } // size 6160 (6 kB) (0 MB) +// { 0xBA334828, 0xBA335FFC } // size 6104 (5 kB) (0 MB) +// { 0xBA33E048, 0xBA33FFFC } // size 8120 (7 kB) (0 MB) +// { 0xBA342F80, 0xBA3437FC } // size 2176 (2 kB) (0 MB) +// { 0xBA343828, 0xBA344044 } // size 2080 (2 kB) (0 MB) +// { 0xBA346028, 0xBA346954 } // size 2352 (2 kB) (0 MB) +// { 0xBA348828, 0xBA349124 } // size 2304 (2 kB) (0 MB) +// { 0xBA355828, 0xBA356574 } // size 3408 (3 kB) (0 MB) +// { 0xBA35E04C, 0xBA35FFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA360080, 0xBA360FFC } // size 3968 (3 kB) (0 MB) +// { 0xBA361444, 0xBA361FFC } // size 3004 (2 kB) (0 MB) +// { 0xBA36423C, 0xBA365FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBA3E2048, 0xBA3E3FFC } // size 8120 (7 kB) (0 MB) +// { 0xBA3E4B3C, 0xBA3E5FF8 } // size 5312 (5 kB) (0 MB) +// { 0xBA3E6054, 0xBA3E7FFC } // size 8108 (7 kB) (0 MB) +// { 0xBA3E895C, 0xBA3E9FF8 } // size 5792 (5 kB) (0 MB) +// { 0xBA3EA050, 0xBA3EBFFC } // size 8112 (7 kB) (0 MB) +// { 0xBA3EC10C, 0xBA3EDFFC } // size 7924 (7 kB) (0 MB) +// { 0xBA3F2028, 0xBA3F2FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA3FF028, 0xBA3FFFFC } // size 4056 (3 kB) (0 MB) +// { 0xBA402028, 0xBA402FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA406048, 0xBA407FFC } // size 8120 (7 kB) (0 MB) +// { 0xBA40B5BC, 0xBA40BFF8 } // size 2624 (2 kB) (0 MB) +// { 0xBA40C04C, 0xBA40DFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA40E07C, 0xBA40EFFC } // size 3972 (3 kB) (0 MB) +// { 0xBA41521C, 0xBA415FF8 } // size 3552 (3 kB) (0 MB) +// { 0xBA416048, 0xBA417FFC } // size 8120 (7 kB) (0 MB) +// { 0xBA41807C, 0xBA418FFC } // size 3972 (3 kB) (0 MB) +// { 0xBA419300, 0xBA419FFC } // size 3328 (3 kB) (0 MB) +// { 0xBA45C89C, 0xBA45DFF8 } // size 5984 (5 kB) (0 MB) +// { 0xBA45E044, 0xBA45FFFC } // size 8124 (7 kB) (0 MB) +// { 0xBA4602E4, 0xBA461FFC } // size 7452 (7 kB) (0 MB) +// { 0xBA464DFC, 0xBA465FFC } // size 4612 (4 kB) (0 MB) +// { 0xBA466028, 0xBA4681FC } // size 8664 (8 kB) (0 MB) +// { 0xBA46AEFC, 0xBA46BFFC } // size 4356 (4 kB) (0 MB) +// { 0xBA46C028, 0xBA46E1FC } // size 8664 (8 kB) (0 MB) +// { 0xBA470EFC, 0xBA471FFC } // size 4356 (4 kB) (0 MB) +// { 0xBA472028, 0xBA472908 } // size 2276 (2 kB) (0 MB) +// { 0xBA477028, 0xBA4781FC } // size 4568 (4 kB) (0 MB) +// { 0xBA47AFFC, 0xBA47BFFC } // size 4100 (4 kB) (0 MB) +// { 0xBA47C028, 0xBA47D01C } // size 4088 (3 kB) (0 MB) +// { 0xBA47D840, 0xBA47E0A8 } // size 2156 (2 kB) (0 MB) +// { 0xBA47F028, 0xBA47FFFC } // size 4056 (3 kB) (0 MB) +// { 0xBA482CFC, 0xBA483FFC } // size 4868 (4 kB) (0 MB) +// { 0xBA484028, 0xBA485120 } // size 4348 (4 kB) (0 MB) +// { 0xBA485A40, 0xBA4862A8 } // size 2156 (2 kB) (0 MB) +// { 0xBA487598, 0xBA487FFC } // size 2664 (2 kB) (0 MB) +// { 0xBA48AFFC, 0xBA48BFFC } // size 4100 (4 kB) (0 MB) +// { 0xBA48C028, 0xBA48DFFC } // size 8152 (7 kB) (0 MB) +// { 0xBA490DFC, 0xBA491FFC } // size 4612 (4 kB) (0 MB) +// { 0xBA492B5C, 0xBA493FF8 } // size 5280 (5 kB) (0 MB) +// { 0xBA494044, 0xBA495FFC } // size 8124 (7 kB) (0 MB) +// { 0xBA49609C, 0xBA497FFC } // size 8036 (7 kB) (0 MB) +// { 0xBA49C24C, 0xBA49CFFC } // size 3508 (3 kB) (0 MB) +// { 0xBA49F23C, 0xBA49FFF8 } // size 3520 (3 kB) (0 MB) +// { 0xBA4A004C, 0xBA4A1FFC } // size 8116 (7 kB) (0 MB) +// { 0xBA4B223C, 0xBA4B3FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBA4B4048, 0xBA4B5FFC } // size 8120 (7 kB) (0 MB) +// { 0xBA4DA9FC, 0xBA4DBFF8 } // size 5632 (5 kB) (0 MB) +// { 0xBA4DC04C, 0xBA4DDFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA4FC19C, 0xBA4FDFF8 } // size 7776 (7 kB) (0 MB) +// { 0xBA4FE068, 0xBA4FFFFC } // size 8088 (7 kB) (0 MB) +// { 0xBA500054, 0xBA501FFC } // size 8108 (7 kB) (0 MB) +// { 0xBA5220A8, 0xBA523FFC } // size 8024 (7 kB) (0 MB) +// { 0xBA524054, 0xBA525FFC } // size 8108 (7 kB) (0 MB) +// { 0xBA5362F8, 0xBA5371E8 } // size 3828 (3 kB) (0 MB) +// { 0xBA55C91C, 0xBA55DFF8 } // size 5856 (5 kB) (0 MB) +// { 0xBA55E044, 0xBA55FFFC } // size 8124 (7 kB) (0 MB) +// { 0xBA560158, 0xBA561FFC } // size 7848 (7 kB) (0 MB) +// { 0xBA5639C0, 0xBA5644FC } // size 2880 (2 kB) (0 MB) +// { 0xBA5645BC, 0xBA565FFC } // size 6724 (6 kB) (0 MB) +// { 0xBA566028, 0xBA566FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA567B98, 0xBA5683FC } // size 2152 (2 kB) (0 MB) +// { 0xBA568718, 0xBA568FFC } // size 2280 (2 kB) (0 MB) +// { 0xBA569688, 0xBA569FFC } // size 2424 (2 kB) (0 MB) +// { 0xBA56B1D0, 0xBA56C1FC } // size 4144 (4 kB) (0 MB) +// { 0xBA56C2C0, 0xBA56CFFC } // size 3392 (3 kB) (0 MB) +// { 0xBA56D23C, 0xBA56DFF8 } // size 3520 (3 kB) (0 MB) +// { 0xBA56E044, 0xBA56FFFC } // size 8124 (7 kB) (0 MB) +// { 0xBA5702BC, 0xBA572014 } // size 7516 (7 kB) (0 MB) +// { 0xBA576028, 0xBA577FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA57A028, 0xBA57C3FC } // size 9176 (8 kB) (0 MB) +// { 0xBA582028, 0xBA583FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA586028, 0xBA587FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA58A028, 0xBA58BFFC } // size 8152 (7 kB) (0 MB) +// { 0xBA58E028, 0xBA58FFFC } // size 8152 (7 kB) (0 MB) +// { 0xBA592BBC, 0xBA593FF8 } // size 5184 (5 kB) (0 MB) +// { 0xBA594050, 0xBA595FFC } // size 8112 (7 kB) (0 MB) +// { 0xBA596298, 0xBA597FFC } // size 7528 (7 kB) (0 MB) +// { 0xBA5B0028, 0xBA5B1FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA5B6028, 0xBA5B71FC } // size 4568 (4 kB) (0 MB) +// { 0xBA5B72C0, 0xBA5B7FFC } // size 3392 (3 kB) (0 MB) +// { 0xBA5B8028, 0xBA5B9FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA5BE028, 0xBA5BE828 } // size 2052 (2 kB) (0 MB) +// { 0xBA5C4028, 0xBA5C4FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA5C7028, 0xBA5C7FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA5D0028, 0xBA5D1FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA5D6028, 0xBA5D7FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA5EC828, 0xBA5EE1FC } // size 6616 (6 kB) (0 MB) +// { 0xBA5F2028, 0xBA5F3FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA60204C, 0xBA603FFC } // size 8116 (7 kB) (0 MB) +// { 0xBA604080, 0xBA604FFC } // size 3968 (3 kB) (0 MB) +// { 0xBA60575C, 0xBA605FFC } // size 2212 (2 kB) (0 MB) +// { 0xBA60C048, 0xBA60DFFC } // size 8120 (7 kB) (0 MB) +// { 0xBA60E07C, 0xBA60EFFC } // size 3972 (3 kB) (0 MB) +// { 0xBA60F400, 0xBA60FFFC } // size 3072 (3 kB) (0 MB) +// { 0xBA61223C, 0xBA613FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBA614048, 0xBA615FFC } // size 8120 (7 kB) (0 MB) +// { 0xBA61819C, 0xBA619FF8 } // size 7776 (7 kB) (0 MB) +// { 0xBA61A04C, 0xBA61BFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA61C514, 0xBA61DFFC } // size 6892 (6 kB) (0 MB) +// { 0xBA6741A8, 0xBA674FFC } // size 3672 (3 kB) (0 MB) +// { 0xBA67D36C, 0xBA67DFFC } // size 3220 (3 kB) (0 MB) +// { 0xBA68E028, 0xBA68FFFC } // size 8152 (7 kB) (0 MB) +// { 0xBA692700, 0xBA693FFC } // size 6400 (6 kB) (0 MB) +// { 0xBA6953FC, 0xBA695FFC } // size 3076 (3 kB) (0 MB) +// { 0xBA6A5680, 0xBA6A60FC } // size 2688 (2 kB) (0 MB) +// { 0xBA6A6680, 0xBA6A71FC } // size 2944 (2 kB) (0 MB) +// { 0xBA6A7680, 0xBA6A7FFC } // size 2432 (2 kB) (0 MB) +// { 0xBA6A8658, 0xBA6A9FFC } // size 6568 (6 kB) (0 MB) +// { 0xBA6AF374, 0xBA6AFBFC } // size 2188 (2 kB) (0 MB) +// { 0xBA6B0174, 0xBA6B0DFC } // size 3212 (3 kB) (0 MB) +// { 0xBA6B1374, 0xBA6B1BFC } // size 2188 (2 kB) (0 MB) +// { 0xBA6B2DFC, 0xBA6B3FF8 } // size 4608 (4 kB) (0 MB) +// { 0xBA6B4050, 0xBA6B5FFC } // size 8112 (7 kB) (0 MB) +// { 0xBA6B6C1C, 0xBA6B7FF8 } // size 5088 (4 kB) (0 MB) +// { 0xBA6EB2FC, 0xBA6EBFF8 } // size 3328 (3 kB) (0 MB) +// { 0xBA6EC04C, 0xBA6EDFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA6EE1D0, 0xBA6F01FC } // size 8240 (8 kB) (0 MB) +// { 0xBA704AF8, 0xBA705FFC } // size 5384 (5 kB) (0 MB) +// { 0xBA7087F0, 0xBA709FFC } // size 6160 (6 kB) (0 MB) +// { 0xBA7128DC, 0xBA713FF8 } // size 5920 (5 kB) (0 MB) +// { 0xBA714048, 0xBA715FFC } // size 8120 (7 kB) (0 MB) +// { 0xBA716294, 0xBA717FFC } // size 7532 (7 kB) (0 MB) +// { 0xBA7181E4, 0xBA718FFC } // size 3612 (3 kB) (0 MB) +// { 0xBA71B028, 0xBA71BFFC } // size 4056 (3 kB) (0 MB) +// { 0xBA71E028, 0xBA71F1FC } // size 4568 (4 kB) (0 MB) +// { 0xBA71F2C0, 0xBA71FFFC } // size 3392 (3 kB) (0 MB) +// { 0xBA720028, 0xBA721FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA726254, 0xBA726FFC } // size 3500 (3 kB) (0 MB) +// { 0xBA729028, 0xBA729FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA737028, 0xBA737FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA73C028, 0xBA73E1FC } // size 8664 (8 kB) (0 MB) +// { 0xBA742028, 0xBA743FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA74841C, 0xBA749FF8 } // size 7136 (6 kB) (0 MB) +// { 0xBA74A04C, 0xBA74BFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA74C2A4, 0xBA74DFFC } // size 7516 (7 kB) (0 MB) +// { 0xBA750028, 0xBA750FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA753028, 0xBA7541FC } // size 4568 (4 kB) (0 MB) +// { 0xBA7542C0, 0xBA754FFC } // size 3392 (3 kB) (0 MB) +// { 0xBA755028, 0xBA755FFC } // size 4056 (3 kB) (0 MB) +// { 0xBA75D20C, 0xBA75DFFC } // size 3572 (3 kB) (0 MB) +// { 0xBA762254, 0xBA762FFC } // size 3500 (3 kB) (0 MB) +// { 0xBA76B028, 0xBA76BFFC } // size 4056 (3 kB) (0 MB) +// { 0xBA770028, 0xBA7721FC } // size 8664 (8 kB) (0 MB) +// { 0xBA776028, 0xBA777FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA77C41C, 0xBA77DFF8 } // size 7136 (6 kB) (0 MB) +// { 0xBA77E048, 0xBA77FFFC } // size 8120 (7 kB) (0 MB) +// { 0xBA780168, 0xBA781FFC } // size 7832 (7 kB) (0 MB) +// { 0xBA78257C, 0xBA782FFC } // size 2692 (2 kB) (0 MB) +// { 0xBA785160, 0xBA785FFC } // size 3744 (3 kB) (0 MB) +// { 0xBA792800, 0xBA7942FC } // size 6912 (6 kB) (0 MB) +// { 0xBA794800, 0xBA795FFC } // size 6144 (6 kB) (0 MB) +// { 0xBA796158, 0xBA7971FC } // size 4264 (4 kB) (0 MB) +// { 0xBA7972C0, 0xBA797FFC } // size 3392 (3 kB) (0 MB) +// { 0xBA79915C, 0xBA799FF8 } // size 3744 (3 kB) (0 MB) +// { 0xBA79A04C, 0xBA79BFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA79CBBC, 0xBA79DFF8 } // size 5184 (5 kB) (0 MB) +// { 0xBA79E04C, 0xBA79FFFC } // size 8116 (7 kB) (0 MB) +// { 0xBA7A007C, 0xBA7A0FFC } // size 3972 (3 kB) (0 MB) +// { 0xBA7A2DBC, 0xBA7A3FF8 } // size 4672 (4 kB) (0 MB) +// { 0xBA7A4048, 0xBA7A5FFC } // size 8120 (7 kB) (0 MB) +// { 0xBA7A607C, 0xBA7A6FFC } // size 3972 (3 kB) (0 MB) +// { 0xBA7A75B4, 0xBA7A7FFC } // size 2636 (2 kB) (0 MB) +// { 0xBA7AA23C, 0xBA7ABFF8 } // size 7616 (7 kB) (0 MB) +// { 0xBA7AC048, 0xBA7ADFFC } // size 8120 (7 kB) (0 MB) +// { 0xBA7D0F9C, 0xBA7D1FF8 } // size 4192 (4 kB) (0 MB) +// { 0xBA7D204C, 0xBA7D3FFC } // size 8116 (7 kB) (0 MB) +// { 0xBA7F25DC, 0xBA7F3FF8 } // size 6688 (6 kB) (0 MB) +// { 0xBA7F4050, 0xBA7F5FFC } // size 8112 (7 kB) (0 MB) +// { 0xBA7F6080, 0xBA7F6FFC } // size 3968 (3 kB) (0 MB) +// { 0xBA81A048, 0xBA81BFFC } // size 8120 (7 kB) (0 MB) +// { 0xBA81C15C, 0xBA81DFFC } // size 7844 (7 kB) (0 MB) +// { 0xBA81E1F8, 0xBA81EFFC } // size 3592 (3 kB) (0 MB) +// { 0xBA820780, 0xBA820FFC } // size 2176 (2 kB) (0 MB) +// { 0xBA821028, 0xBA8221FC } // size 4568 (4 kB) (0 MB) +// { 0xBA824610, 0xBA825FFC } // size 6640 (6 kB) (0 MB) +// { 0xBA8677DC, 0xBA867FF8 } // size 2080 (2 kB) (0 MB) +// { 0xBA868048, 0xBA869FFC } // size 8120 (7 kB) (0 MB) +// { 0xBA86A0D4, 0xBA86AFFC } // size 3884 (3 kB) (0 MB) +// { 0xBA86C240, 0xBA86D3FC } // size 4544 (4 kB) (0 MB) +// { 0xBA86F01C, 0xBA8703FC } // size 5092 (4 kB) (0 MB) +// { 0xBA87123C, 0xBA871FF8 } // size 3520 (3 kB) (0 MB) +// { 0xBA872048, 0xBA873FFC } // size 8120 (7 kB) (0 MB) +// { 0xBA87419C, 0xBA875FFC } // size 7780 (7 kB) (0 MB) +// { 0xBA878028, 0xBA87A3FC } // size 9176 (8 kB) (0 MB) +// { 0xBA87C20C, 0xBA87DFFC } // size 7668 (7 kB) (0 MB) +// { 0xBA880028, 0xBA881FFC } // size 8152 (7 kB) (0 MB) +// { 0xBA884BDC, 0xBA885FF8 } // size 5152 (5 kB) (0 MB) +// { 0xBA886044, 0xBA887FFC } // size 8124 (7 kB) (0 MB) +// { 0xBA88861C, 0xBA889FF8 } // size 6624 (6 kB) (0 MB) +// { 0xBA88A048, 0xBA88BFFC } // size 8120 (7 kB) (0 MB) +// { 0xBA88C75C, 0xBA88DFF8 } // size 6304 (6 kB) (0 MB) +// { 0xBA88E050, 0xBA88FFFC } // size 8112 (7 kB) (0 MB) +// { 0xBA890080, 0xBA890FFC } // size 3968 (3 kB) (0 MB) +// { 0xBA895528, 0xBA8CCA24 } // size 226560 (221 kB) (0 MB) +// { 0xBAA4E9DC, 0xBAA4FFF8 } // size 5664 (5 kB) (0 MB) +// { 0xBAA50048, 0xBAA51FFC } // size 8120 (7 kB) (0 MB) +// { 0xBAA5285C, 0xBAA53FF8 } // size 6048 (5 kB) (0 MB) +// { 0xBAA54044, 0xBAA55FFC } // size 8124 (7 kB) (0 MB) +// { 0xBAA56114, 0xBAA57FFC } // size 7916 (7 kB) (0 MB) +// { 0xBAA589E0, 0xBAA593FC } // size 2592 (2 kB) (0 MB) +// { 0xBAA5ABE0, 0xBAA5B5FC } // size 2592 (2 kB) (0 MB) +// { 0xBAA5C9E0, 0xBAA5D3FC } // size 2592 (2 kB) (0 MB) +// { 0xBAA5EBE0, 0xBAA5F5FC } // size 2592 (2 kB) (0 MB) +// { 0xBAA609E0, 0xBAA613FC } // size 2592 (2 kB) (0 MB) +// { 0xBAA62BE0, 0xBAA635FC } // size 2592 (2 kB) (0 MB) +// { 0xBAA649E0, 0xBAA653FC } // size 2592 (2 kB) (0 MB) +// { 0xBAA66BE0, 0xBAA675FC } // size 2592 (2 kB) (0 MB) +// { 0xBAA69308, 0xBAA69FFC } // size 3320 (3 kB) (0 MB) +// { 0xBAA6E374, 0xBAA6F1FC } // size 3724 (3 kB) (0 MB) +// { 0xBAA6FB98, 0xBAA705FC } // size 2664 (2 kB) (0 MB) +// { 0xBAA71998, 0xBAA723FC } // size 2664 (2 kB) (0 MB) +// { 0xBAA908BC, 0xBAA91FF8 } // size 5952 (5 kB) (0 MB) +// { 0xBAA92048, 0xBAA93FFC } // size 8120 (7 kB) (0 MB) +// { 0xBAA94384, 0xBAA95FFC } // size 7292 (7 kB) (0 MB) +// { 0xBAA9E028, 0xBAA9EFFC } // size 4056 (3 kB) (0 MB) +// { 0xBAAA1284, 0xBAAA1FFC } // size 3452 (3 kB) (0 MB) +// { 0xBAAA4154, 0xBAAA51FC } // size 4268 (4 kB) (0 MB) +// { 0xBAAA52C0, 0xBAAA5FFC } // size 3392 (3 kB) (0 MB) +// { 0xBAAA6028, 0xBAAA7FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAAAD27C, 0xBAAAE1FC } // size 3972 (3 kB) (0 MB) +// { 0xBAAB22A4, 0xBAAB2FFC } // size 3420 (3 kB) (0 MB) +// { 0xBAAB5028, 0xBAAB5FFC } // size 4056 (3 kB) (0 MB) +// { 0xBAACA828, 0xBAACBFFC } // size 6104 (5 kB) (0 MB) +// { 0xBAAD0028, 0xBAAD1FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAAD628C, 0xBAAD81FC } // size 8052 (7 kB) (0 MB) +// { 0xBAADC028, 0xBAADDFFC } // size 8152 (7 kB) (0 MB) +// { 0xBAAE223C, 0xBAAE3FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBAAE4050, 0xBAAE5FFC } // size 8112 (7 kB) (0 MB) +// { 0xBAAE699C, 0xBAAE7FF8 } // size 5728 (5 kB) (0 MB) +// { 0xBAAE804C, 0xBAAE9FFC } // size 8116 (7 kB) (0 MB) +// { 0xBAAEB31C, 0xBAAEBFF8 } // size 3296 (3 kB) (0 MB) +// { 0xBAAEC050, 0xBAAEDFFC } // size 8112 (7 kB) (0 MB) +// { 0xBAAF8058, 0xBAAF9FFC } // size 8104 (7 kB) (0 MB) +// { 0xBAAFAC9C, 0xBAAFBFF8 } // size 4960 (4 kB) (0 MB) +// { 0xBAAFC054, 0xBAAFDFFC } // size 8108 (7 kB) (0 MB) +// { 0xBAAFE1E4, 0xBAB001FC } // size 8220 (8 kB) (0 MB) +// { 0xBAB04028, 0xBAB051FC } // size 4568 (4 kB) (0 MB) +// { 0xBAB052C0, 0xBAB05FFC } // size 3392 (3 kB) (0 MB) +// { 0xBAB06028, 0xBAB07FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAB26028, 0xBAB27FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAB2E828, 0xBAB301FC } // size 6616 (6 kB) (0 MB) +// { 0xBAB34028, 0xBAB35FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAB3EC5C, 0xBAB3FFF8 } // size 5024 (4 kB) (0 MB) +// { 0xBAB40048, 0xBAB41FFC } // size 8120 (7 kB) (0 MB) +// { 0xBAB420A8, 0xBAB42FFC } // size 3928 (3 kB) (0 MB) +// { 0xBAB43304, 0xBAB43FFC } // size 3324 (3 kB) (0 MB) +// { 0xBAB45780, 0xBAB45FFC } // size 2176 (2 kB) (0 MB) +// { 0xBAB4623C, 0xBAB47FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBAB4804C, 0xBAB49FFC } // size 8116 (7 kB) (0 MB) +// { 0xBAB4A360, 0xBAB4BFFC } // size 7328 (7 kB) (0 MB) +// { 0xBAB4C64C, 0xBAB4CFFC } // size 2484 (2 kB) (0 MB) +// { 0xBAB55028, 0xBAB55FFC } // size 4056 (3 kB) (0 MB) +// { 0xBAB5A028, 0xBAB5B1FC } // size 4568 (4 kB) (0 MB) +// { 0xBAB5B2C0, 0xBAB5BFFC } // size 3392 (3 kB) (0 MB) +// { 0xBAB5C028, 0xBAB5E1FC } // size 8664 (8 kB) (0 MB) +// { 0xBAB60710, 0xBAB61FFC } // size 6384 (6 kB) (0 MB) +// { 0xBAB62028, 0xBAB63FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAB666F0, 0xBAB67FFC } // size 6416 (6 kB) (0 MB) +// { 0xBAB68028, 0xBAB69FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAB6C510, 0xBAB6DFFC } // size 6896 (6 kB) (0 MB) +// { 0xBAB6E168, 0xBAB6FFFC } // size 7832 (7 kB) (0 MB) +// { 0xBAB727F0, 0xBAB73FFC } // size 6160 (6 kB) (0 MB) +// { 0xBAB7518C, 0xBAB75FFC } // size 3700 (3 kB) (0 MB) +// { 0xBAB78410, 0xBAB79FFC } // size 7152 (6 kB) (0 MB) +// { 0xBAB7A604, 0xBAB7C1FC } // size 7164 (6 kB) (0 MB) +// { 0xBAB7E610, 0xBAB7FFFC } // size 6640 (6 kB) (0 MB) +// { 0xBAB80C6C, 0xBAB821FC } // size 5524 (5 kB) (0 MB) +// { 0xBAB84028, 0xBAB85FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAB88510, 0xBAB89FFC } // size 6896 (6 kB) (0 MB) +// { 0xBAB8A028, 0xBAB8BFFC } // size 8152 (7 kB) (0 MB) +// { 0xBAB8E7F0, 0xBAB8FFFC } // size 6160 (6 kB) (0 MB) +// { 0xBAB9085C, 0xBAB91FF8 } // size 6048 (5 kB) (0 MB) +// { 0xBAB92044, 0xBAB93FFC } // size 8124 (7 kB) (0 MB) +// { 0xBAB96D1C, 0xBAB97FF8 } // size 4832 (4 kB) (0 MB) +// { 0xBAB9804C, 0xBAB99FFC } // size 8116 (7 kB) (0 MB) +// { 0xBAB9AA1C, 0xBAB9BFF8 } // size 5600 (5 kB) (0 MB) +// { 0xBAB9C048, 0xBAB9DFFC } // size 8120 (7 kB) (0 MB) +// { 0xBAB9E1A0, 0xBAB9EFFC } // size 3680 (3 kB) (0 MB) +// { 0xBABBA6BC, 0xBABBBFF8 } // size 6464 (6 kB) (0 MB) +// { 0xBABBC048, 0xBABBDFFC } // size 8120 (7 kB) (0 MB) +// { 0xBABBE078, 0xBABBEFFC } // size 3976 (3 kB) (0 MB) +// { 0xBABC0C4C, 0xBACB9588 } // size 1018176 (994 kB) (0 MB) +// { 0xBACE89C8, 0xBACE9FF8 } // size 5684 (5 kB) (0 MB) +// { 0xBACEA050, 0xBACEBFFC } // size 8112 (7 kB) (0 MB) +// { 0xBACEC088, 0xBACEDFFC } // size 8056 (7 kB) (0 MB) +// { 0xBACEE330, 0xBACF01FC } // size 7888 (7 kB) (0 MB) +// { 0xBACF423C, 0xBACF5FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBACF6048, 0xBACF7FFC } // size 8120 (7 kB) (0 MB) +// { 0xBACF833C, 0xBACF9FFC } // size 7364 (7 kB) (0 MB) +// { 0xBACFA1E8, 0xBACFBFFC } // size 7704 (7 kB) (0 MB) +// { 0xBAD00028, 0xBAD01FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD06028, 0xBAD07FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD0C028, 0xBAD0DFFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD12028, 0xBAD12FFC } // size 4056 (3 kB) (0 MB) +// { 0xBAD19798, 0xBAD19FFC } // size 2152 (2 kB) (0 MB) +// { 0xBAD22028, 0xBAD23FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD28028, 0xBAD29FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD2E028, 0xBAD2FFFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD34028, 0xBAD35FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD3A028, 0xBAD3BFFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD4023C, 0xBAD41FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBAD42044, 0xBAD43FFC } // size 8124 (7 kB) (0 MB) +// { 0xBAD44100, 0xBAD45FFC } // size 7936 (7 kB) (0 MB) +// { 0xBAD46620, 0xBAD47FFC } // size 6624 (6 kB) (0 MB) +// { 0xBAD54800, 0xBAD55FFC } // size 6144 (6 kB) (0 MB) +// { 0xBAD56440, 0xBAD57FFC } // size 7104 (6 kB) (0 MB) +// { 0xBAD5841C, 0xBAD59FF8 } // size 7136 (6 kB) (0 MB) +// { 0xBAD5A048, 0xBAD5BFFC } // size 8120 (7 kB) (0 MB) +// { 0xBAD5C38C, 0xBAD5DFFC } // size 7284 (7 kB) (0 MB) +// { 0xBAD62028, 0xBAD63FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD68028, 0xBAD69FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD6E028, 0xBAD6F1FC } // size 4568 (4 kB) (0 MB) +// { 0xBAD6F2C0, 0xBAD6FFFC } // size 3392 (3 kB) (0 MB) +// { 0xBAD70028, 0xBAD71FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD76028, 0xBAD77FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD7C028, 0xBAD7DFFC } // size 8152 (7 kB) (0 MB) +// { 0xBAD81828, 0xBAD82074 } // size 2128 (2 kB) (0 MB) +// { 0xBAD8C028, 0xBAD8C908 } // size 2276 (2 kB) (0 MB) +// { 0xBAD8E028, 0xBAD8EFFC } // size 4056 (3 kB) (0 MB) +// { 0xBADA0028, 0xBADA1FFC } // size 8152 (7 kB) (0 MB) +// { 0xBADA6028, 0xBADA7FFC } // size 8152 (7 kB) (0 MB) +// { 0xBADAC028, 0xBADAE1FC } // size 8664 (8 kB) (0 MB) +// { 0xBADB0528, 0xBADB21FC } // size 7384 (7 kB) (0 MB) +// { 0xBADB6028, 0xBADB7FFC } // size 8152 (7 kB) (0 MB) +// { 0xBADBC23C, 0xBADBDFF8 } // size 7616 (7 kB) (0 MB) +// { 0xBADBE04C, 0xBADBFFFC } // size 8116 (7 kB) (0 MB) +// { 0xBADC019C, 0xBADC1FFC } // size 7780 (7 kB) (0 MB) +// { 0xBADC27B4, 0xBADC3FFC } // size 6220 (6 kB) (0 MB) +// { 0xBADC82F8, 0xBADC9FFC } // size 7432 (7 kB) (0 MB) +// { 0xBADD2F00, 0xBADD44FC } // size 5632 (5 kB) (0 MB) +// { 0xBADD4D80, 0xBADD5FFC } // size 4736 (4 kB) (0 MB) +// { 0xBADD6028, 0xBADD6FFC } // size 4056 (3 kB) (0 MB) +// { 0xBADE0028, 0xBADE1FFC } // size 8152 (7 kB) (0 MB) +// { 0xBADEA23C, 0xBADEBFF8 } // size 7616 (7 kB) (0 MB) +// { 0xBADEC048, 0xBADEDFFC } // size 8120 (7 kB) (0 MB) +// { 0xBADEE6FC, 0xBADEFFF8 } // size 6400 (6 kB) (0 MB) +// { 0xBADF0050, 0xBADF1FFC } // size 8112 (7 kB) (0 MB) +// { 0xBADFAF7C, 0xBADFBFF8 } // size 4224 (4 kB) (0 MB) +// { 0xBADFC048, 0xBADFDFFC } // size 8120 (7 kB) (0 MB) +// { 0xBADFE274, 0xBADFFFFC } // size 7564 (7 kB) (0 MB) +// { 0xBAE001B8, 0xBAE01FFC } // size 7752 (7 kB) (0 MB) +// { 0xBAE0E1F8, 0xBAE0FFFC } // size 7688 (7 kB) (0 MB) +// { 0xBAE347EC, 0xBAE35020 } // size 2104 (2 kB) (0 MB) +// { 0xBAE35F40, 0xBAE36FFC } // size 4288 (4 kB) (0 MB) +// { 0xBAE3723C, 0xBAE37FF8 } // size 3520 (3 kB) (0 MB) +// { 0xBAE3804C, 0xBAE39FFC } // size 8116 (7 kB) (0 MB) +// { 0xBAF04028, 0xBAF04864 } // size 2112 (2 kB) (0 MB) +// { 0xBAF18048, 0xBAF19FFC } // size 8120 (7 kB) (0 MB) +// { 0xBAF1E71C, 0xBAF1FFF8 } // size 6368 (6 kB) (0 MB) +// { 0xBAF20044, 0xBAF21FFC } // size 8124 (7 kB) (0 MB) +// { 0xBAF226E0, 0xBAF23FFC } // size 6432 (6 kB) (0 MB) +// { 0xBAF40798, 0xBAF42FFC } // size 10344 (10 kB) (0 MB) +// { 0xBAF43028, 0xBAF43FFC } // size 4056 (3 kB) (0 MB) +// { 0xBAF66FEC, 0xBAF697FC } // size 10260 (10 kB) (0 MB) +// { 0xBAF69828, 0xBAF6A224 } // size 2560 (2 kB) (0 MB) +// { 0xBAF6AF40, 0xBAF6B7FC } // size 2240 (2 kB) (0 MB) +// { 0xBAF7A028, 0xBAF7BFFC } // size 8152 (7 kB) (0 MB) +// { 0xBAF94E98, 0xBAF95908 } // size 2676 (2 kB) (0 MB) +// { 0xBAF96D44, 0xBAF977FC } // size 2748 (2 kB) (0 MB) +// { 0xBAFA4028, 0xBAFA4FFC } // size 4056 (3 kB) (0 MB) +// { 0xBAFA6800, 0xBAFA7338 } // size 2876 (2 kB) (0 MB) +// { 0xBAFBAE14, 0xBAFBBDFC } // size 4076 (3 kB) (0 MB) +// { 0xBAFBC904, 0xBAFBD7FC } // size 3836 (3 kB) (0 MB) +// { 0xBAFCA028, 0xBAFCBFFC } // size 8152 (7 kB) (0 MB) +// { 0xBAFD8028, 0xBAFD9FFC } // size 8152 (7 kB) (0 MB) +// { 0xBAFE6028, 0xBAFE6874 } // size 2128 (2 kB) (0 MB) +// { 0xBAFE8028, 0xBAFE8838 } // size 2068 (2 kB) (0 MB) +// { 0xBAFE9340, 0xBAFE9FFC } // size 3264 (3 kB) (0 MB) +// { 0xBAFEA028, 0xBAFEA908 } // size 2276 (2 kB) (0 MB) +// { 0xBAFEC028, 0xBAFEDFFC } // size 8152 (7 kB) (0 MB) +// { 0xBAFFA028, 0xBAFFBFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB008028, 0xBB009FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB016028, 0xBB017FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB024028, 0xBB025FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB028028, 0xBB029FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB037634, 0xBB037FFC } // size 2508 (2 kB) (0 MB) +// { 0xBB038028, 0xBB039FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB046028, 0xBB047FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB054028, 0xBB0548B8 } // size 2196 (2 kB) (0 MB) +// { 0xBB06A800, 0xBB06BBFC } // size 5120 (5 kB) (0 MB) +// { 0xBB06CB28, 0xBB06D7FC } // size 3288 (3 kB) (0 MB) +// { 0xBB090FEC, 0xBB091820 } // size 2104 (2 kB) (0 MB) +// { 0xBB092740, 0xBB0937FC } // size 4288 (4 kB) (0 MB) +// { 0xBB095724, 0xBB095FFC } // size 2268 (2 kB) (0 MB) +// { 0xBB096028, 0xBB097FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB0A423C, 0xBB0A5FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBB0A6044, 0xBB0A7FFC } // size 8124 (7 kB) (0 MB) +// { 0xBB0AAF3C, 0xBB0ABFF8 } // size 4288 (4 kB) (0 MB) +// { 0xBB0AC04C, 0xBB0ADFFC } // size 8116 (7 kB) (0 MB) +// { 0xBB0AE1A0, 0xBB0B01FC } // size 8288 (8 kB) (0 MB) +// { 0xBB0C490C, 0xBB0C5FFC } // size 5876 (5 kB) (0 MB) +// { 0xBB0C87F0, 0xBB0C9FFC } // size 6160 (6 kB) (0 MB) +// { 0xBB0CD23C, 0xBB0CDFF8 } // size 3520 (3 kB) (0 MB) +// { 0xBB0CE04C, 0xBB0CFFFC } // size 8116 (7 kB) (0 MB) +// { 0xBB0D0350, 0xBB0D1FFC } // size 7344 (7 kB) (0 MB) +// { 0xBB0D29E0, 0xBB0D33FC } // size 2592 (2 kB) (0 MB) +// { 0xBB0D4BE0, 0xBB0D55FC } // size 2592 (2 kB) (0 MB) +// { 0xBB0D69E0, 0xBB0D73FC } // size 2592 (2 kB) (0 MB) +// { 0xBB0D8BE0, 0xBB0D95FC } // size 2592 (2 kB) (0 MB) +// { 0xBB0DA9E0, 0xBB0DB3FC } // size 2592 (2 kB) (0 MB) +// { 0xBB0DCBE0, 0xBB0DD5FC } // size 2592 (2 kB) (0 MB) +// { 0xBB0DE9E0, 0xBB0DF3FC } // size 2592 (2 kB) (0 MB) +// { 0xBB0E0BE0, 0xBB0E15FC } // size 2592 (2 kB) (0 MB) +// { 0xBB0E3028, 0xBB0E3FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB164828, 0xBB1651FC } // size 2520 (2 kB) (0 MB) +// { 0xBB165B98, 0xBB1665FC } // size 2664 (2 kB) (0 MB) +// { 0xBB167998, 0xBB1683FC } // size 2664 (2 kB) (0 MB) +// { 0xBB17E028, 0xBB17EFFC } // size 4056 (3 kB) (0 MB) +// { 0xBB18123C, 0xBB181FF8 } // size 3520 (3 kB) (0 MB) +// { 0xBB18204C, 0xBB183FFC } // size 8116 (7 kB) (0 MB) +// { 0xBB18804C, 0xBB189FFC } // size 8116 (7 kB) (0 MB) +// { 0xBB18A278, 0xBB18BFFC } // size 7560 (7 kB) (0 MB) +// { 0xBB19F468, 0xBB1A03FC } // size 3992 (3 kB) (0 MB) +// { 0xBB1A1028, 0xBB1A1FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB1B2A3C, 0xBB1B3FF8 } // size 5568 (5 kB) (0 MB) +// { 0xBB1B404C, 0xBB1B5FFC } // size 8116 (7 kB) (0 MB) +// { 0xBB1B6354, 0xBB1B7FFC } // size 7340 (7 kB) (0 MB) +// { 0xBB1B89E0, 0xBB1B93FC } // size 2592 (2 kB) (0 MB) +// { 0xBB1BABE0, 0xBB1BB5FC } // size 2592 (2 kB) (0 MB) +// { 0xBB1BC9E0, 0xBB1BD3FC } // size 2592 (2 kB) (0 MB) +// { 0xBB1BEBE0, 0xBB1BF5FC } // size 2592 (2 kB) (0 MB) +// { 0xBB1C09E0, 0xBB1C13FC } // size 2592 (2 kB) (0 MB) +// { 0xBB1C2BE0, 0xBB1C35FC } // size 2592 (2 kB) (0 MB) +// { 0xBB1C49E0, 0xBB1C53FC } // size 2592 (2 kB) (0 MB) +// { 0xBB1C6BE0, 0xBB1C75FC } // size 2592 (2 kB) (0 MB) +// { 0xBB1C9028, 0xBB1C9FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB24A028, 0xBB24B1FC } // size 4568 (4 kB) (0 MB) +// { 0xBB24BB98, 0xBB24C5FC } // size 2664 (2 kB) (0 MB) +// { 0xBB24D998, 0xBB24E3FC } // size 2664 (2 kB) (0 MB) +// { 0xBB26723C, 0xBB267FF8 } // size 3520 (3 kB) (0 MB) +// { 0xBB268048, 0xBB269FFC } // size 8120 (7 kB) (0 MB) +// { 0xBB26A4E4, 0xBB26BFFC } // size 6940 (6 kB) (0 MB) +// { 0xBB293028, 0xBB293FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB29C7E8, 0xBB29DFFC } // size 6168 (6 kB) (0 MB) +// { 0xBB29E008, 0xBB29FFFC } // size 8184 (7 kB) (0 MB) +// { 0xBB2FC828, 0xBB2FDFFC } // size 6104 (5 kB) (0 MB) +// { 0xBB330828, 0xBB331FFC } // size 6104 (5 kB) (0 MB) +// { 0xBB33A6E8, 0xBB33C1FC } // size 6936 (6 kB) (0 MB) +// { 0xBB33C208, 0xBB33DFFC } // size 7672 (7 kB) (0 MB) +// { 0xBB35F828, 0xBB360064 } // size 2112 (2 kB) (0 MB) +// { 0xBB362028, 0xBB362864 } // size 2112 (2 kB) (0 MB) +// { 0xBB37E7E8, 0xBB3802FC } // size 6936 (6 kB) (0 MB) +// { 0xBB380308, 0xBB381FFC } // size 7416 (7 kB) (0 MB) +// { 0xBB382028, 0xBB383FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB390028, 0xBB3924FC } // size 9432 (9 kB) (0 MB) +// { 0xBB394694, 0xBB3953FC } // size 3436 (3 kB) (0 MB) +// { 0xBB39A028, 0xBB39BFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB3A47E8, 0xBB3A5FFC } // size 6168 (6 kB) (0 MB) +// { 0xBB3A6008, 0xBB3A7FFC } // size 8184 (7 kB) (0 MB) +// { 0xBB3A95FC, 0xBB3A9FF8 } // size 2560 (2 kB) (0 MB) +// { 0xBB3AA04C, 0xBB3ABFFC } // size 8116 (7 kB) (0 MB) +// { 0xBB3AC108, 0xBB3AE000 } // size 7932 (7 kB) (0 MB) +// { 0xBB3B2028, 0xBB3B42FC } // size 8920 (8 kB) (0 MB) +// { 0xBB3B5390, 0xBB3B5FFC } // size 3184 (3 kB) (0 MB) +// { 0xBB3B623C, 0xBB3B7FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBB3B804C, 0xBB3B9FFC } // size 8116 (7 kB) (0 MB) +// { 0xBB3BA33C, 0xBB3BBFFC } // size 7364 (7 kB) (0 MB) +// { 0xBB3BD028, 0xBB3BE828 } // size 6148 (6 kB) (0 MB) +// { 0xBB3C0000, 0xBB3C083C } // size 2112 (2 kB) (0 MB) +// { 0xBB3C0FC0, 0xBB3C17FC } // size 2112 (2 kB) (0 MB) +// { 0xBB3C2000, 0xBB3C2800 } // size 2052 (2 kB) (0 MB) +// { 0xBB3C3FFC, 0xBB3C48BC } // size 2244 (2 kB) (0 MB) +// { 0xBB3C4FA0, 0xBB3C67FC } // size 6240 (6 kB) (0 MB) +// { 0xBB3C6828, 0xBB3C71FC } // size 2520 (2 kB) (0 MB) +// { 0xBB3C72C0, 0xBB3C7FFC } // size 3392 (3 kB) (0 MB) +// { 0xBB3C8028, 0xBB3C9FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB3FC2B8, 0xBB3FDFFC } // size 7496 (7 kB) (0 MB) +// { 0xBB4076F0, 0xBB4081FC } // size 2832 (2 kB) (0 MB) +// { 0xBB4096F0, 0xBB409FFC } // size 2320 (2 kB) (0 MB) +// { 0xBB40A028, 0xBB40BFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB410028, 0xBB4121FC } // size 8664 (8 kB) (0 MB) +// { 0xBB414028, 0xBB4161FC } // size 8664 (8 kB) (0 MB) +// { 0xBB41A028, 0xBB41BFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB42023C, 0xBB421FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBB422050, 0xBB423FFC } // size 8112 (7 kB) (0 MB) +// { 0xBB49953C, 0xBB499FF8 } // size 2752 (2 kB) (0 MB) +// { 0xBB49A04C, 0xBB49BFFC } // size 8116 (7 kB) (0 MB) +// { 0xBB49C2FC, 0xBB49DFFC } // size 7428 (7 kB) (0 MB) +// { 0xBB4AA394, 0xBB4ABFFC } // size 7276 (7 kB) (0 MB) +// { 0xBB4B8028, 0xBB4B9FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB4C6A38, 0xBB4C7FFC } // size 5576 (5 kB) (0 MB) +// { 0xBB4D0F00, 0xBB4D24FC } // size 5632 (5 kB) (0 MB) +// { 0xBB4D2D80, 0xBB4D3FFC } // size 4736 (4 kB) (0 MB) +// { 0xBB4D4028, 0xBB4D4FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB4E004C, 0xBB4E1FFC } // size 8116 (7 kB) (0 MB) +// { 0xBB4E2424, 0xBB4E3FFC } // size 7132 (6 kB) (0 MB) +// { 0xBB4E6028, 0xBB4E6FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB4E9028, 0xBB4EA1FC } // size 4568 (4 kB) (0 MB) +// { 0xBB4EA2C0, 0xBB4EAFFC } // size 3392 (3 kB) (0 MB) +// { 0xBB4EB028, 0xBB4EBFFC } // size 4056 (3 kB) (0 MB) +// { 0xBB4F0028, 0xBB4F1FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB4F6028, 0xBB4F81FC } // size 8664 (8 kB) (0 MB) +// { 0xBB4FC028, 0xBB4FCFFC } // size 4056 (3 kB) (0 MB) +// { 0xBB4FF028, 0xBB4FFFFC } // size 4056 (3 kB) (0 MB) +// { 0xBB504028, 0xBB504FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB51ED24, 0xBB51FFFC } // size 4828 (4 kB) (0 MB) +// { 0xBB52499C, 0xBB525FFC } // size 5732 (5 kB) (0 MB) +// { 0xBB52A828, 0xBB52C1FC } // size 6616 (6 kB) (0 MB) +// { 0xBB530028, 0xBB531FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB536028, 0xBB537FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB53C23C, 0xBB53DFF8 } // size 7616 (7 kB) (0 MB) +// { 0xBB53E04C, 0xBB53FFFC } // size 8116 (7 kB) (0 MB) +// { 0xBB54029C, 0xBB541FFC } // size 7524 (7 kB) (0 MB) +// { 0xBB54420C, 0xBB544FFC } // size 3572 (3 kB) (0 MB) +// { 0xBB547210, 0xBB5481FC } // size 4080 (3 kB) (0 MB) +// { 0xBB5482C0, 0xBB548FFC } // size 3392 (3 kB) (0 MB) +// { 0xBB549028, 0xBB549FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB54E254, 0xBB54EFFC } // size 3500 (3 kB) (0 MB) +// { 0xBB551028, 0xBB551FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB55A028, 0xBB55BFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB560FD4, 0xBB561FFC } // size 4140 (4 kB) (0 MB) +// { 0xBB566028, 0xBB5681FC } // size 8664 (8 kB) (0 MB) +// { 0xBB56C028, 0xBB56DFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB57223C, 0xBB573FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBB57404C, 0xBB575FFC } // size 8116 (7 kB) (0 MB) +// { 0xBB576450, 0xBB577FFC } // size 7088 (6 kB) (0 MB) +// { 0xBB578308, 0xBB578FFC } // size 3320 (3 kB) (0 MB) +// { 0xBB57F378, 0xBB5801FC } // size 3720 (3 kB) (0 MB) +// { 0xBB5802C0, 0xBB580FFC } // size 3392 (3 kB) (0 MB) +// { 0xBB581028, 0xBB581FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB586028, 0xBB587FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB58C028, 0xBB58E1FC } // size 8664 (8 kB) (0 MB) +// { 0xBB592334, 0xBB592FFC } // size 3276 (3 kB) (0 MB) +// { 0xBB59533C, 0xBB595FFC } // size 3268 (3 kB) (0 MB) +// { 0xBB59A028, 0xBB59AFFC } // size 4056 (3 kB) (0 MB) +// { 0xBB5B8028, 0xBB5B9FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB5C36F0, 0xBB5C41FC } // size 2832 (2 kB) (0 MB) +// { 0xBB5C56F0, 0xBB5C5FFC } // size 2320 (2 kB) (0 MB) +// { 0xBB5C6028, 0xBB5C7FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB5CC528, 0xBB5CE1FC } // size 7384 (7 kB) (0 MB) +// { 0xBB5D2028, 0xBB5D3FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB5D8028, 0xBB5D9FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB5DE23C, 0xBB5DFFF8 } // size 7616 (7 kB) (0 MB) +// { 0xBB5E0054, 0xBB5E1FFC } // size 8108 (7 kB) (0 MB) +// { 0xBB5E2220, 0xBB5E3FFC } // size 7648 (7 kB) (0 MB) +// { 0xBB5E4390, 0xBB5E5FFC } // size 7280 (7 kB) (0 MB) +// { 0xBB5EA028, 0xBB5EA940 } // size 2332 (2 kB) (0 MB) +// { 0xBB630028, 0xBB6323FC } // size 9176 (8 kB) (0 MB) +// { 0xBB636050, 0xBB637FFC } // size 8112 (7 kB) (0 MB) +// { 0xBB63A828, 0xBB63B944 } // size 4384 (4 kB) (0 MB) +// { 0xBB64317C, 0xBB643FF8 } // size 3712 (3 kB) (0 MB) +// { 0xBB64404C, 0xBB645FFC } // size 8116 (7 kB) (0 MB) +// { 0xBB64644C, 0xBB647FFC } // size 7092 (6 kB) (0 MB) +// { 0xBB64A028, 0xBB64AFFC } // size 4056 (3 kB) (0 MB) +// { 0xBB64D028, 0xBB64E1FC } // size 4568 (4 kB) (0 MB) +// { 0xBB64E2C0, 0xBB64EFFC } // size 3392 (3 kB) (0 MB) +// { 0xBB64F028, 0xBB64FFFC } // size 4056 (3 kB) (0 MB) +// { 0xBB654028, 0xBB65683C } // size 10264 (10 kB) (0 MB) +// { 0xBB656FC0, 0xBB6577FC } // size 2112 (2 kB) (0 MB) +// { 0xBB658000, 0xBB658800 } // size 2052 (2 kB) (0 MB) +// { 0xBB658FFC, 0xBB6597FC } // size 2052 (2 kB) (0 MB) +// { 0xBB65A000, 0xBB65A93C } // size 2368 (2 kB) (0 MB) +// { 0xBB65AE98, 0xBB65D7FC } // size 10600 (10 kB) (0 MB) +// { 0xBB65EDE0, 0xBB65FFFC } // size 4640 (4 kB) (0 MB) +// { 0xBB664028, 0xBB6661FC } // size 8664 (8 kB) (0 MB) +// { 0xBB66A028, 0xBB66AFFC } // size 4056 (3 kB) (0 MB) +// { 0xBB66D640, 0xBB66DFFC } // size 2496 (2 kB) (0 MB) +// { 0xBB672028, 0xBB672FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB690028, 0xBB691FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB696834, 0xBB6981FC } // size 6604 (6 kB) (0 MB) +// { 0xBB69C028, 0xBB69DFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB6A233C, 0xBB6A3FFC } // size 7364 (7 kB) (0 MB) +// { 0xBB6A823C, 0xBB6A9FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBB6AA04C, 0xBB6ABFFC } // size 8116 (7 kB) (0 MB) +// { 0xBB6AC424, 0xBB6ADFFC } // size 7132 (6 kB) (0 MB) +// { 0xBB6B0378, 0xBB6B0FFC } // size 3208 (3 kB) (0 MB) +// { 0xBB6B3028, 0xBB6B41FC } // size 4568 (4 kB) (0 MB) +// { 0xBB6B42C0, 0xBB6B4FFC } // size 3392 (3 kB) (0 MB) +// { 0xBB6B5028, 0xBB6B5FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB6BA028, 0xBB6BBFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB6C0028, 0xBB6C21FC } // size 8664 (8 kB) (0 MB) +// { 0xBB6C6028, 0xBB6C6FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB6CAB1C, 0xBB6CBFFC } // size 5348 (5 kB) (0 MB) +// { 0xBB6D0028, 0xBB6D0FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB6EE028, 0xBB6EFFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB6F4528, 0xBB6F61FC } // size 7384 (7 kB) (0 MB) +// { 0xBB6FA028, 0xBB6FBFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB700640, 0xBB701FFC } // size 6592 (6 kB) (0 MB) +// { 0xBB70623C, 0xBB707FF8 } // size 7616 (7 kB) (0 MB) +// { 0xBB708048, 0xBB709FFC } // size 8120 (7 kB) (0 MB) +// { 0xBB70A38C, 0xBB70BFFC } // size 7284 (7 kB) (0 MB) +// { 0xBB710028, 0xBB711FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB716028, 0xBB717FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB71C028, 0xBB71D1FC } // size 4568 (4 kB) (0 MB) +// { 0xBB71D2C0, 0xBB71DFFC } // size 3392 (3 kB) (0 MB) +// { 0xBB71E028, 0xBB71FFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB724028, 0xBB725FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB72B828, 0xBB72C074 } // size 2128 (2 kB) (0 MB) +// { 0xBB736028, 0xBB736908 } // size 2276 (2 kB) (0 MB) +// { 0xBB738028, 0xBB738FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB741028, 0xBB741FFC } // size 4056 (3 kB) (0 MB) +// { 0xBB748A74, 0xBB749FFC } // size 5516 (5 kB) (0 MB) +// { 0xBB74E028, 0xBB74FFFC } // size 8152 (7 kB) (0 MB) +// { 0xBB754028, 0xBB755FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB75A028, 0xBB75C1FC } // size 8664 (8 kB) (0 MB) +// { 0xBB75E528, 0xBB7601FC } // size 7384 (7 kB) (0 MB) +// { 0xBB764028, 0xBB765FFC } // size 8152 (7 kB) (0 MB) +// { 0xBB76EF88, 0xBB77EEB4 } // size 65328 (63 kB) (0 MB) +// { 0xBB77F7E0, 0xBB8477E4 } // size 819208 (800 kB) (0 MB) +// { 0xBB858010, 0xBB859FF8 } // size 8172 (7 kB) (0 MB) +// { 0xBB86A010, 0xBB86BFF8 } // size 8172 (7 kB) (0 MB) +// { 0xBB87C00C, 0xBB936CB8 } // size 765104 (747 kB) (0 MB) +// { 0xBB936D8C, 0xBB94918C } // size 74756 (73 kB) (0 MB) +// { 0xBB94919C, 0xBB94B18C } // size 8180 (7 kB) (0 MB) +// { 0xBB952414, 0xBB952EA0 } // size 2704 (2 kB) (0 MB) +// { 0xBB95310C, 0xBB953FAC } // size 3748 (3 kB) (0 MB) +// { 0xBB954078, 0xBB954FBC } // size 3912 (3 kB) (0 MB) +// { 0xBB954FC8, 0xBB955FC4 } // size 4096 (4 kB) (0 MB) +// { 0xBB956010, 0xBB95700C } // size 4096 (4 kB) (0 MB) +// { 0xBB9570B8, 0xBB95801C } // size 3944 (3 kB) (0 MB) +// { 0xBB958030, 0xBB959028 } // size 4092 (3 kB) (0 MB) +// { 0xBB95904C, 0xBB95A030 } // size 4072 (3 kB) (0 MB) +// { 0xBB95A080, 0xBB95B054 } // size 4056 (3 kB) (0 MB) +// { 0xBB95B388, 0xBB95C35C } // size 4056 (3 kB) (0 MB) +// { 0xBB95C670, 0xBB95D670 } // size 4100 (4 kB) (0 MB) +// { 0xBB95D67C, 0xBB95E678 } // size 4096 (4 kB) (0 MB) +// { 0xBB95E694, 0xBB95F688 } // size 4088 (3 kB) (0 MB) +// { 0xBB95F698, 0xBB960694 } // size 4096 (4 kB) (0 MB) +// { 0xBB9606A0, 0xBB9616A0 } // size 4100 (4 kB) (0 MB) +// { 0xBB9616C4, 0xBB9626A8 } // size 4072 (3 kB) (0 MB) +// { 0xBB9626C0, 0xBB9636B8 } // size 4092 (3 kB) (0 MB) +// { 0xBB9636C4, 0xBB9646C4 } // size 4100 (4 kB) (0 MB) +// { 0xBB9646D0, 0xBB9656D0 } // size 4100 (4 kB) (0 MB) +// { 0xBB9656DC, 0xBB9666DC } // size 4100 (4 kB) (0 MB) +// { 0xBB9666E8, 0xBB9676E4 } // size 4096 (4 kB) (0 MB) +// { 0xBB967704, 0xBB968704 } // size 4100 (4 kB) (0 MB) +// { 0xBB968710, 0xBB96970C } // size 4096 (4 kB) (0 MB) +// { 0xBB969728, 0xBB96A71C } // size 4088 (3 kB) (0 MB) +// { 0xBB96A72C, 0xBB96B728 } // size 4096 (4 kB) (0 MB) +// { 0xBB96B734, 0xBB96C734 } // size 4100 (4 kB) (0 MB) +// { 0xBB96C758, 0xBB96D73C } // size 4072 (3 kB) (0 MB) +// { 0xBB96D754, 0xBB96E74C } // size 4092 (3 kB) (0 MB) +// { 0xBB96E758, 0xBB96F758 } // size 4100 (4 kB) (0 MB) +// { 0xBB96F764, 0xBB970764 } // size 4100 (4 kB) (0 MB) +// { 0xBB970770, 0xBB971770 } // size 4100 (4 kB) (0 MB) +// { 0xBB97177C, 0xBB972778 } // size 4096 (4 kB) (0 MB) +// { 0xBB97ED38, 0xBB97FFF8 } // size 4804 (4 kB) (0 MB) +// { 0xBB980000, 0xBB990028 } // size 65580 (64 kB) (0 MB) +// { 0xBB9936D0, 0xBB993FF8 } // size 2348 (2 kB) (0 MB) +// { 0xBB994000, 0xBB9A4028 } // size 65580 (64 kB) (0 MB) +// { 0xBB9A8D8C, 0xBB9B8CBC } // size 65332 (63 kB) (0 MB) +// { 0xBB9B9528, 0xBB9C90F4 } // size 64464 (62 kB) (0 MB) +// { 0xBB9C9F0C, 0xBB9CB1BC } // size 4788 (4 kB) (0 MB) +// { 0xBB9CB1E4, 0xBB9DB114 } // size 65332 (63 kB) (0 MB) +// { 0xBB9DD3EC, 0xBB9ED15C } // size 64884 (63 kB) (0 MB) +// { 0xBB9EDAFC, 0xBB9F1AFC } // size 16388 (16 kB) (0 MB) +// { 0xBB9F1B40, 0xBB9F5B3C } // size 16384 (16 kB) (0 MB) +// { 0xBB9FAF24, 0xBBA00B74 } // size 23636 (23 kB) (0 MB) +// { 0xBBA00BC0, 0xBBA0EBC0 } // size 57348 (56 kB) (0 MB) +// { 0xBBA0FE1C, 0xBBA1CBBC } // size 52644 (51 kB) (0 MB) +// { 0xBBA1D144, 0xBBA1DCF0 } // size 2992 (2 kB) (0 MB) +// { 0xBBA1DD40, 0xBBA1FCBC } // size 8064 (7 kB) (0 MB) +// { 0xBBA2057C, 0xBBA21C3C } // size 5828 (5 kB) (0 MB) +// { 0xBBA22438, 0xBBA251E8 } // size 11700 (11 kB) (0 MB) +// { 0xBBA25200, 0xBBA2C1FC } // size 28672 (28 kB) (0 MB) +// { 0xBBA2C7AC, 0xBBA331FC } // size 27220 (26 kB) (0 MB) +// { 0xBBA350C8, 0xBBA3678C } // size 5832 (5 kB) (0 MB) +// { 0xBBA367C0, 0xBBA3A17C } // size 14784 (14 kB) (0 MB) +// { 0xBBA3AB1C, 0xBBA3DB3C } // size 12324 (12 kB) (0 MB) +// { 0xBBA40640, 0xBBA4120C } // size 3024 (2 kB) (0 MB) +// { 0xBBA414AC, 0xBBA41DDC } // size 2356 (2 kB) (0 MB) +// { 0xBBA44700, 0xBBA456C0 } // size 4036 (3 kB) (0 MB) +// { 0xBBA45BFC, 0xBBA4667C } // size 2692 (2 kB) (0 MB) +// { 0xBBA48290, 0xBBA48A90 } // size 2052 (2 kB) (0 MB) +// { 0xBBA722AC, 0xBBA821DC } // size 65332 (63 kB) (0 MB) +// { 0xBBA84708, 0xBBA8A0E8 } // size 23012 (22 kB) (0 MB) +// { 0xBBA8A100, 0xBBA980FC } // size 57344 (56 kB) (0 MB) +// { 0xBBA99EBC, 0xBBAA60FC } // size 49732 (48 kB) (0 MB) +// { 0xBBAAC960, 0xBBAB0480 } // size 15140 (14 kB) (0 MB) +// { 0xBBAB04C0, 0xBBABE4BC } // size 57344 (56 kB) (0 MB) +// { 0xBBAC3B5C, 0xBBACC4BC } // size 35172 (34 kB) (0 MB) +// { 0xBBACFBFC, 0xBBAD0D0C } // size 4372 (4 kB) (0 MB) +// { 0xBBAD0DEC, 0xBBAD1E1C } // size 4148 (4 kB) (0 MB) +// { 0xBBAD4434, 0xBBAD6920 } // size 9456 (9 kB) (0 MB) +// { 0xBBAD6940, 0xBBAE025C } // size 39200 (38 kB) (0 MB) +// { 0xBBAE45BC, 0xBBAE9B7C } // size 21956 (21 kB) (0 MB) +// { 0xBBAED0CC, 0xBBAEF5B8 } // size 9456 (9 kB) (0 MB) +// { 0xBBAEF600, 0xBBAF8F1C } // size 39200 (38 kB) (0 MB) +// { 0xBBAFD27C, 0xBBB0283C } // size 21956 (21 kB) (0 MB) +// { 0xBBB051BC, 0xBBB05D8C } // size 3028 (2 kB) (0 MB) +// { 0xBBB05EDC, 0xBBB0695C } // size 2692 (2 kB) (0 MB) +// { 0xBBB08900, 0xBBB094CC } // size 3024 (2 kB) (0 MB) +// { 0xBBB095AC, 0xBBB0A09C } // size 2804 (2 kB) (0 MB) +// { 0xBBB0D884, 0xBBB0F224 } // size 6564 (6 kB) (0 MB) +// { 0xBBB0F240, 0xBBB1623C } // size 28672 (28 kB) (0 MB) +// { 0xBBB196BC, 0xBBB1D23C } // size 15236 (14 kB) (0 MB) +// { 0xBBB212B4, 0xBBB22894 } // size 5604 (5 kB) (0 MB) +// { 0xBBB228C0, 0xBBB298BC } // size 28672 (28 kB) (0 MB) +// { 0xBBB2D5FC, 0xBBB308BC } // size 12996 (12 kB) (0 MB) +// { 0xBBB364A4, 0xBBB382CC } // size 7724 (7 kB) (0 MB) +// { 0xBBB38300, 0xBBB40EFC } // size 35840 (35 kB) (0 MB) +// { 0xBBB454FC, 0xBBB49AFC } // size 17924 (17 kB) (0 MB) +// { 0xBBB4E6E0, 0xBBB515BC } // size 12000 (11 kB) (0 MB) +// { 0xBBB515D4, 0xBBB52570 } // size 4000 (3 kB) (0 MB) +// { 0xBBB54F5C, 0xBBB5653C } // size 5604 (5 kB) (0 MB) +// { 0xBBB56580, 0xBBB5D57C } // size 28672 (28 kB) (0 MB) +// { 0xBBB612BC, 0xBBB6457C } // size 12996 (12 kB) (0 MB) +// { 0xBBB6A580, 0xBBB6B68C } // size 4368 (4 kB) (0 MB) +// { 0xBBB6B76C, 0xBBB6C79C } // size 4148 (4 kB) (0 MB) +// { 0xBBB70F3C, 0xBBB7251C } // size 5604 (5 kB) (0 MB) +// { 0xBBB72540, 0xBBB7953C } // size 28672 (28 kB) (0 MB) +// { 0xBBB7D27C, 0xBBB8053C } // size 12996 (12 kB) (0 MB) +// { 0xBBB83680, 0xBBB8424C } // size 3024 (2 kB) (0 MB) +// { 0xBBB8439C, 0xBBB84E1C } // size 2692 (2 kB) (0 MB) +// { 0xBBB86DC0, 0xBBB8798C } // size 3024 (2 kB) (0 MB) +// { 0xBBB87A6C, 0xBBB8855C } // size 2804 (2 kB) (0 MB) +// { 0xBBB8FD08, 0xBBB916A8 } // size 6564 (6 kB) (0 MB) +// { 0xBBB916C0, 0xBBB986BC } // size 28672 (28 kB) (0 MB) +// { 0xBBB9BB3C, 0xBBB9F6BC } // size 15236 (14 kB) (0 MB) +// { 0xBBBA2280, 0xBBBA338C } // size 4368 (4 kB) (0 MB) +// { 0xBBBA377C, 0xBBBA449C } // size 3364 (3 kB) (0 MB) +// { 0xBBBAA238, 0xBBBABBD8 } // size 6564 (6 kB) (0 MB) +// { 0xBBBABC00, 0xBBBB2BFC } // size 28672 (28 kB) (0 MB) +// { 0xBBBB607C, 0xBBBB9BFC } // size 15236 (14 kB) (0 MB) +// { 0xBBBBD380, 0xBBBBDF4C } // size 3024 (2 kB) (0 MB) +// { 0xBBBC1230, 0xBBBC1D6C } // size 2880 (2 kB) (0 MB) +// { 0xBBBC1D7C, 0xBBBC4F5C } // size 12772 (12 kB) (0 MB) +// { 0xBBBC74F8, 0xBBBCA22C } // size 11576 (11 kB) (0 MB) +// { 0xBBBCA23C, 0xBBBD513C } // size 44804 (43 kB) (0 MB) +// { 0xBBBD973C, 0xBBBE003C } // size 26884 (26 kB) (0 MB) +// { 0xBBBE1658, 0xBBBE2194 } // size 2880 (2 kB) (0 MB) +// { 0xBBBE21C0, 0xBBBE539C } // size 12768 (12 kB) (0 MB) +// { 0xBBBE8000, 0xBBBE8FBC } // size 4032 (3 kB) (0 MB) +// { 0xBBBE909C, 0xBBBE9F7C } // size 3812 (3 kB) (0 MB) +// { 0xBBBEBE78, 0xBBBED818 } // size 6564 (6 kB) (0 MB) +// { 0xBBBED840, 0xBBBF483C } // size 28672 (28 kB) (0 MB) +// { 0xBBBF7CBC, 0xBBBFB83C } // size 15236 (14 kB) (0 MB) +// { 0xBBBFD970, 0xBBC00750 } // size 11748 (11 kB) (0 MB) +// { 0xBBC00780, 0xBBC0777C } // size 28672 (28 kB) (0 MB) +// { 0xBBC07CBC, 0xBBC0E77C } // size 27332 (26 kB) (0 MB) +// { 0xBBC10478, 0xBBC11E18 } // size 6564 (6 kB) (0 MB) +// { 0xBBC11E40, 0xBBC18E3C } // size 28672 (28 kB) (0 MB) +// { 0xBBC1C2BC, 0xBBC1FE3C } // size 15236 (14 kB) (0 MB) +// { 0xBBC227BC, 0xBBC2338C } // size 3028 (2 kB) (0 MB) +// { 0xBBC234DC, 0xBBC23F5C } // size 2692 (2 kB) (0 MB) +// { 0xBBC25F00, 0xBBC26ACC } // size 3024 (2 kB) (0 MB) +// { 0xBBC26BAC, 0xBBC2769C } // size 2804 (2 kB) (0 MB) +// { 0xBBC2B3EC, 0xBBC2D0C4 } // size 7388 (7 kB) (0 MB) +// { 0xBBC2D100, 0xBBC3543C } // size 33600 (32 kB) (0 MB) +// { 0xBBC3948C, 0xBBC3D77C } // size 17140 (16 kB) (0 MB) +// { 0xBBC3E9D4, 0xBBC3F510 } // size 2880 (2 kB) (0 MB) +// { 0xBBC3F540, 0xBBC4271C } // size 12768 (12 kB) (0 MB) +// { 0xBBC49440, 0xBBC4AA20 } // size 5604 (5 kB) (0 MB) +// { 0xBBC4AA40, 0xBBC51A3C } // size 28672 (28 kB) (0 MB) +// { 0xBBC5577C, 0xBBC58A3C } // size 12996 (12 kB) (0 MB) +// { 0xBBC59C94, 0xBBC5A7D0 } // size 2880 (2 kB) (0 MB) +// { 0xBBC5A800, 0xBBC5D9DC } // size 12768 (12 kB) (0 MB) +// { 0xBBC606C0, 0xBBC617CC } // size 4368 (4 kB) (0 MB) +// { 0xBBC618AC, 0xBBC628DC } // size 4148 (4 kB) (0 MB) +// { 0xBBC69AE4, 0xBBC6B364 } // size 6276 (6 kB) (0 MB) +// { 0xBBC6B380, 0xBBC7237C } // size 28672 (28 kB) (0 MB) +// { 0xBBC75A9C, 0xBBC7937C } // size 14564 (14 kB) (0 MB) +// { 0xBBC7C4C0, 0xBBC7D08C } // size 3024 (2 kB) (0 MB) +// { 0xBBC7D1DC, 0xBBC7DC5C } // size 2692 (2 kB) (0 MB) +// { 0xBBC7FC00, 0xBBC807CC } // size 3024 (2 kB) (0 MB) +// { 0xBBC808AC, 0xBBC8139C } // size 2804 (2 kB) (0 MB) +// { 0xBBC82144, 0xBBC82C80 } // size 2880 (2 kB) (0 MB) +// { 0xBBC82CC0, 0xBBC85E9C } // size 12768 (12 kB) (0 MB) +// { 0xBBC8E4C0, 0xBBC8F08C } // size 3024 (2 kB) (0 MB) +// { 0xBBC8F1DC, 0xBBC8FC5C } // size 2692 (2 kB) (0 MB) +// { 0xBBC91C00, 0xBBC927CC } // size 3024 (2 kB) (0 MB) +// { 0xBBC928AC, 0xBBC9339C } // size 2804 (2 kB) (0 MB) +// { 0xBBC94878, 0xBBC96C38 } // size 9156 (8 kB) (0 MB) +// { 0xBBC96C80, 0xBBC9DC7C } // size 28672 (28 kB) (0 MB) +// { 0xBBC9F95C, 0xBBCA4C7C } // size 21284 (20 kB) (0 MB) +// { 0xBBCA8FB0, 0xBBCABBB0 } // size 11268 (11 kB) (0 MB) +// { 0xBBCABC00, 0xBBCB2BFC } // size 28672 (28 kB) (0 MB) +// { 0xBBCB359C, 0xBBCB9BFC } // size 26212 (25 kB) (0 MB) +// { 0xBBCBBAF0, 0xBBCBE840 } // size 11604 (11 kB) (0 MB) +// { 0xBBCBE880, 0xBBCC587C } // size 28672 (28 kB) (0 MB) +// { 0xBBCC5F0C, 0xBBCCC87C } // size 26996 (26 kB) (0 MB) +// { 0xBBCCE0E8, 0xBBCD1078 } // size 12180 (11 kB) (0 MB) +// { 0xBBCD10C0, 0xBBCD80BC } // size 28672 (28 kB) (0 MB) +// { 0xBBCD820C, 0xBBCDF0BC } // size 28340 (27 kB) (0 MB) +// { 0xBBCE02FC, 0xBBCE307C } // size 11652 (11 kB) (0 MB) +// { 0xBBCE30C0, 0xBBCEA0BC } // size 28672 (28 kB) (0 MB) +// { 0xBBCEA6DC, 0xBBCF10BC } // size 27108 (26 kB) (0 MB) +// { 0xBBCF4750, 0xBBCF66F0 } // size 8100 (7 kB) (0 MB) +// { 0xBBCF6740, 0xBBCFD73C } // size 28672 (28 kB) (0 MB) +// { 0xBBCFFDBC, 0xBBD0473C } // size 18820 (18 kB) (0 MB) +// { 0xBBD07800, 0xBBD083CC } // size 3024 (2 kB) (0 MB) +// { 0xBBD0AF00, 0xBBD0BACC } // size 3024 (2 kB) (0 MB) +// { 0xBBD10FB8, 0xBBD11830 } // size 2172 (2 kB) (0 MB) +// { 0xBBD1205C, 0xBBD1301C } // size 4036 (3 kB) (0 MB) +// { 0xBBD137FC, 0xBBD147BC } // size 4036 (3 kB) (0 MB) +// { 0xBBD158AC, 0xBBD1640C } // size 2916 (2 kB) (0 MB) +// { 0xBBD169BC, 0xBBD1751C } // size 2916 (2 kB) (0 MB) +// { 0xBBD1EE0C, 0xBBD1FB9C } // size 3476 (3 kB) (0 MB) +// { 0xBBD2006C, 0xBBD20DFC } // size 3476 (3 kB) (0 MB) +// { 0xBBD2348C, 0xBBD2405C } // size 3028 (2 kB) (0 MB) +// { 0xBBD246EC, 0xBBD252BC } // size 3028 (2 kB) (0 MB) +// { 0xBBD2786C, 0xBBD2851C } // size 3252 (3 kB) (0 MB) +// { 0xBBD28ACC, 0xBBD2977C } // size 3252 (3 kB) (0 MB) +// { 0xBBD2BAFC, 0xBBD2C9DC } // size 3812 (3 kB) (0 MB) +// { 0xBBD2CD5C, 0xBBD2DC3C } // size 3812 (3 kB) (0 MB) +// { 0xBBD301EC, 0xBBD30E9C } // size 3252 (3 kB) (0 MB) +// { 0xBBD3144C, 0xBBD320FC } // size 3252 (3 kB) (0 MB) +// { 0xBBD346AC, 0xBBD3535C } // size 3252 (3 kB) (0 MB) +// { 0xBBD3590C, 0xBBD365BC } // size 3252 (3 kB) (0 MB) +// { 0xBBD38D9C, 0xBBD3981C } // size 2692 (2 kB) (0 MB) +// { 0xBBD39FFC, 0xBBD3AA7C } // size 2692 (2 kB) (0 MB) +// { 0xBBD3EB3C, 0xBBD402F0 } // size 6072 (5 kB) (0 MB) +// { 0xBBD412FC, 0xBBD4423C } // size 12100 (11 kB) (0 MB) +// { 0xBBD451FC, 0xBBD4813C } // size 12100 (11 kB) (0 MB) +// { 0xBBD496F4, 0xBBD4A7E0 } // size 4336 (4 kB) (0 MB) +// { 0xBBD4AD3C, 0xBBD4D1FC } // size 9412 (9 kB) (0 MB) +// { 0xBBD4D73C, 0xBBD4FBFC } // size 9412 (9 kB) (0 MB) +// { 0xBBD537BC, 0xBBD5955C } // size 23972 (23 kB) (0 MB) +// { 0xBBD5A1BC, 0xBBD6757C } // size 54212 (52 kB) (0 MB) +// { 0xBBD681BC, 0xBBD7557C } // size 54212 (52 kB) (0 MB) +// { 0xBBD769EC, 0xBBD77D4C } // size 4964 (4 kB) (0 MB) +// { 0xBBD78C5C, 0xBBD7B1FC } // size 9636 (9 kB) (0 MB) +// { 0xBBD7C0DC, 0xBBD7E67C } // size 9636 (9 kB) (0 MB) +// { 0xBBD8CF0C, 0xBBD8D9FC } // size 2804 (2 kB) (0 MB) +// { 0xBBD8DECC, 0xBBD8E9BC } // size 2804 (2 kB) (0 MB) +// { 0xBBD9388C, 0xBBD9437C } // size 2804 (2 kB) (0 MB) +// { 0xBBD9484C, 0xBBD9533C } // size 2804 (2 kB) (0 MB) +// { 0xBBD9993C, 0xBBD9A73C } // size 3588 (3 kB) (0 MB) +// { 0xBBD9D140, 0xBBD9E39C } // size 4704 (4 kB) (0 MB) +// { 0xBBD9E94C, 0xBBD9F5FC } // size 3252 (3 kB) (0 MB) +// { 0xBBDA3010, 0xBBDA3AFC } // size 2800 (2 kB) (0 MB) +// { 0xBBDA3B40, 0xBBDA581C } // size 7392 (7 kB) (0 MB) +// { 0xBBDA5F1C, 0xBBDA74FC } // size 5604 (5 kB) (0 MB) +// { 0xBBDAA08C, 0xBBDAB50C } // size 5252 (5 kB) (0 MB) +// { 0xBBDAB540, 0xBBDAE9BC } // size 13440 (13 kB) (0 MB) +// { 0xBBDAF35C, 0xBBDB1E3C } // size 10980 (10 kB) (0 MB) +// { 0xBBDB3180, 0xBBDB43DC } // size 4704 (4 kB) (0 MB) +// { 0xBBDB7BDC, 0xBBDB86C8 } // size 2800 (2 kB) (0 MB) +// { 0xBBDB8700, 0xBBDBA3DC } // size 7392 (7 kB) (0 MB) +// { 0xBBDBAADC, 0xBBDBC0BC } // size 5604 (5 kB) (0 MB) +// { 0xBBDBEA88, 0xBBDC0058 } // size 5588 (5 kB) (0 MB) +// { 0xBBDC0080, 0xBBDC34FC } // size 13440 (13 kB) (0 MB) +// { 0xBBDC387C, 0xBBDC697C } // size 12548 (12 kB) (0 MB) +// { 0xBBDC8374, 0xBBDC96A4 } // size 4916 (4 kB) (0 MB) +// { 0xBBDC96C0, 0xBBDCC5FC } // size 12096 (11 kB) (0 MB) +// { 0xBBDCCB3C, 0xBBDCF53C } // size 10756 (10 kB) (0 MB) +// { 0xBBDD50A4, 0xBBDDB054 } // size 24500 (23 kB) (0 MB) +// { 0xBBDDB080, 0xBBDE907C } // size 57344 (56 kB) (0 MB) +// { 0xBBDE931C, 0xBBDF707C } // size 56676 (55 kB) (0 MB) +// { 0xBBDFABC8, 0xBBDFC388 } // size 6084 (5 kB) (0 MB) +// { 0xBBDFC3C0, 0xBBE033BC } // size 28672 (28 kB) (0 MB) +// { 0xBBE06C9C, 0xBBE0A3BC } // size 14116 (13 kB) (0 MB) +// { 0xBBE0CC2C, 0xBBE0DF94 } // size 4972 (4 kB) (0 MB) +// { 0xBBE0DFC0, 0xBBE1311C } // size 20832 (20 kB) (0 MB) +// { 0xBBE1556C, 0xBBE1827C } // size 11540 (11 kB) (0 MB) +// { 0xBBE1B698, 0xBBE1D0C4 } // size 6704 (6 kB) (0 MB) +// { 0xBBE1D100, 0xBBE22F7C } // size 24192 (23 kB) (0 MB) +// { 0xBBE2512C, 0xBBE28DFC } // size 15572 (15 kB) (0 MB) +// { 0xBBE29650, 0xBBE2B6A8 } // size 8284 (8 kB) (0 MB) +// { 0xBBE2B6C0, 0xBBE3081C } // size 20832 (20 kB) (0 MB) +// { 0xBBE30E3C, 0xBBE3597C } // size 19268 (18 kB) (0 MB) +// { 0xBBE35DF8, 0xBBE38174 } // size 9088 (8 kB) (0 MB) +// { 0xBBE381C0, 0xBBE4247C } // size 41664 (40 kB) (0 MB) +// { 0xBBE46F68, 0xBBE494D8 } // size 9588 (9 kB) (0 MB) +// { 0xBBE49500, 0xBBE504FC } // size 28672 (28 kB) (0 MB) +// { 0xBBE51DEC, 0xBBE574FC } // size 22292 (21 kB) (0 MB) +// { 0xBBE5A278, 0xBBE5BE88 } // size 7188 (7 kB) (0 MB) +// { 0xBBE5BEC0, 0xBBE62EBC } // size 28672 (28 kB) (0 MB) +// { 0xBBE65D8C, 0xBBE69EBC } // size 16692 (16 kB) (0 MB) +// { 0xBBE6C780, 0xBBE6E37C } // size 7168 (7 kB) (0 MB) +// { 0xBBE72240, 0xBBE73E3C } // size 7168 (7 kB) (0 MB) +// { 0xBBE77640, 0xBBE7923C } // size 7168 (7 kB) (0 MB) +// { 0xBBE7CA40, 0xBBE7E63C } // size 7168 (7 kB) (0 MB) +// { 0xBBE85940, 0xBBE870E0 } // size 6052 (5 kB) (0 MB) +// { 0xBBE87A7C, 0xBBE8887C } // size 3588 (3 kB) (0 MB) +// { 0xBBE8AB90, 0xBBE8BA6C } // size 3808 (3 kB) (0 MB) +// { 0xBBE8BA7C, 0xBBE8E47C } // size 10756 (10 kB) (0 MB) +// { 0xBBE8F35C, 0xBBE90E7C } // size 6948 (6 kB) (0 MB) +// { 0xBBE96240, 0xBBE9703C } // size 3584 (3 kB) (0 MB) +// { 0xBBE9711C, 0xBBE97E3C } // size 3364 (3 kB) (0 MB) +// { 0xBBE9AA40, 0xBBE9B83C } // size 3584 (3 kB) (0 MB) +// { 0xBBE9B91C, 0xBBE9C63C } // size 3364 (3 kB) (0 MB) +// { 0xBBEA0280, 0xBBEA107C } // size 3584 (3 kB) (0 MB) +// { 0xBBEA131C, 0xBBEA1E7C } // size 2916 (2 kB) (0 MB) +// { 0xBBEA4A80, 0xBBEA587C } // size 3584 (3 kB) (0 MB) +// { 0xBBEA5A3C, 0xBBEA667C } // size 3140 (3 kB) (0 MB) +// { 0xBBEA7024, 0xBBEA7F00 } // size 3808 (3 kB) (0 MB) +// { 0xBBEA7F40, 0xBBEAA940 } // size 10756 (10 kB) (0 MB) +// { 0xBBEAB81C, 0xBBEAD33C } // size 6948 (6 kB) (0 MB) +// { 0xBBEAFCC0, 0xBBEB0ABC } // size 3584 (3 kB) (0 MB) +// { 0xBBEB0D5C, 0xBBEB18BC } // size 2916 (2 kB) (0 MB) +// { 0xBBEB44C0, 0xBBEB52BC } // size 3584 (3 kB) (0 MB) +// { 0xBBEB547C, 0xBBEB60BC } // size 3140 (3 kB) (0 MB) +// { 0xBBEB6854, 0xBBEB7940 } // size 4336 (4 kB) (0 MB) +// { 0xBBEB7980, 0xBBEBA380 } // size 10756 (10 kB) (0 MB) +// { 0xBBEBA8BC, 0xBBEBCD7C } // size 9412 (9 kB) (0 MB) +// { 0xBBEC4880, 0xBBEC6410 } // size 7060 (6 kB) (0 MB) +// { 0xBBEC73CC, 0xBBEC7F9C } // size 3028 (2 kB) (0 MB) +// { 0xBBED5740, 0xBBED653C } // size 3584 (3 kB) (0 MB) +// { 0xBBED661C, 0xBBED733C } // size 3364 (3 kB) (0 MB) +// { 0xBBED9F40, 0xBBEDAD3C } // size 3584 (3 kB) (0 MB) +// { 0xBBEDAE1C, 0xBBEDBB3C } // size 3364 (3 kB) (0 MB) +// { 0xBBEDE940, 0xBBEDF900 } // size 4036 (3 kB) (0 MB) +// { 0xBBEDFB9C, 0xBBEE08BC } // size 3364 (3 kB) (0 MB) +// { 0xBBEE4300, 0xBBEE50FC } // size 3584 (3 kB) (0 MB) +// { 0xBBEE52BC, 0xBBEE5EFC } // size 3140 (3 kB) (0 MB) +// { 0xBBEE8B00, 0xBBEE98FC } // size 3584 (3 kB) (0 MB) +// { 0xBBEE9B9C, 0xBBEEA6FC } // size 2916 (2 kB) (0 MB) +// { 0xBBEEB440, 0xBBEEC400 } // size 4036 (3 kB) (0 MB) +// { 0xBBEEC69C, 0xBBEED3BC } // size 3364 (3 kB) (0 MB) +// { 0xBBEEFAB4, 0xBBEF0BA4 } // size 4340 (4 kB) (0 MB) +// { 0xBBEF0BC0, 0xBBEF385C } // size 11424 (11 kB) (0 MB) +// { 0xBBEF42DC, 0xBBEF64FC } // size 8740 (8 kB) (0 MB) +// { 0xBBEF71C0, 0xBBEF817C } // size 4032 (3 kB) (0 MB) +// { 0xBBEF83AC, 0xBBEF913C } // size 3476 (3 kB) (0 MB) +// { 0xBBF03080, 0xBBF04C7C } // size 7168 (7 kB) (0 MB) +// { 0xBBF08B40, 0xBBF0A73C } // size 7168 (7 kB) (0 MB) +// { 0xBBF0DF40, 0xBBF0FB3C } // size 7168 (7 kB) (0 MB) +// { 0xBBF13340, 0xBBF14F3C } // size 7168 (7 kB) (0 MB) +// { 0xBBF17CB0, 0xBBF195F0 } // size 6468 (6 kB) (0 MB) +// { 0xBBF19640, 0xBBF2063C } // size 28672 (28 kB) (0 MB) +// { 0xBBF23B9C, 0xBBF2763C } // size 15012 (14 kB) (0 MB) +// { 0xBBF28CC0, 0xBBF2BAA0 } // size 11748 (11 kB) (0 MB) +// { 0xBBF2BAC0, 0xBBF32ABC } // size 28672 (28 kB) (0 MB) +// { 0xBBF32FFC, 0xBBF39ABC } // size 27332 (26 kB) (0 MB) +// { 0xBC9AA154, 0xBC9ABAB8 } // size 6504 (6 kB) (0 MB) +// { 0xBC9AC81C, 0xBC9AFC9C } // size 13444 (13 kB) (0 MB) +// { 0xBC9B09BC, 0xBC9B3E3C } // size 13444 (13 kB) (0 MB) +// { 0xBC9B6E44, 0xBC9B87A8 } // size 6504 (6 kB) (0 MB) +// { 0xBC9B94DC, 0xBC9BC95C } // size 13444 (13 kB) (0 MB) +// { 0xBC9BD67C, 0xBC9C0AFC } // size 13444 (13 kB) (0 MB) +// { 0xBC9C3C98, 0xBC9C871C } // size 19080 (18 kB) (0 MB) +// { 0xBCA0F4A4, 0xBCA35ABC } // size 157212 (153 kB) (0 MB) +// { 0xBCA35AF0, 0xBCA36764 } // size 3192 (3 kB) (0 MB) +// { 0xBCA36774, 0xBCA4662C } // size 65212 (63 kB) (0 MB) +// { 0xBCA48AB0, 0xBCAE0FFC } // size 623952 (609 kB) (0 MB) +// { 0xBCAE7878, 0xBD207DB4 } // size 7472448 (7297 kB) (7 MB) +// { 0xBD3B966C, 0xBD8943C0 } // size 5090648 (4971 kB) (4 MB) +// { 0xBD894770, 0xBD8A037C } // size 48144 (47 kB) (0 MB) +// { 0xBD8A1F88, 0xBD8A2D7C } // size 3576 (3 kB) (0 MB) +// { 0xBD8A63F4, 0xBD8AD3C4 } // size 28628 (27 kB) (0 MB) +// { 0xBD8AD3D8, 0xBDFFFFFC } // size 7679016 (7499 kB) (7 MB) +// { 0xBE2F02A0, 0xBE2F217C } // size 7904 (7 kB) (0 MB) +// { 0xBE320A64, 0xBE323574 } // size 11028 (10 kB) (0 MB) +// { 0xBE324220, 0xBE32B73C } // size 29984 (29 kB) (0 MB) +// { 0xBE34A2A0, 0xBE34C0FC } // size 7776 (7 kB) (0 MB) +// { 0xBE358B80, 0xBE35CCFC } // size 16768 (16 kB) (0 MB) +// { 0xBE363020, 0xBE36407C } // size 4192 (4 kB) (0 MB) +// { 0xBE37EB98, 0xBE38172C } // size 11160 (10 kB) (0 MB) +// { 0xBE382600, 0xBE3AC4BC } // size 171712 (167 kB) (0 MB) +// { 0xBE3BF8D0, 0xBE3E24FC } // size 142384 (139 kB) (0 MB) +// { 0xBE3EB3B0, 0xBE3EE394 } // size 12264 (11 kB) (0 MB) +// { 0xBE3EFD40, 0xBE410CBC } // size 135040 (131 kB) (0 MB) +// { 0xBE41EA50, 0xBE4474FC } // size 166576 (162 kB) (0 MB) +// { 0xBE46ADC0, 0xBE46E57C } // size 14272 (13 kB) (0 MB) +// { 0xBE473BE0, 0xBE47543C } // size 6240 (6 kB) (0 MB) +// { 0xBE47EFD0, 0xBE4884BC } // size 38128 (37 kB) (0 MB) +// { 0xBE49167C, 0xBE493C2C } // size 9652 (9 kB) (0 MB) +// { 0xBE495690, 0xBE49C57C } // size 28400 (27 kB) (0 MB) +// { 0xBE4A58B0, 0xBE4B49FC } // size 61776 (60 kB) (0 MB) +// { 0xBE4DC17C, 0xBE4DF94C } // size 14292 (13 kB) (0 MB) +// { 0xBE4E0AD0, 0xBE5000BC } // size 128496 (125 kB) (0 MB) +// { 0xBE50A1A0, 0xBE53327C } // size 168160 (164 kB) (0 MB) +// { 0xBE536660, 0xBE5584FC } // size 138912 (135 kB) (0 MB) +// { 0xBE58316C, 0xBE58659C } // size 13364 (13 kB) (0 MB) +// { 0xBE586AD0, 0xBE5B86BC } // size 203760 (198 kB) (0 MB) +// { 0xBE5CFF70, 0xBE5D7FBC } // size 32848 (32 kB) (0 MB) +// { 0xBE5DE9D8, 0xBE5E0F8C } // size 9656 (9 kB) (0 MB) +// { 0xBE5E12B0, 0xBE60507C } // size 146896 (143 kB) (0 MB) +// { 0xBE605CBC, 0xBFF849BC } // size 26733828 (26107 kB) (25 MB) +// { 0xBFF869BC, 0xBFF8CA3C } // size 24708 (24 kB) (0 MB) +// { 0xBFF8DA24, 0xBFF8E600 } // size 3040 (2 kB) (0 MB) + +// { 0xC1000000, 0xC1E1FFFC } // size 14811136 (14464 kB) (14 MB) +// { 0xC1EB1380, 0xC1EB4B3C } // size 14272 (13 kB) (0 MB) +// { 0xC1FEFE7C, 0xC1FF5EFC } // size 24708 (24 kB) (0 MB) +// { 0xC1FF6E84, 0xC1FF7AC0 } // size 3136 (3 kB) (0 MB) +// { 0xC2086268, 0xC2090B3C } // size 43224 (42 kB) (0 MB) +// { 0xC20B15D8, 0xC20B97FC } // size 33320 (32 kB) (0 MB) +// { 0xC20BE2A0, 0xC20BED7C } // size 2784 (2 kB) (0 MB) +// { 0xC20CCE7C, 0xC20CEEBC } // size 8260 (8 kB) (0 MB) +// { 0xC20E5888, 0xC20E7E4C } // size 9672 (9 kB) (0 MB) +// { 0xC20E7E58, 0xC20EC73C } // size 18664 (18 kB) (0 MB) +// { 0xC20F212C, 0xC210AF3C } // size 101908 (99 kB) (0 MB) +// { 0xC2119BAC, 0xC211EEFC } // size 21332 (20 kB) (0 MB) +// { 0xC2122F30, 0xC212787C } // size 18768 (18 kB) (0 MB) +// { 0xC2131054, 0xC213C63C } // size 46572 (45 kB) (0 MB) +// { 0xC214A474, 0xC214DC3C } // size 14284 (13 kB) (0 MB) +// { 0xC21ABCA0, 0xC21AE904 } // size 11368 (11 kB) (0 MB) +// { 0xC21AE910, 0xC21C207C } // size 79728 (77 kB) (0 MB) +// { 0xC21DBB50, 0xC21DCFFC } // size 5296 (5 kB) (0 MB) +// { 0xC21DD064, 0xC21E287C } // size 22556 (22 kB) (0 MB) +// { 0xC301308C, 0xC301F0BC } // size 49204 (48 kB) (0 MB) +// { 0xC301F0C4, 0xC3023014 } // size 16212 (15 kB) (0 MB) +// { 0xC30230C4, 0xC3027014 } // size 16212 (15 kB) (0 MB) +// { 0xC30270C4, 0xC302B014 } // size 16212 (15 kB) (0 MB) +// { 0xC302B0C4, 0xC302F014 } // size 16212 (15 kB) (0 MB) +// { 0xC302F0C4, 0xC3033014 } // size 16212 (15 kB) (0 MB) +// { 0xC30330C4, 0xC3037014 } // size 16212 (15 kB) (0 MB) +// { 0xC30398E8, 0xC303A2B4 } // size 2512 (2 kB) (0 MB) +// { 0xC303B068, 0xC303BC68 } // size 3076 (3 kB) (0 MB) +// { 0xC3043150, 0xC3043C64 } // size 2840 (2 kB) (0 MB) +// { 0xC3045AF0, 0xC304E09C } // size 34224 (33 kB) (0 MB) +// { 0xC304E3D4, 0xC3050B24 } // size 10068 (9 kB) (0 MB) +// { 0xC3051940, 0xC30528D4 } // size 3992 (3 kB) (0 MB) +// { 0xC3052930, 0xC30538DC } // size 4016 (3 kB) (0 MB) +// { 0xC3053934, 0xC30548D4 } // size 4004 (3 kB) (0 MB) +// { 0xC30566EC, 0xC3058664 } // size 8060 (7 kB) (0 MB) +// { 0xC30586EC, 0xC305A664 } // size 8060 (7 kB) (0 MB) +// { 0xC305A6EC, 0xC305C664 } // size 8060 (7 kB) (0 MB) +// { 0xC305CB90, 0xC305DC78 } // size 4332 (4 kB) (0 MB) +// { 0xC305E40C, 0xC305ECF0 } // size 2280 (2 kB) (0 MB) +// { 0xC3060044, 0xC3060F8C } // size 3916 (3 kB) (0 MB) +// { 0xC3061040, 0xC306203C } // size 4096 (4 kB) (0 MB) +// { 0xC3062DB8, 0xC306EE3C } // size 49288 (48 kB) (0 MB) +// { 0xC306EE84, 0xC3070DC4 } // size 8004 (7 kB) (0 MB) +// { 0xC3070E84, 0xC3072DC4 } // size 8004 (7 kB) (0 MB) +// { 0xC3072E84, 0xC3074DC4 } // size 8004 (7 kB) (0 MB) +// { 0xC30761F0, 0xC307745C } // size 4720 (4 kB) (0 MB) +// { 0xC307F28C, 0xC307FAC0 } // size 2104 (2 kB) (0 MB) +// { 0xC307FAF8, 0xC3081350 } // size 6236 (6 kB) (0 MB) +// { 0xC3081358, 0xC30822A4 } // size 3920 (3 kB) (0 MB) +// { 0xC3082358, 0xC30832A4 } // size 3920 (3 kB) (0 MB) +// { 0xC3083358, 0xC30842A4 } // size 3920 (3 kB) (0 MB) +// { 0xC30858E4, 0xC30878C4 } // size 8164 (7 kB) (0 MB) +// { 0xC30878F8, 0xC308B8C4 } // size 16336 (15 kB) (0 MB) +// { 0xC308C240, 0xC3097744 } // size 46344 (45 kB) (0 MB) +// { 0xC3097930, 0xC30A37E4 } // size 48824 (47 kB) (0 MB) +// { 0xC30A3818, 0xC30B16BC } // size 57000 (55 kB) (0 MB) +// { 0xC30B16C4, 0xC30B262C } // size 3948 (3 kB) (0 MB) +// { 0xC30B26C0, 0xC30B3B3C } // size 5248 (5 kB) (0 MB) +// { 0xC30B4204, 0xC30B5900 } // size 5888 (5 kB) (0 MB) +// { 0xC30B5934, 0xC30B713C } // size 6156 (6 kB) (0 MB) +// { 0xC30B7190, 0xC30BC074 } // size 20200 (19 kB) (0 MB) +// { 0xC30BC138, 0xC30BD13C } // size 4104 (4 kB) (0 MB) +// { 0xC30BD144, 0xC30C1084 } // size 16196 (15 kB) (0 MB) +// { 0xC30C1144, 0xC30C5084 } // size 16196 (15 kB) (0 MB) +// { 0xC30C5144, 0xC30C9084 } // size 16196 (15 kB) (0 MB) +// { 0xC30CAE10, 0xC30CB788 } // size 2428 (2 kB) (0 MB) +// { 0xC30CC780, 0xC30CCFA4 } // size 2088 (2 kB) (0 MB) +// { 0xC30CDEC0, 0xC30CE6E4 } // size 2088 (2 kB) (0 MB) +// { 0xC30CF600, 0xC30D707C } // size 31360 (30 kB) (0 MB) +// { 0xC30D719C, 0xC30DC3FC } // size 21092 (20 kB) (0 MB) +// { 0xC30DC61C, 0xC318037C } // size 671076 (655 kB) (0 MB) +// { 0xC31804E0, 0xC31C037C } // size 261792 (255 kB) (0 MB) +// { 0xC31C07C4, 0xC321063C } // size 327292 (319 kB) (0 MB) +// { 0xC3227980, 0xC322AF34 } // size 13752 (13 kB) (0 MB) +// { 0xC322C600, 0xC3231D00 } // size 22276 (21 kB) (0 MB) +// { 0xC32327E4, 0xC3233060 } // size 2176 (2 kB) (0 MB) +// { 0xC3234080, 0xC324B340 } // size 94916 (92 kB) (0 MB) +// { 0xC324D8C0, 0xC328D880 } // size 262084 (255 kB) (0 MB) +// { 0xC329D234, 0xC32CA42C } // size 184828 (180 kB) (0 MB) +// { 0xC32CA434, 0xC32CDF68 } // size 15160 (14 kB) (0 MB) +// { 0xC32CE26C, 0xC32CF4FC } // size 4756 (4 kB) (0 MB) +// { 0xC32CF504, 0xC32D0790 } // size 4752 (4 kB) (0 MB) +// { 0xC32D34BC, 0xC32D4A3C } // size 5508 (5 kB) (0 MB) +// { 0xC32EB100, 0xC32EBC98 } // size 2972 (2 kB) (0 MB) +// { 0xC32ED180, 0xC32EFFC0 } // size 11844 (11 kB) (0 MB) +// { 0xC32F4540, 0xC32FA080 } // size 23364 (22 kB) (0 MB) +// { 0xC3302A6C, 0xC33045C0 } // size 7000 (6 kB) (0 MB) +// { 0xC331AE90, 0xC331C33C } // size 5296 (5 kB) (0 MB) +// { 0xC332B500, 0xC3340F88 } // size 88716 (86 kB) (0 MB) +// { 0xC334DB34, 0xC334EB40 } // size 4112 (4 kB) (0 MB) +// { 0xC3354284, 0xC3356354 } // size 8404 (8 kB) (0 MB) +// { 0xC33573C8, 0xC33583FC } // size 4152 (4 kB) (0 MB) +// { 0xC3358A80, 0xC335A484 } // size 6664 (6 kB) (0 MB) +// { 0xC335A4C0, 0xC35021FC } // size 1736000 (1695 kB) (1 MB) +// { 0xC350C1D4, 0xC39182CC } // size 4243708 (4144 kB) (4 MB) +// { 0xC3919AC4, 0xC39298C4 } // size 65028 (63 kB) (0 MB) +// { 0xC3929AC4, 0xC3939534 } // size 64116 (62 kB) (0 MB) +// { 0xC3939AC4, 0xC39498C4 } // size 65028 (63 kB) (0 MB) +// { 0xC3949AC0, 0xC394CFFC } // size 13632 (13 kB) (0 MB) +// { 0xC394EEB0, 0xC3954988 } // size 23260 (22 kB) (0 MB) +// { 0xC3955000, 0xC3955FFC } // size 4096 (4 kB) (0 MB) +// { 0xC395667C, 0xC395778C } // size 4372 (4 kB) (0 MB) +// { 0xC39577C0, 0xC3975C80 } // size 124100 (121 kB) (0 MB) +// { 0xC39769C8, 0xC398D320 } // size 92508 (90 kB) (0 MB) +// { 0xC398DAF8, 0xC399DC08 } // size 65812 (64 kB) (0 MB) +// { 0xC399DC78, 0xC39ABF80 } // size 58124 (56 kB) (0 MB) +// { 0xC39B1124, 0xC39C8200 } // size 94432 (92 kB) (0 MB) +// { 0xC39C966C, 0xC39CB580 } // size 7960 (7 kB) (0 MB) +// { 0xC39CC178, 0xC39D5580 } // size 37900 (37 kB) (0 MB) +// { 0xC39D5E20, 0xC39E5F34 } // size 65816 (64 kB) (0 MB) +// { 0xC39E5F84, 0xC39F6A80 } // size 68352 (66 kB) (0 MB) +// { 0xC39FBC54, 0xC3A14080 } // size 99376 (97 kB) (0 MB) +// { 0xC3A14094, 0xC3EBFFFC } // size 4898668 (4783 kB) (4 MB) +// { 0xC3F028E0, 0xC3F2477C } // size 138912 (135 kB) (0 MB) +// { 0xC3F37B10, 0xC3F5A73C } // size 142384 (139 kB) (0 MB) +// { 0xC3F69350, 0xC3F91DFC } // size 166576 (162 kB) (0 MB) +// { 0xC3F927DC, 0xC3FEE3BC } // size 375780 (366 kB) (0 MB) +// { 0xC3FF23B4, 0xC3FF643C } // size 16524 (16 kB) (0 MB) +// { 0xC3FF7274, 0xC3FF8000 } // size 3472 (3 kB) (0 MB) +// { 0xC3FFFFD4, 0xC8FFFFFC } // size 83886124 (81920 kB) (80 MB) + {0, 0} +}; + +static const memory_values_t mem_vals_532[] = +{ + // TODO: Check which of those areas are usable +// {0xB8000000 + 0x000DCC9C, 0xB8000000 + 0x00174F80}, // 608 kB +// {0xB8000000 + 0x00180B60, 0xB8000000 + 0x001C0A00}, // 255 kB +// {0xB8000000 + 0x001ECE9C, 0xB8000000 + 0x00208CC0}, // 111 kB +// {0xB8000000 + 0x00234180, 0xB8000000 + 0x0024B444}, // 92 kB +// {0xB8000000 + 0x0024D8C0, 0xB8000000 + 0x0028D884}, // 255 kB +// {0xB8000000 + 0x003A745C, 0xB8000000 + 0x004D2B68}, // 1197 kB +// {0xB8000000 + 0x004D77B0, 0xB8000000 + 0x00502200}, // 170 kB +// {0xB8000000 + 0x005B3A88, 0xB8000000 + 0x005C6870}, // 75 kB +// {0xB8000000 + 0x0061F3E4, 0xB8000000 + 0x00632B04}, // 77 kB +// {0xB8000000 + 0x00639790, 0xB8000000 + 0x00649BC4}, // 65 kB +// {0xB8000000 + 0x00691490, 0xB8000000 + 0x006B3CA4}, // 138 kB +// {0xB8000000 + 0x006D7BCC, 0xB8000000 + 0x006EEB84}, // 91 kB +// {0xB8000000 + 0x00704E44, 0xB8000000 + 0x0071E3C4}, // 101 kB +// {0xB8000000 + 0x0073B684, 0xB8000000 + 0x0074C184}, // 66 kB +// {0xB8000000 + 0x00751354, 0xB8000000 + 0x00769784}, // 97 kB +// {0xB8000000 + 0x008627DC, 0xB8000000 + 0x00872904}, // 64 kB +// {0xB8000000 + 0x008C1E98, 0xB8000000 + 0x008EB0A0}, // 164 kB +// {0xB8000000 + 0x008EEC30, 0xB8000000 + 0x00B06E98}, // 2144 kB +// {0xB8000000 + 0x00B06EC4, 0xB8000000 + 0x00B930C4}, // 560 kB +// {0xB8000000 + 0x00BA1868, 0xB8000000 + 0x00BC22A4}, // 130 kB +// {0xB8000000 + 0x00BC48F8, 0xB8000000 + 0x00BDEC84}, // 104 kB +// {0xB8000000 + 0x00BE3DC0, 0xB8000000 + 0x00C02284}, // 121 kB +// {0xB8000000 + 0x00C02FC8, 0xB8000000 + 0x00C19924}, // 90 kB +// {0xB8000000 + 0x00C2D35C, 0xB8000000 + 0x00C3DDC4}, // 66 kB +// {0xB8000000 + 0x00C48654, 0xB8000000 + 0x00C6E2E4}, // 151 kB +// {0xB8000000 + 0x00D04E04, 0xB8000000 + 0x00D36938}, // 198 kB +// {0xB8000000 + 0x00DC88AC, 0xB8000000 + 0x00E14288}, // 302 kB +// {0xB8000000 + 0x00E21ED4, 0xB8000000 + 0x00EC8298}, // 664 kB +// {0xB8000000 + 0x00EDDC7C, 0xB8000000 + 0x00F7C2A8}, // 633 kB +// {0xB8000000 + 0x00F89EF4, 0xB8000000 + 0x010302B8}, // 664 kB +// {0xB8000000 + 0x01030800, 0xB8000000 + 0x013F69A0}, // 3864 kB +// {0xB8000000 + 0x016CE000, 0xB8000000 + 0x016E0AA0}, // 74 kB +// {0xB8000000 + 0x0170200C, 0xB8000000 + 0x018B9C58}, // 1759 kB +// {0xB8000000 + 0x01F17658, 0xB8000000 + 0x01F6765C}, // 320 kB +// {0xB8000000 + 0x01F6779C, 0xB8000000 + 0x01FB77A0}, // 320 kB +// {0xB8000000 + 0x01FB78E0, 0xB8000000 + 0x020078E4}, // 320 kB +// {0xB8000000 + 0x02007A24, 0xB8000000 + 0x02057A28}, // 320 kB +// {0xB8000000 + 0x02057B68, 0xB8000000 + 0x021B957C}, // 1414 kB +// {0xB8000000 + 0x02891528, 0xB8000000 + 0x028C8A28}, // 221 kB +// {0xB8000000 + 0x02BBCC4C, 0xB8000000 + 0x02CB958C}, // 1010 kB +// {0xB8000000 + 0x0378D45C, 0xB8000000 + 0x03855464}, // 800 kB +// {0xB8000000 + 0x0387800C, 0xB8000000 + 0x03944938}, // 818 kB +// {0xB8000000 + 0x03944A08, 0xB8000000 + 0x03956E0C}, // 73 kB +// {0xB8000000 + 0x04A944A4, 0xB8000000 + 0x04ABAAC0}, // 153 kB +// {0xB8000000 + 0x04ADE370, 0xB8000000 + 0x0520EAB8}, // 7361 kB // ok +// {0xB8000000 + 0x053B966C, 0xB8000000 + 0x058943C4}, // 4971 kB // ok +// {0xB8000000 + 0x058AD3D8, 0xB8000000 + 0x06000000}, // 7499 kB +// {0xB8000000 + 0x0638D320, 0xB8000000 + 0x063B0280}, // 139 kB +// {0xB8000000 + 0x063C39E0, 0xB8000000 + 0x063E62C0}, // 138 kB +// {0xB8000000 + 0x063F52A0, 0xB8000000 + 0x06414A80}, // 125 kB +// {0xB8000000 + 0x06422810, 0xB8000000 + 0x0644B2C0}, // 162 kB +// {0xB8000000 + 0x064E48D0, 0xB8000000 + 0x06503EC0}, // 125 kB +// {0xB8000000 + 0x0650E360, 0xB8000000 + 0x06537080}, // 163 kB +// {0xB8000000 + 0x0653A460, 0xB8000000 + 0x0655C300}, // 135 kB +// {0xB8000000 + 0x0658AA40, 0xB8000000 + 0x065BC4C0}, // 198 kB // ok +// {0xB8000000 + 0x065E51A0, 0xB8000000 + 0x06608E80}, // 143 kB // ok +// {0xB8000000 + 0x06609ABC, 0xB8000000 + 0x07F82C00}, // 26084 kB // ok + +// {0xC0000000 + 0x000DCC9C, 0xC0000000 + 0x00180A00}, // 655 kB +// {0xC0000000 + 0x00180B60, 0xC0000000 + 0x001C0A00}, // 255 kB +// {0xC0000000 + 0x001F5EF0, 0xC0000000 + 0x00208CC0}, // 75 kB +// {0xC0000000 + 0x00234180, 0xC0000000 + 0x0024B444}, // 92 kB +// {0xC0000000 + 0x0024D8C0, 0xC0000000 + 0x0028D884}, // 255 kB +// {0xC0000000 + 0x003A745C, 0xC0000000 + 0x004D2B68}, // 1197 kB +// {0xC0000000 + 0x006D3334, 0xC0000000 + 0x00772204}, // 635 kB +// {0xC0000000 + 0x00789C60, 0xC0000000 + 0x007C6000}, // 240 kB +// {0xC0000000 + 0x00800000, 0xC0000000 + 0x01E20000}, // 22876 kB // ok + { 0xBE609ABC, 0xBFF82C00 }, // 26084 kB + { 0xB9030800, 0xB93F69A0 }, // 3864 kB + { 0xB88EEC30, 0xB8B06E98 }, // 2144 kB + { 0xBD3B966C, 0xBD8943C4 }, // 4971 kB + { 0xBCAE0370, 0xBD20EAB8 }, // 7361 kB + { 0xBD8AD3D8, 0xBE000000 }, // 7499 kB + + {0, 0} +}; // total : 66mB + 25mB + +static const memory_values_t mem_vals_540[] = +{ + { 0xBE609EFC, 0xBFF82BC0 }, // 26083 kB + { 0xBD8AD3D8, 0xBE000000 }, // 7499 kB + { 0xBCB56370, 0xBD1EF6B8 }, // 6756 kB + { 0xBD3B966C, 0xBD8943C4 }, // 4971 kB + { 0xB9030800, 0xB93F6A04 }, // 3864 kB + { 0xB88EEC30, 0xB8B06E98 }, // 2144 kB + { 0xB970200C, 0xB98B9C58 }, // 1759 kB + { 0xB8B06EC4, 0xB8B930C4 }, // 560 kB + + {0, 0} +}; + +//! retain container for our memory area table data +static unsigned char ucMemAreaTableBuffer[0xff]; + +s_mem_area * memoryGetAreaTable(void) +{ + return (s_mem_area *) (ucMemAreaTableBuffer); +} + +static inline void memoryAddArea(int start, int end, int cur_index) +{ + // Create and copy new memory area + s_mem_area * mem_area = memoryGetAreaTable(); + mem_area[cur_index].address = start; + mem_area[cur_index].size = end - start; + mem_area[cur_index].next = 0; + + // Fill pointer to this area in the previous area + if (cur_index > 0) + { + mem_area[cur_index - 1].next = &mem_area[cur_index]; + } +} + +/* Create memory areas arrays */ +void memoryInitAreaTable() +{ + u32 ApplicationMemoryEnd; + + asm volatile("lis %0, __CODE_END@h; ori %0, %0, __CODE_END@l" : "=r" (ApplicationMemoryEnd)); + + // This one seems to be available on every firmware and therefore its our code area but also our main RPX area behind our code + // 22876 kB - our application // ok + memoryAddArea(ApplicationMemoryEnd + 0xC0000000, 0xC1E20000, 0); + + const memory_values_t * mem_vals = NULL; + + switch(OS_FIRMWARE) + { + case 500: { + mem_vals = mem_vals_500; + break; + } + case 532: { + mem_vals = mem_vals_532; + break; + } + case 540: + case 550: { + mem_vals = mem_vals_540; + break; + } + default: + return; // no known values + } + + // Fill entries + int i = 0; + while (mem_vals[i].start_address) + { + memoryAddArea(mem_vals[i].start_address, mem_vals[i].end_address, i + 1); + i++; + } +} diff --git a/src/game/memory_area_table.h b/src/game/memory_area_table.h new file mode 100644 index 0000000..1c8af75 --- /dev/null +++ b/src/game/memory_area_table.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * 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_AREA_TABLE_H_ +#define _MEMORY_AREA_TABLE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct used to organize empty memory areas */ +typedef struct _s_mem_area +{ + unsigned int address; + unsigned int size; + struct _s_mem_area* next; +} s_mem_area; + +void memoryInitAreaTable(); +s_mem_area * memoryGetAreaTable(void); + + +#ifdef __cplusplus +} +#endif + +#endif // _MEMORY_AREA_TABLE_H_ diff --git a/src/game/rpx_rpl_table.c b/src/game/rpx_rpl_table.c new file mode 100644 index 0000000..bf75620 --- /dev/null +++ b/src/game/rpx_rpl_table.c @@ -0,0 +1,210 @@ +#include +#include "rpx_rpl_table.h" +#include "kernel/kernel_functions.h" +#include "common/common.h" + +//! static container holding our retain data +static unsigned char ucRpxData[0xffff]; +static int iRpxRplCount = 0; + +void rpxRplTableInit(void) +{ + s_rpx_rpl *pRpxData = (s_rpx_rpl*)ucRpxData; + //! initialize the RPL/RPX table first entry to zero + 1 byte for name zero termination + //! just in case no RPL/RPX are found, though it wont boot then anyway + memset(pRpxData, 0, sizeof(s_rpx_rpl) + 1); + iRpxRplCount = 0; +} + +s_rpx_rpl * rpxRplTableAddEntry(const char *name, int offset, int size, int is_rpx, int entry_index, s_mem_area* area) +{ + // fill rpx/rpl entry + s_rpx_rpl * rpx_rpl_data = (s_rpx_rpl *)(ucRpxData); + // get to last entry + while(rpx_rpl_data->next) { + rpx_rpl_data = rpx_rpl_data->next; + } + + // setup next entry on the previous one (only if it is not the first entry) + if(entry_index > 0) { + rpx_rpl_data->next = (s_rpx_rpl *)( ((u32)rpx_rpl_data) + sizeof(s_rpx_rpl) + strlen(rpx_rpl_data->name) + 1 ); + rpx_rpl_data = rpx_rpl_data->next; + } + + // setup current entry + rpx_rpl_data->area = area; + rpx_rpl_data->size = size; + rpx_rpl_data->offset = offset; + rpx_rpl_data->is_rpx = is_rpx; + rpx_rpl_data->next = 0; + strcpy(rpx_rpl_data->name, name); + + iRpxRplCount++; + + return rpx_rpl_data; +} + +s_rpx_rpl* rpxRplTableGet(void) +{ + return (s_rpx_rpl*)ucRpxData; +} + +int rpxRplTableGetCount(void) +{ + return iRpxRplCount; +} + +s_mem_area *rpxRplTableGetNextFreeMemArea(u32 * mem_area_addr_start, u32 * mem_area_addr_end, u32 * mem_area_offset) +{ + s_mem_area * mem_area = memoryGetAreaTable(); + s_rpx_rpl *rpl_struct = rpxRplTableGet(); + while(rpl_struct != 0) + { + // check if this entry was loaded into memory + if(rpl_struct->size == 0) { + // see if we find entries behind this one that was pre-loaded + rpl_struct = rpl_struct->next; + // entry was not loaded into memory -> skip it + continue; + } + + // this entry has been loaded to memory, remember it's area + mem_area = rpl_struct->area; + + int rpl_size = rpl_struct->size; + int rpl_offset = rpl_struct->offset; + // find the end of the entry and switch between areas if needed + while(mem_area && (u32)(rpl_offset + rpl_size) >= mem_area->size) + { + rpl_size -= mem_area->size - rpl_offset; + rpl_offset = 0; + mem_area = mem_area->next; + } + + if(!mem_area) + return NULL; + + // set new start, end and memory area offset + *mem_area_addr_start = mem_area->address; + *mem_area_addr_end = mem_area->address + mem_area->size; + *mem_area_offset = rpl_offset + rpl_size; + + // see if we find entries behind this one that was pre-loaded + rpl_struct = rpl_struct->next; + } + return mem_area; +} + +int rpxRplCopyDataToMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, const u8 *data, u32 dataSize) +{ + s_mem_area *mem_area = rpx_rpl_struct->area; + u32 mem_area_addr_start = mem_area->address; + u32 mem_area_addr_end = mem_area_addr_start + mem_area->size; + u32 mem_area_offset = rpx_rpl_struct->offset; + + // add to offset + mem_area_offset += fileOffset; + + // skip position to the end of the fill + while ((mem_area_addr_start + mem_area_offset) >= mem_area_addr_end) // TODO: maybe >, not >= + { + // subtract what was in the offset left from last memory block + mem_area_offset = (mem_area_addr_start + mem_area_offset) - mem_area_addr_end; + mem_area = mem_area->next; + if(!mem_area) + return 0; + + mem_area_addr_start = mem_area->address; + mem_area_addr_end = mem_area_addr_start + mem_area->size; + } + + // copy to memory + u32 copiedBytes = 0; + while(copiedBytes < dataSize) + { + u32 blockSize = dataSize - copiedBytes; + u32 mem_area_addr_dest = mem_area_addr_start + mem_area_offset; + + if((mem_area_addr_dest + blockSize) > mem_area_addr_end) + blockSize = mem_area_addr_end - mem_area_addr_dest; + + if(blockSize == 0) + { + // Set next memory area + mem_area = mem_area->next; + if(!mem_area) + return 0; + + mem_area_addr_start = mem_area->address; + mem_area_addr_end = mem_area->address + mem_area->size; + mem_area_offset = 0; + continue; + } + + SC0x25_KernelCopyData(mem_area_addr_dest, (u32)&data[copiedBytes], blockSize); + mem_area_offset += blockSize; + copiedBytes += blockSize; + } + + return copiedBytes; +} + +int rpxRplCopyDataFromMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, u8 *data, u32 dataSize) +{ + s_mem_area *mem_area = rpx_rpl_struct->area; + u32 mem_area_addr_start = mem_area->address; + u32 mem_area_addr_end = mem_area_addr_start + mem_area->size; + u32 mem_area_offset = rpx_rpl_struct->offset; + + if(fileOffset > rpx_rpl_struct->size) + return 0; + + if((fileOffset + dataSize) > rpx_rpl_struct->size) + dataSize = rpx_rpl_struct->size - fileOffset; + + // add to offset + mem_area_offset += fileOffset; + + // skip position to the end of the fill + while ((mem_area_addr_start + mem_area_offset) >= mem_area_addr_end) // TODO: maybe >, not >= + { + // subtract what was in the offset left from last memory block + mem_area_offset = (mem_area_addr_start + mem_area_offset) - mem_area_addr_end; + mem_area = mem_area->next; + if(!mem_area) + return 0; + + mem_area_addr_start = mem_area->address; + mem_area_addr_end = mem_area_addr_start + mem_area->size; + } + + // copy to memory + u32 copiedBytes = 0; + while(copiedBytes < dataSize) + { + u32 blockSize = dataSize - copiedBytes; + u32 mem_area_addr_dest = mem_area_addr_start + mem_area_offset; + + if((mem_area_addr_dest + blockSize) > mem_area_addr_end) + blockSize = mem_area_addr_end - mem_area_addr_dest; + + if(blockSize == 0) + { + // Set next memory area + mem_area = mem_area->next; + if(!mem_area) + return 0; + + mem_area_addr_start = mem_area->address; + mem_area_addr_end = mem_area->address + mem_area->size; + mem_area_offset = 0; + continue; + } + + SC0x25_KernelCopyData((u32)&data[copiedBytes], mem_area_addr_dest, blockSize); + mem_area_offset += blockSize; + copiedBytes += blockSize; + } + + return copiedBytes; +} diff --git a/src/game/rpx_rpl_table.h b/src/game/rpx_rpl_table.h new file mode 100644 index 0000000..b114b70 --- /dev/null +++ b/src/game/rpx_rpl_table.h @@ -0,0 +1,37 @@ +#ifndef __RPX_ARRAY_H_ +#define __RPX_ARRAY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "common/common.h" +#include "memory_area_table.h" + +/* Struct used to organize rpx/rpl data in memory */ +typedef struct _s_rpx_rpl +{ + struct _s_rpx_rpl* next; + s_mem_area* area; + unsigned int offset; + unsigned int size; + unsigned char is_rpx; + char name[0]; +} s_rpx_rpl; + +void rpxRplTableInit(void); +s_rpx_rpl* rpxRplTableAddEntry(const char *name, int offset, int size, int is_rpx, int entry_index, s_mem_area* area); +s_rpx_rpl* rpxRplTableGet(void); +int rpxRplTableGetCount(void); + +s_mem_area *rpxRplTableGetNextFreeMemArea(u32 * mem_area_addr_start, u32 * mem_area_addr_end, u32 * mem_area_offset); +int rpxRplCopyDataToMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, const u8 *data, u32 dataSize); +int rpxRplCopyDataFromMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, u8 *data, u32 dataSize); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/kernel/kernel_functions.c b/src/kernel/kernel_functions.c new file mode 100644 index 0000000..ea23be5 --- /dev/null +++ b/src/kernel/kernel_functions.c @@ -0,0 +1,81 @@ +#include +#include "common/common.h" +#include "common/kernel_defs.h" +#include "kernel/kernel_functions.h" +#include "kernel/syscalls.h" +#include "pygecko.h" + +/* our retain data */ +ReducedCosAppXmlInfo cosAppXmlInfoStruct; +/* + * 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; + + // on title switch reset the dumper + //ResetDumper(); +} + +void SetupKernelCallback(void) +{ + KernelSetupSyscalls(); +} + +void KernelSetDBATs(bat_table_t * table) +{ + SC0x36_KernelReadDBATs(table); + bat_table_t bat_table_copy = *table; + + // try to use a free slot + int iUse; + for(iUse = 0; iUse < 7; iUse++) + { + // skip position 5 as it is our main DBAT for our code data + if(iUse == 5) + continue; + + if(bat_table_copy.bat[iUse].h == 0 || bat_table_copy.bat[iUse].l == 0) + { + break; + } + } + + bat_table_copy.bat[iUse].h = 0xC0001FFF; + bat_table_copy.bat[iUse].l = 0x30000012; + SC0x37_KernelWriteDBATs(&bat_table_copy); +} + +void KernelRestoreDBATs(bat_table_t * table) +{ + SC0x37_KernelWriteDBATs(table); +} diff --git a/src/kernel/kernel_functions.h b/src/kernel/kernel_functions.h new file mode 100644 index 0000000..62df739 --- /dev/null +++ b/src/kernel/kernel_functions.h @@ -0,0 +1,22 @@ +#ifndef __KERNEL_FUNCTIONS_H_ +#define __KERNEL_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "common/kernel_defs.h" +#include "syscalls.h" + +extern ReducedCosAppXmlInfo cosAppXmlInfoStruct; + +void SetupKernelCallback(void); + +void KernelSetDBATs(bat_table_t * table); +void KernelRestoreDBATs(bat_table_t * table); + +#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..fd9cfee --- /dev/null +++ b/src/kernel/kernel_hooks.S @@ -0,0 +1,174 @@ +# 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 + +.globl injectBAT +injectBAT: + #Set dbat6u + #lis r3, 0x000000FF@h + #ori r3, r3, 0x000000FF@l + #mtspr 1, r3 + #set dbat6l + #lis r3, 0x30000012@h + #ori r3, r3, 0x30000012@l + #mtspr 2, r3 + #Set ibat6u + #lis r3, 0x000000FF@h + #ori r3, r3, 0x000000FF@l + #mtspr 3, r3 + #set ibat6l + lis r3, 0x2ff09C00@h + ori r3, r3, 0x2ff09C00@l + mtspr 4, r3 + rfi + + .globl RunSyscall36 +RunSyscall36: + mflr r0 + stwu r1, -0x10(r1) + stw r30, 0x4(r1) + stw r31, 0x8(r1) + mr r5, r0 + mr r6, r1 + li r0, 0x3600 + sc + nop + mr r0, r5 + mr r1, r6 + lwz r30, 0x04(r1) + lwz r31, 0x08(r1) + addi r1, r1, 0x10 + mtlr r0 + blr diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c new file mode 100644 index 0000000..aaca44f --- /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 = 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..2eaefa7 --- /dev/null +++ b/src/kernel/syscalls.h @@ -0,0 +1,25 @@ +#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..99e2c82 --- /dev/null +++ b/src/kernel/syscalls_asm.S @@ -0,0 +1,19 @@ +# 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..da0fb16 --- /dev/null +++ b/src/link.ld @@ -0,0 +1,43 @@ +OUTPUT(tcpgecko.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.c b/src/main.c new file mode 100644 index 0000000..5519826 --- /dev/null +++ b/src/main.c @@ -0,0 +1,222 @@ +#include +#include +#include +#include +#include + +#include +#include +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/fs_functions.h" +#include "dynamic_libs/sys_functions.h" +#include "dynamic_libs/vpad_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "patcher/function_hooks.h" +#include "fs/fs_utils.h" +#include "fs/sd_fat_devoptab.h" +#include "kernel/kernel_functions.h" +#include "system/memory.h" +#include "utils/logger.h" +#include "utils/utils.h" +#include "common/common.h" + +#define FS_BUFFER_SIZE 40000 + +int CCHandler; + +void startMiiMaker() { + char buf_vol_odd[20]; + snprintf(buf_vol_odd, sizeof(buf_vol_odd), "%s", "/vol/storage_odd03"); + _SYSLaunchTitleByPathFromLauncher(buf_vol_odd, 18, 0); +} + +char *buffer[FS_BUFFER_SIZE]; + +#define PRINT_TEXT2(x, y, ...) { snprintf(msg, 80, __VA_ARGS__); OSScreenPutFontEx(0, x, y, msg); OSScreenPutFontEx(1, x, y, msg); } + +/* Entry point */ +int Menu_Main(void) { + //!******************************************************************* + //! Initialize function pointers * + //!******************************************************************* + //! do OS (for acquire) and sockets first so we got logging + InitOSFunctionPointers(); + InitSocketFunctionPointers(); + InitFSFunctionPointers(); + InitVPadFunctionPointers(); + InitSysFunctionPointers(); + + const char ip_address[100] = "192.168.178.49"; + log_init(ip_address); + log_deinit(); + log_init(ip_address); + log_printf("Started %s\n", cosAppXmlInfoStruct.rpx_name); + + if (strcasecmp("men.rpx", cosAppXmlInfoStruct.rpx_name) == 0) { + return EXIT_RELAUNCH_ON_LOAD; + } else if (strlen(cosAppXmlInfoStruct.rpx_name) > 0 && + strcasecmp("ffl_app.rpx", cosAppXmlInfoStruct.rpx_name) != 0) { + + return EXIT_RELAUNCH_ON_LOAD; + } + + //! ******************************************************************* + //! * Setup EABI registers * + //! ******************************************************************* + register int old_sdata_start, old_sdata2_start; + asm volatile ( + "mr %0, 13\n" + "mr %1, 2\n" + "lis 2, __sdata2_start@h\n" + "ori 2, 2,__sdata2_start@l\n" // Set the Small Data 2 (Read Only) base register. + "lis 13, __sdata_start@h\n" + "ori 13, 13, __sdata_start@l\n"// # Set the Small Data (Read\Write) base register. + : "=r" (old_sdata_start), "=r" (old_sdata2_start) + ); + + //!******************************************************************* + //! Initialize BSS sections * + //!******************************************************************* + asm volatile ( + "lis 3, __bss_start@h\n" + "ori 3, 3,__bss_start@l\n" + "lis 5, __bss_end@h\n" + "ori 5, 5, __bss_end@l\n" + "subf 5, 3, 5\n" + "li 4, 0\n" + "bl memset\n" + ); + + SetupKernelCallback(); + PatchMethodHooks(); + + memoryInitialize(); + + VPADInit(); + + // Prepare screen + int screen_buf0_size = 0; + int screen_buf1_size = 0; + + // Init screen and screen buffers + OSScreenInit(); + screen_buf0_size = OSScreenGetBufferSizeEx(0); + screen_buf1_size = OSScreenGetBufferSizeEx(1); + + unsigned char *screenBuffer = MEM1_alloc(screen_buf0_size + screen_buf1_size, 0x40); + + OSScreenSetBufferEx(0, screenBuffer); + OSScreenSetBufferEx(1, (screenBuffer + screen_buf0_size)); + + OSScreenEnableEx(0, 1); + OSScreenEnableEx(1, 1); + + char msg[80]; + int launchMethod = 0; + int update_screen = 1; + int vpadError = -1; + VPADData vpad_data; + + while (1) { + // Read vpad + VPADRead(0, &vpad_data, 1, &vpadError); + + if (update_screen) { + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + + // Print message + PRINT_TEXT2(14, 1, "-- TCPGecko Installer --"); + PRINT_TEXT2(0, 5, "Press A to install TCPGecko."); + PRINT_TEXT2(0, 6, "Press X to install TCPGecko with CosmoCortney's codehandler..."); + + + PRINT_TEXT2(0, 17, "Press home button to exit ..."); + + + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); + } + + u32 pressedButtons = vpad_data.btns_d | vpad_data.btns_h; + + // Home Button + if (pressedButtons & VPAD_BUTTON_HOME) { + launchMethod = 0; + break; + } + // A Button + if (pressedButtons & VPAD_BUTTON_A) { + launchMethod = 2; + break; + } + // X Button + if (pressedButtons & VPAD_BUTTON_X) { + mount_sd_fat("sd"); + + unsigned char *Badbuffer = 0; + unsigned int filesize = 0; + int ret = LoadFileToMem("sd:/wiiu/apps/TCPGecko/codehandler.bin", &Badbuffer, &filesize); + if (ret == -1) { + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + PRINT_TEXT2(14, 5, "Codehandler.bin not found"); + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); + launchMethod = 0; + sleep(2); + break; + } + if (filesize > FS_BUFFER_SIZE) { + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + PRINT_TEXT2(14, 5, "Codehandler.bin is too big"); + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); + launchMethod = 0; + sleep(2); + break; + } + memcpy(buffer, Badbuffer, filesize); + free(Badbuffer); + + unsigned int phys_cafe_codehandler_loc = (unsigned int) OSEffectiveToPhysical((void *) CODE_HANDLER_INSTALL_ADDRESS); + + DCFlushRange(&buffer, filesize); + SC0x25_KernelCopyData((u32) phys_cafe_codehandler_loc, (int) buffer, filesize); + m_DCInvalidateRange((u32) phys_cafe_codehandler_loc, filesize); + + unmount_sd_fat("sd"); + CCHandler = 1; + + launchMethod = 2; + break; + } + + // Button pressed ? + update_screen = (pressedButtons & (VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN)) + ? 1 : 0; + usleep(20 * 1000); + } + + asm volatile ("mr 13, %0" : : "r" (old_sdata_start)); + asm volatile ("mr 2, %0" : : "r" (old_sdata2_start)); + + MEM1_free(screenBuffer); + screenBuffer = NULL; + + log_deinit(); + + memoryRelease(); + + if (launchMethod == 0) { + RestoreInstructions(); + return EXIT_SUCCESS; + } else if (launchMethod == 1) { + startMiiMaker(); + } else { + SYSLaunchMenu(); + } + + return EXIT_RELAUNCH_ON_LOAD; +} \ No newline at end of file diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..eb4e8da --- /dev/null +++ b/src/main.h @@ -0,0 +1,22 @@ +#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); + +extern int pygecko; +extern int CCHandler; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/patcher/fs_logger.c b/src/patcher/fs_logger.c new file mode 100644 index 0000000..514f299 --- /dev/null +++ b/src/patcher/fs_logger.c @@ -0,0 +1,154 @@ +#include +#include "common/common.h" +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "function_hooks.h" +#include "fs_logger.h" +#include "utils/utils.h" + +#define CHECK_ERROR(cond) if (cond) { goto error; } + +#define bss_ptr (*(struct bss_t **)0x100000e4) +#define MAX_CLIENT 32 +#define MASK_FD 0x0fff00ff + +struct bss_t { + int global_sock; + int socket_fs[MAX_CLIENT]; + void *pClient_fs[MAX_CLIENT]; + volatile int lock; + char mount_base[255]; + char save_base[255]; + void* file_replacer; + char update_path[50]; + char save_dir_common[7]; + char save_dir_user[9]; +}; + +#define bss (*bss_ptr) + + +static int sendwait(int sock, const unsigned char *buffer, int len) { + while (bss.lock) + usleep(5000); + bss.lock = 1; + + int ret; + while (len > 0) { + ret = send(sock, buffer, len, 0); + if(ret < 0) + { + len = ret; + break; + } + + len -= ret; + buffer += ret; + } + bss.lock = 0; + return len; +} + + +int fs_logger_connect(int *psock) { + struct sockaddr_in addr; + int sock, ret; + socket_lib_init(); + + //if (OSGetTitleID() == 0x000500001010ED00) +//OSFatal("hi"); + + // No ip means that we don't have any server running, so no logs + if (0 == 0) { + *psock = -1; + return 0; + } + + + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + CHECK_ERROR(sock == -1); + + addr.sin_family = AF_INET; + addr.sin_port = 7332; + addr.sin_addr.s_addr = 0; + + ret = connect(sock, (void *)&addr, sizeof(addr)); + CHECK_ERROR(ret < 0); + + int enable = 1; + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&enable, sizeof(enable)); + + unsigned char buffer[2]; + ret = recv(sock, buffer, 1, 0); + CHECK_ERROR(ret < 0); + + *psock = sock; + + bss.lock = 0; + return 0; + +error: + if (sock != -1) + socketclose(sock); + + *psock = -1; + return -1; +} + +void fs_logger_disconnect(int sock) { + CHECK_ERROR(sock == -1); + + unsigned char buffer[2]; + buffer[0] = BYTE_DISCONNECT; + buffer[1] = 0; + sendwait(sock, buffer, 1); + + socketclose(sock); +error: + return; +} + +void fs_log_string(int sock, const char* str, unsigned char flag_byte) { + if(sock == -1) { + return; + } + int i; + int len_str = 0; + while (str[len_str]) + len_str++; + + // + { + unsigned char *buffer = memalign(0x40, ROUNDUP((1 + 4 + len_str + 1), 0x40)); + if(!buffer) + return; + + buffer[0] = flag_byte; + *(int *)(buffer + 1) = len_str + 1; + for (i = 0; i < len_str; i++) + buffer[5 + i] = str[i]; + + buffer[5 + i] = 0; + + sendwait(sock, buffer, 1 + 4 + len_str + 1); + + free(buffer); + } + +} + +void fs_log_byte(int sock, unsigned char byte) { + if(sock != -1) { + unsigned char *buffer = memalign(0x40, 0x40); + if(!buffer) + return; + + buffer[0] = byte; + buffer[1] = 0; + + sendwait(sock, buffer, 1); + + free(buffer); + } +} diff --git a/src/patcher/fs_logger.h b/src/patcher/fs_logger.h new file mode 100644 index 0000000..16f451a --- /dev/null +++ b/src/patcher/fs_logger.h @@ -0,0 +1,75 @@ +#ifndef FS_LOGGER_H_ +#define FS_LOGGER_H_ + +/* Communication bytes with the server */ +// Com +#define BYTE_NORMAL 0xff +#define BYTE_SPECIAL 0xfe +#define BYTE_OK 0xfd +#define BYTE_PING 0xfc +#define BYTE_LOG_STR 0xfb +#define BYTE_DISCONNECT 0xfa + +// SD +#define BYTE_MOUNT_SD 0xe0 +#define BYTE_MOUNT_SD_OK 0xe1 +#define BYTE_MOUNT_SD_BAD 0xe2 + +// Replacement +#define BYTE_STAT 0x00 +#define BYTE_STAT_ASYNC 0x01 +#define BYTE_OPEN_FILE 0x02 +#define BYTE_OPEN_FILE_ASYNC 0x03 +#define BYTE_OPEN_DIR 0x04 +#define BYTE_OPEN_DIR_ASYNC 0x05 +#define BYTE_CHANGE_DIR 0x06 +#define BYTE_CHANGE_DIR_ASYNC 0x07 +#define BYTE_MAKE_DIR 0x08 +#define BYTE_MAKE_DIR_ASYNC 0x09 +#define BYTE_RENAME 0x0A +#define BYTE_RENAME_ASYNC 0x0B +#define BYTE_REMOVE 0x0C +#define BYTE_REMOVE_ASYNC 0x0D + +// Log +#define BYTE_CLOSE_FILE 0x40 +#define BYTE_CLOSE_FILE_ASYNC 0x41 +#define BYTE_CLOSE_DIR 0x42 +#define BYTE_CLOSE_DIR_ASYNC 0x43 +#define BYTE_FLUSH_FILE 0x44 +#define BYTE_GET_ERROR_CODE_FOR_VIEWER 0x45 +#define BYTE_GET_LAST_ERROR 0x46 +#define BYTE_GET_MOUNT_SOURCE 0x47 +#define BYTE_GET_MOUNT_SOURCE_NEXT 0x48 +#define BYTE_GET_POS_FILE 0x49 +#define BYTE_SET_POS_FILE 0x4A +#define BYTE_GET_STAT_FILE 0x4B +#define BYTE_EOF 0x4C +#define BYTE_READ_FILE 0x4D +#define BYTE_READ_FILE_ASYNC 0x4E +#define BYTE_READ_FILE_WITH_POS 0x4F +#define BYTE_READ_DIR 0x50 +#define BYTE_READ_DIR_ASYNC 0x51 +#define BYTE_GET_CWD 0x52 +#define BYTE_SET_STATE_CHG_NOTIF 0x53 +#define BYTE_TRUNCATE_FILE 0x54 +#define BYTE_WRITE_FILE 0x55 +#define BYTE_WRITE_FILE_WITH_POS 0x56 + +#define BYTE_SAVE_INIT 0x57 +#define BYTE_SAVE_SHUTDOWN 0x58 +#define BYTE_SAVE_INIT_SAVE_DIR 0x59 +#define BYTE_SAVE_FLUSH_QUOTA 0x5A +#define BYTE_SAVE_OPEN_DIR 0x5B +#define BYTE_SAVE_REMOVE 0x5C + +#define BYTE_CREATE_THREAD 0x60 + + +int fs_logger_connect(int *socket); +void fs_logger_disconnect(int socket); +void fs_log_string(int sock, const char* str, unsigned char byte); +void fs_log_byte(int sock, unsigned char byte); + + +#endif diff --git a/src/patcher/function_hooks.c b/src/patcher/function_hooks.c new file mode 100644 index 0000000..469801e --- /dev/null +++ b/src/patcher/function_hooks.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include "../common/common.h" +#include "../dynamic_libs/os_functions.h" +#include "../kernel/kernel_functions.h" +#include "function_hooks.h" +#include "../dynamic_libs/gx2_types.h" + +#define LIB_CODE_RW_BASE_OFFSET 0xC1000000 +#define CODE_RW_BASE_OFFSET 0x00000000 + +#define DECL(res, name, ...) \ + res (* real_ ## name)(__VA_ARGS__); \ + res my_ ## name(__VA_ARGS__) + +/* ***************************************************************************** + * Creates function pointer array + * ****************************************************************************/ +// #define MAKE_MAGIC(x, lib) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x } + +#define MAKE_MAGIC(x, lib, functionType) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x,0,0,functionType,0} + +DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, + s32 scan_target) { + // TODO Does not execute + GX2Surface surface = colorBuffer->surface; + u32 image_size = surface.image_size; + char buffer[100] = {0}; + __os_snprintf(buffer, 100, "Image size: %i", image_size); + OSFatal(buffer); + + real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target); +} + +DECL(int, FSInit, void) { + return real_FSInit(); +} + +DECL(int, socket_lib_finish, void) { + return 0; +} + +static const struct hooks_magic_t { + const unsigned int replaceAddr; + const unsigned int replaceCall; + const unsigned int library; + const char functionName[50]; + unsigned int realAddr; + unsigned int restoreInstruction; + unsigned char functionType; + unsigned char alreadyPatched; +} method_hooks[] = { + MAKE_MAGIC(FSInit, LIB_CORE_INIT, STATIC_FUNCTION), + MAKE_MAGIC(socket_lib_finish, LIB_CORE_INIT, STATIC_FUNCTION), + MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, DYNAMIC_FUNCTION), +}; + +//! buffer to store our 2 instructions needed for our replacements +//! the code will be placed in the address of that buffer - CODE_RW_BASE_OFFSET +//! avoid this buffer to be placed in BSS and reset on start up +volatile unsigned int fs_method_calls[sizeof(method_hooks) / sizeof(struct hooks_magic_t) * 2]; + +void PatchMethodHooks(void) { + restore_instructions_t *restore = RESTORE_INSTR_ADDR; + //! check if it is already patched + if (restore->magic == RESTORE_INSTR_MAGIC) + return; + + restore->magic = RESTORE_INSTR_MAGIC; + restore->instr_count = 0; + + bat_table_t table; + KernelSetDBATs(&table); + + /* Patch branches to it. */ + volatile unsigned int *space = &fs_method_calls[0]; + + int method_hooks_count = sizeof(method_hooks) / sizeof(struct hooks_magic_t); + + for (int i = 0; i < method_hooks_count; i++) { + unsigned int repl_addr = method_hooks[i].replaceAddr; + unsigned int call_addr = method_hooks[i].replaceCall; + + unsigned int real_addr = 0; + + if (strcmp(method_hooks[i].functionName, "OSDynLoad_Acquire") == 0) { + memcpy(&real_addr, &OSDynLoad_Acquire, 4); + } else { + OSDynLoad_FindExport(coreinit_handle, 0, method_hooks[i].functionName, &real_addr); + } + + // fill the restore instruction section + restore->data[restore->instr_count].addr = real_addr; + restore->data[restore->instr_count].instr = *(volatile unsigned int *) (LIB_CODE_RW_BASE_OFFSET + real_addr); + restore->instr_count++; + + // set pointer to the real function + *(volatile unsigned int *) (call_addr) = (unsigned int) (space) - CODE_RW_BASE_OFFSET; + DCFlushRange((void *) (call_addr), 4); + + // fill the instruction of the real function + *space = *(volatile unsigned int *) (LIB_CODE_RW_BASE_OFFSET + real_addr); + space++; + + // jump to real function skipping the first/replaced instruction + *space = 0x48000002 | ((real_addr + 4) & 0x03fffffc); + space++; + DCFlushRange((void *) (space - 2), 8); + ICInvalidateRange((unsigned char *) (space - 2) - CODE_RW_BASE_OFFSET, 8); + + unsigned int replace_instr = 0x48000002 | (repl_addr & 0x03fffffc); + *(volatile unsigned int *) (LIB_CODE_RW_BASE_OFFSET + real_addr) = replace_instr; + DCFlushRange((void *) (LIB_CODE_RW_BASE_OFFSET + real_addr), 4); + ICInvalidateRange((void *) (real_addr), 4); + } + + KernelRestoreDBATs(&table); +} + +/* ****************************************************************** */ +/* RESTORE ORIGINAL INSTRUCTIONS */ +/* ****************************************************************** */ +void RestoreInstructions(void) { + bat_table_t table; + KernelSetDBATs(&table); + + restore_instructions_t *restore = RESTORE_INSTR_ADDR; + if (restore->magic == RESTORE_INSTR_MAGIC) { + for (unsigned int i = 0; i < restore->instr_count; i++) { + *(volatile unsigned int *) (LIB_CODE_RW_BASE_OFFSET + restore->data[i].addr) = restore->data[i].instr; + DCFlushRange((void *) (LIB_CODE_RW_BASE_OFFSET + restore->data[i].addr), (u32) 4); + ICInvalidateRange((void *) restore->data[i].addr, (u32) 4); + } + } + restore->magic = 0; + restore->instr_count = 0; + + KernelRestoreDBATs(&table); + KernelRestoreInstructions(); +} \ No newline at end of file diff --git a/src/patcher/function_hooks.h b/src/patcher/function_hooks.h new file mode 100644 index 0000000..02fddfd --- /dev/null +++ b/src/patcher/function_hooks.h @@ -0,0 +1,15 @@ +#ifndef _FUNCTION_HOOKS_H_ +#define _FUNCTION_HOOKS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void PatchMethodHooks(void); +void RestoreInstructions(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _FS_H */ diff --git a/src/pygecko.c b/src/pygecko.c new file mode 100644 index 0000000..dec8d56 --- /dev/null +++ b/src/pygecko.c @@ -0,0 +1,1333 @@ +#include +#include +#include +#include "common/common.h" +#include // Actually must be included before os_functions +#include "dynamic_libs/os_functions.h" +#include +#include +#include "main.h" +#include "dynamic_libs/socket_functions.h" +#include "dynamic_libs/gx2_functions.h" +#include "kernel/syscalls.h" +#include "dynamic_libs/fs_functions.h" +#include "common/fs_defs.h" +#include "system/exception_handler.h" + +void *client; +void *commandBlock; +bool kernelCopyServiceStarted; + +struct pygecko_bss_t { + int error, line; + void *thread; + unsigned char stack[0x6F00]; +}; + +/* TCP Gecko Commands */ +#define COMMAND_WRITE_8 0x01 +#define COMMAND_WRITE_16 0x02 +#define COMMAND_WRITE_32 0x03 +#define COMMAND_READ_MEMORY 0x04 +#define COMMAND_READ_MEMORY_KERNEL 0x05 +#define COMMAND_VALIDATE_ADDRESS_RANGE 0x06 +#define COMMAND_MEMORY_DISASSEMBLE 0x08 +#define COMMAND_READ_MEMORY_COMPRESSED 0x09 // TODO Remove command when done and integrate in read memory +#define COMMAND_KERNEL_WRITE 0x0B +#define COMMAND_KERNEL_READ 0x0C +#define COMMAND_TAKE_SCREEN_SHOT 0x0D // TODO Finish this +#define COMMAND_UPLOAD_MEMORY 0x41 +#define COMMAND_SERVER_STATUS 0x50 +#define COMMAND_GET_DATA_BUFFER_SIZE 0x51 +#define COMMAND_READ_FILE 0x52 +#define COMMAND_READ_DIRECTORY 0x53 +#define COMMAND_REPLACE_FILE 0x54 // TODO Test this +#define COMMAND_GET_CODE_HANDLER_ADDRESS 0x55 +#define COMMAND_READ_THREADS 0x56 +#define COMMAND_ACCOUNT_IDENTIFIER 0x57 +#define COMMAND_WRITE_SCREEN 0x58 // TODO Exception DSI +#define COMMAND_FOLLOW_POINTER 0x60 +#define COMMAND_RPC 0x70 +#define COMMAND_GET_SYMBOL 0x71 +#define COMMAND_MEMORY_SEARCH 0x73 +#define COMMAND_SERVER_VERSION 0x99 +#define COMMAND_OS_VERSION 0x9A +#define COMMAND_RUN_KERNEL_COPY_SERVICE 0xCD + +#define CHECK_ERROR(cond) if (cond) { bss->line = __LINE__; goto error; } +#define errno (*__gh_errno_ptr()) +#define MSG_DONTWAIT 32 +#define EWOULDBLOCK 6 +#define FS_BUFFER_SIZE 0x1000 +#define DATA_BUFFER_SIZE 0x5000 +#define DISASSEMBLER_BUFFER_SIZE 0x1024 +#define SERVER_VERSION "02/25/2017" +#define ONLY_ZEROS_READ 0xB0 +#define NON_ZEROS_READ 0xBD + +#define ASSERT_MINIMUM_HOLDS(actual, minimum, variableName) \ +if(actual < minimum) { \ + char buffer[100] = {0}; \ + __os_snprintf(buffer, 100, "%s: Limit exceeded (minimum: %i, actual: %i)", variableName, minimum, actual); \ + OSFatal(buffer); \ +} \ + +#define ASSERT_MAXIMUM_HOLDS(maximum, actual, variableName) \ +if(actual > maximum) { \ + char buffer[100] = {0}; \ + __os_snprintf(buffer, 100, "%s: Limit exceeded (maximum: %i, actual: %i)", variableName, maximum, actual); \ + OSFatal(buffer); \ +} \ + +#define ASSERT_FUNCTION_SUCCEEDED(returnValue, functionName) \ + if (returnValue < 0) { \ + char buffer[100] = {0}; \ + __os_snprintf(buffer, 100, "%s failed with return value: %i", functionName, returnValue); \ + OSFatal(buffer); \ + } \ + +#define ASSERT_VALID_EFFECTIVE_ADDRESS(effectiveAddress, message) \ + if(!OSIsAddressValid((void *) effectiveAddress)) { \ + char buffer[100] = {0}; \ + __os_snprintf(buffer, 100, "Address %04x invalid: %s", effectiveAddress, message); \ + OSFatal(buffer); \ + } \ + +#define ASSERT_INTEGER(actual, expected, name) \ + if(actual != expected) { \ + char buffer[50] = {0}; \ + __os_snprintf(buffer, 50, "%s assertion failed: %i == %i", name, actual, expected); \ + OSFatal(buffer); \ + } \ + +#define ASSERT_STRING(actual, expected) \ + if(strcmp(actual, expected) != 0) { \ + char buffer[50] = {0}; \ + __os_snprintf(buffer, 50, "String assertion failed: \"%s\" == \"%s\"", actual, expected); \ + OSFatal(buffer); \ + } \ + +#define ASSERT_ALLOCATED(variable, name) \ + if(variable == 0) { \ + char buffer[50] = {0}; \ + __os_snprintf(buffer, 50, "%s allocation failed", name); \ + OSFatal(buffer); \ + } \ + +ZEXTERN int ZEXPORT +deflateEnd OF((z_streamp +strm)); +ZEXTERN int ZEXPORT +deflateInit OF((z_streamp +strm, +int level +)); +ZEXTERN int ZEXPORT +deflate OF((z_streamp +strm, +int flush +)); + +unsigned char *memcpy_buffer[DATA_BUFFER_SIZE]; + +void pygecko_memcpy(unsigned char *destinationBuffer, unsigned char *sourceBuffer, unsigned int length) { + memcpy(memcpy_buffer, sourceBuffer, length); + SC0x25_KernelCopyData((unsigned int) OSEffectiveToPhysical(destinationBuffer), (unsigned int) &memcpy_buffer, + length); + DCFlushRange(destinationBuffer, (u32) length); +} + +unsigned char *kernelCopyBuffer[4]; + +void kernelCopy(unsigned char *destinationBuffer, unsigned char *sourceBuffer, unsigned int length) { + memcpy(kernelCopyBuffer, sourceBuffer, length); + unsigned int destinationAddress = (unsigned int) OSEffectiveToPhysical(destinationBuffer); + SC0x25_KernelCopyData(destinationAddress, (unsigned int) &kernelCopyBuffer, length); + DCFlushRange(destinationBuffer, (u32) length); +} + +#define KERNEL_COPY_SOURCE_ADDRESS 0x10100000 + +int kernelCopyService(int argc, void *argv) { + while (true) { + // Read the destination address from the source address + int destinationAddress = *(int *) KERNEL_COPY_SOURCE_ADDRESS; + + // Avoid crashing + if (OSIsAddressValid((const void *) destinationAddress)) { + // Perform memory copy + unsigned char *valueBuffer = (unsigned char *) (KERNEL_COPY_SOURCE_ADDRESS + 4); + kernelCopy((unsigned char *) destinationAddress, valueBuffer, 4); + + // "Consume" address and value for synchronization with the code handler for instance + *(int *) KERNEL_COPY_SOURCE_ADDRESS = 0; + *(((int *) KERNEL_COPY_SOURCE_ADDRESS) + 1) = 0; + } + } +} + +void startKernelCopyService() { + unsigned int stack = (unsigned int) memalign(0x40, 0x100); + ASSERT_ALLOCATED(stack, "Kernel copy thread stack") + stack += 0x100; + void *thread = memalign(0x40, 0x1000); + ASSERT_ALLOCATED(thread, "Kernel copy thread") + + int status = OSCreateThread(thread, kernelCopyService, 1, NULL, (u32) stack + sizeof(stack), sizeof(stack), 31, + OS_THREAD_ATTR_AFFINITY_CORE1 | OS_THREAD_ATTR_PINNED_AFFINITY | OS_THREAD_ATTR_DETACH); + ASSERT_INTEGER(status, 1, "Creating kernel copy thread") + // OSSetThreadName(thread, "Kernel Copier"); + OSResumeThread(thread); +} + +/*Validates the address range (last address inclusive) but is SLOW on bigger ranges */ +static int validateAddressRange(int starting_address, int ending_address) { + return __OSValidateAddressSpaceRange(1, (void *) starting_address, ending_address - starting_address + 1); +} + +static int recvwait(struct pygecko_bss_t *bss, int sock, void *buffer, int len) { + int ret; + while (len > 0) { + ret = recv(sock, buffer, len, 0); + CHECK_ERROR(ret < 0); + len -= ret; + buffer += ret; + } + return 0; + + error: + bss->error = ret; + return ret; +} + +static int recvbyte(struct pygecko_bss_t *bss, int sock) { + unsigned char buffer[1]; + int ret; + + ret = recvwait(bss, sock, buffer, 1); + if (ret < 0) return ret; + return buffer[0]; +} + +static int checkbyte(int sock) { + unsigned char buffer[1]; + int ret; + + ret = recv(sock, buffer, 1, MSG_DONTWAIT); + if (ret < 0) return ret; + if (ret == 0) return -1; + return buffer[0]; +} + +static int sendwait(struct pygecko_bss_t *bss, int sock, const void *buffer, int len) { + int ret; + while (len > 0) { + ret = send(sock, buffer, len, 0); + CHECK_ERROR(ret < 0); + len -= ret; + buffer += ret; + } + return 0; + error: + bss->error = ret; + return ret; +} + +static int sendbyte(struct pygecko_bss_t *bss, int sock, unsigned char byte) { + unsigned char buffer[1]; + + buffer[0] = byte; + return sendwait(bss, sock, buffer, 1); +} + +void writeScreen(char message[100], int secondsDelay) { + // TODO Does nothing then crashes (in games)? + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + + OSScreenPutFontEx(0, 14, 1, message); + OSScreenPutFontEx(1, 14, 1, message); + + sleep(secondsDelay); + + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); +} + +void receiveString(struct pygecko_bss_t *bss, + int clientfd, + char *stringBuffer, + int bufferSize) { + // Receive the string length + char lengthBuffer[4] = {0}; + int ret = recvwait(bss, clientfd, lengthBuffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (string length)") + int stringLength = ((int *) lengthBuffer)[0]; + + if (stringLength >= 0 && stringLength <= bufferSize) { + // Receive the actual string + ret = recvwait(bss, clientfd, stringBuffer, stringLength); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (string)") + } else { + OSFatal("String buffer size exceeded"); + } +} + +void considerInitializingFileSystem() { + if (!client) { + // Initialize the file system + int status = FSInit(); + ASSERT_FUNCTION_SUCCEEDED(status, "FSInit") + + // Allocate the client + client = malloc(FS_CLIENT_SIZE); + ASSERT_ALLOCATED(client, "Client") + + // Register the client + status = FSAddClientEx(client, 0, -1); + ASSERT_FUNCTION_SUCCEEDED(status, "FSAddClientEx") + + // Allocate the command block + commandBlock = malloc(FS_CMD_BLOCK_SIZE); + ASSERT_ALLOCATED(commandBlock, "Command block") + + FSInitCmdBlock(commandBlock); + } +} + +char *disassemblerBuffer; +void *disassemblerBufferPointer; + +void formatDisassembled(char *format, ...) { + if (!disassemblerBuffer) { + disassemblerBuffer = malloc(DISASSEMBLER_BUFFER_SIZE); + ASSERT_ALLOCATED(disassemblerBuffer, "Disassembler buffer") + disassemblerBufferPointer = disassemblerBuffer; + } + + va_list variableArguments; + va_start(variableArguments, format); + char *temporaryBuffer; + int printedBytesCount = vasprintf(&temporaryBuffer, format, variableArguments); + ASSERT_ALLOCATED(temporaryBuffer, "Temporary buffer") + ASSERT_MINIMUM_HOLDS(printedBytesCount, 1, "Printed bytes count") + va_end(variableArguments); + + // Do not smash the buffer + long projectedSize = (void *) disassemblerBuffer - disassemblerBufferPointer + printedBytesCount; + if (projectedSize < DISASSEMBLER_BUFFER_SIZE) { + memcpy(disassemblerBuffer, temporaryBuffer, printedBytesCount); + disassemblerBuffer += printedBytesCount; + } + + free(temporaryBuffer); +} + +bool isValidDataAddress(int address) { + return OSIsAddressValid((const void *) address) + && address >= 0x10000000 + && address < 0x50000000; +} + +int roundUpToAligned(int number) { + return (number + 3) & ~0x03; +} + +#define ERROR_BUFFER_SIZE 100 + +void reportIllegalCommandByte(int commandByte) { + char errorBuffer[ERROR_BUFFER_SIZE]; + __os_snprintf(errorBuffer, ERROR_BUFFER_SIZE, "Illegal command byte received: 0x%02x\nServer Version: %s", + commandByte, SERVER_VERSION); + OSFatal(errorBuffer); +} + +void writeInt(unsigned int address, unsigned int value) { + pygecko_memcpy((unsigned char *) address, (unsigned char *) &value, 4); +} + +#define MINIMUM_KERNEL_COMPARE_LENGTH 4 +#define KERNEL_MEMORY_COMPARE_STEP_SIZE 1 + +int kernelMemoryCompare(const void *sourceBuffer, + const void *destinationBuffer, + int length) { + if (length < MINIMUM_KERNEL_COMPARE_LENGTH) { + ASSERT_MINIMUM_HOLDS(length, MINIMUM_KERNEL_COMPARE_LENGTH, "length"); + } + + bool loopEntered = false; + + while (kern_read(sourceBuffer) == kern_read(destinationBuffer)) { + loopEntered = true; + sourceBuffer = (char *) sourceBuffer + KERNEL_MEMORY_COMPARE_STEP_SIZE; + destinationBuffer = (char *) destinationBuffer + KERNEL_MEMORY_COMPARE_STEP_SIZE; + length -= KERNEL_MEMORY_COMPARE_STEP_SIZE; + + if (length <= MINIMUM_KERNEL_COMPARE_LENGTH - 1) { + break; + } + } + + if (loopEntered) { + sourceBuffer -= KERNEL_MEMORY_COMPARE_STEP_SIZE; + destinationBuffer -= KERNEL_MEMORY_COMPARE_STEP_SIZE; + } + + return kern_read(sourceBuffer) - kern_read(destinationBuffer); +} + +static int rungecko(struct pygecko_bss_t *bss, int clientfd) { + int ret; + + // Hold the command and the data + unsigned char buffer[1 + DATA_BUFFER_SIZE]; + + // Run the RPC server + while (true) { + ret = checkbyte(clientfd); + + if (ret < 0) { + CHECK_ERROR(errno != EWOULDBLOCK); + GX2WaitForVsync(); + continue; + } + + switch (ret) { + case COMMAND_WRITE_8: { + char *destinationAddress; + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0); + + destinationAddress = ((char **) buffer)[0]; + *destinationAddress = buffer[7]; + DCFlushRange(destinationAddress, 1); + break; + } + case COMMAND_WRITE_16: { + short *destinationAddress; + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0) + + destinationAddress = ((short **) buffer)[0]; + *destinationAddress = ((short *) buffer)[3]; + DCFlushRange(destinationAddress, 2); + break; + } + case COMMAND_WRITE_32: { + int destinationAddress, value; + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0) + + destinationAddress = ((int *) buffer)[0]; + value = ((int *) buffer)[1]; + + pygecko_memcpy((unsigned char *) destinationAddress, (unsigned char *) &value, 4); + break; + } + case COMMAND_READ_MEMORY: { + const unsigned char *startingAddress, *endingAddress; + ret = recvwait(bss, clientfd, buffer, 2 * 4); + CHECK_ERROR(ret < 0) + startingAddress = ((const unsigned char **) buffer)[0]; + endingAddress = ((const unsigned char **) buffer)[1]; + + while (startingAddress != endingAddress) { + int length = (int) (endingAddress - startingAddress); + + // Do not smash the buffer + if (length > DATA_BUFFER_SIZE) { + length = DATA_BUFFER_SIZE; + } + + // Figure out if all bytes are zero to possibly avoid sending them + int rangeIterationIndex = 0; + for (; rangeIterationIndex < length; rangeIterationIndex++) { + int character = startingAddress[rangeIterationIndex]; + + if (character != 0) { + break; + } + } + + if (rangeIterationIndex == length) { + // No need to send all zero bytes for performance + ret = sendbyte(bss, clientfd, ONLY_ZEROS_READ); + CHECK_ERROR(ret < 0) + } else { + // TODO Compression of ptr, sending of status, compressed size and data, length: 1 + 4 + len(data) + buffer[0] = NON_ZEROS_READ; + memcpy(buffer + 1, startingAddress, length); + ret = sendwait(bss, clientfd, buffer, length + 1); + CHECK_ERROR(ret < 0) + } + + /* No exit condition. + We reconnect client-sided instead as a hacky work-around + to gain a little more performance by avoiding the very rare search canceling + */ + + startingAddress += length; + } + break; + } + case COMMAND_READ_MEMORY_KERNEL: { + const unsigned char *startingAddress, *endingAddress, *useKernRead; + ret = recvwait(bss, clientfd, buffer, 3 * 4); + CHECK_ERROR(ret < 0) + startingAddress = ((const unsigned char **) buffer)[0]; + endingAddress = ((const unsigned char **) buffer)[1]; + useKernRead = ((const unsigned char **) buffer)[2]; + + while (startingAddress != endingAddress) { + int length = (int) (endingAddress - startingAddress); + + // Do not smash the buffer + if (length > DATA_BUFFER_SIZE) { + length = DATA_BUFFER_SIZE; + } + + // Figure out if all bytes are zero to possibly avoid sending them + int rangeIterationIndex = 0; + for (; rangeIterationIndex < length; rangeIterationIndex++) { + int character = useKernRead ? kern_read(startingAddress + rangeIterationIndex) + : startingAddress[rangeIterationIndex]; + if (character != 0) { + break; + } + } + + if (rangeIterationIndex == length) { + // No need to send all zero bytes for performance + ret = sendbyte(bss, clientfd, ONLY_ZEROS_READ); + CHECK_ERROR(ret < 0) + } else { + // TODO Compression of ptr, sending of status, compressed size and data, length: 1 + 4 + len(data) + buffer[0] = NON_ZEROS_READ; + + if (useKernRead) { + for (int offset = 0; offset < length; offset += 4) { + *((int *) (buffer + 1) + offset / 4) = kern_read(startingAddress + offset); + } + } else { + memcpy(buffer + 1, startingAddress, length); + } + + ret = sendwait(bss, clientfd, buffer, length + 1); + CHECK_ERROR(ret < 0) + } + + /* No exit condition. + We reconnect client-sided instead as a hacky work-around + to gain a little more performance by avoiding the very rare search canceling + */ + + startingAddress += length; + } + break; + } + case COMMAND_VALIDATE_ADDRESS_RANGE: { + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0) + + // Retrieve the data + int startingAddress = ((int *) buffer)[0]; + int endingAddress = ((int *) buffer)[1]; + + int isAddressRangeValid = validateAddressRange(startingAddress, endingAddress); + + sendbyte(bss, clientfd, (unsigned char) isAddressRangeValid); + break; + } + /*case COMMAND_DISASSEMBLE_RANGE: { + // Receive the starting, ending address and the disassembler options + ret = recvwait(bss, clientfd, buffer, 4 + 4 + 4); + CHECK_ERROR(ret < 0) + void *startingAddress = ((void **) buffer)[0]; + void *endingAddress = ((void **) buffer)[1]; + int disassemblerOptions = ((int *) buffer)[2]; + + // Disassemble + DisassemblePPCRange(startingAddress, endingAddress, formatDisassembled, OSGetSymbolName, + (u32) disassemblerOptions); + + // Send the disassembler buffer size + int length = DISASSEMBLER_BUFFER_SIZE; + ret = sendwait(bss, clientfd, &length, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (disassembler buffer size)") + + // Send the data + ret = sendwait(bss, clientfd, disassemblerBufferPointer, length); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (disassembler buffer)") + + // Place the pointer back to the beginning + disassemblerBuffer = (char *) disassemblerBufferPointer; + + break; + }*/ + case COMMAND_MEMORY_DISASSEMBLE: { + // Receive the starting address, ending address and disassembler options + ret = recvwait(bss, clientfd, buffer, 4 + 4 + 4); + CHECK_ERROR(ret < 0) + int startingAddress = ((int *) buffer)[0]; + int endingAddress = ((int *) buffer)[1]; + int disassemblerOptions = ((int *) buffer)[2]; + + int currentAddress = startingAddress; + int bufferSize = PPC_DISASM_MAX_BUFFER; + int integerSize = 4; + + // Disassemble everything + while (currentAddress < endingAddress) { + int currentIntegerIndex = 0; + + while ((currentIntegerIndex < (DATA_BUFFER_SIZE / integerSize)) + && (currentAddress < endingAddress)) { + int value = *(int *) currentAddress; + ((int *) buffer)[currentIntegerIndex++] = value; + char *opCodeBuffer = malloc(bufferSize); + bool status = DisassemblePPCOpcode((u32 *) currentAddress, opCodeBuffer, (u32) bufferSize, + OSGetSymbolName, + (u32) disassemblerOptions); + + ((int *) buffer)[currentIntegerIndex++] = status; + + if (status == 1) { + // Send the length of the opCode buffer string + int length = strlen(opCodeBuffer); + ((int *) buffer)[currentIntegerIndex++] = length; + + // Send the opCode buffer itself + memcpy(buffer + (currentIntegerIndex * integerSize), opCodeBuffer, length); + currentIntegerIndex += (roundUpToAligned(length) / integerSize); + } + + free(opCodeBuffer); + currentAddress += integerSize; + } + + int bytesToSend = currentIntegerIndex * integerSize; + ret = sendwait(bss, clientfd, &bytesToSend, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Buffer size)") + + // VALUE(4)|STATUS(4)|LENGTH(4)|DISASSEMBLED(LENGTH) + ret = sendwait(bss, clientfd, buffer, bytesToSend); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Buffer)") + } + + int bytesToSend = 0; + ret = sendwait(bss, clientfd, &bytesToSend, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (No more bytes)") + + break; + } + case COMMAND_READ_MEMORY_COMPRESSED: { + // Receive the starting address and length + ret = recvwait(bss, clientfd, buffer, 4 + 4); + CHECK_ERROR(ret < 0) + int startingAddress = ((int *) buffer)[0]; + unsigned int inputLength = ((unsigned int *) buffer)[1]; + + z_stream stream; + memset(&stream, 0, sizeof(stream)); + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + + // Initialize the stream struct + ret = deflateInit(&stream, Z_BEST_COMPRESSION); + ASSERT_INTEGER(ret, Z_OK, "deflateInit") + + // Supply the data + stream.avail_in = inputLength; + stream.next_in = (Bytef *) startingAddress; + stream.avail_out = DATA_BUFFER_SIZE; + void *outputBuffer = (void *) (&buffer + 4); + stream.next_out = (Bytef *) outputBuffer; + + // Deflate + ret = deflate(&stream, Z_FINISH); + ASSERT_INTEGER(ret, Z_OK, "deflate"); + + // Finish + ret = deflateEnd(&stream); + ASSERT_INTEGER(ret, Z_OK, "deflateEnd"); + + // Send the compressed buffer size and content + int deflatedSize = stream.total_out; + ((int *) buffer)[0] = deflatedSize; + ret = sendwait(bss, clientfd, buffer, 4 + deflatedSize); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Compressed data)") + + break; + + // https://www.gamedev.net/resources/_/technical/game-programming/in-memory-data-compression-and-decompression-r2279 + /* + + // Setup compressed buffer + unsigned int compressedBufferSize = length * 2; + void *compressedBuffer = (void *) OSAllocFromSystem(compressedBufferSize, 0x4); + ASSERT_ALLOCATED(compressedBuffer, "Compressed buffer") + + unsigned int zlib_handle; + OSDynLoad_Acquire("zlib125.rpl", (u32 *) &zlib_handle); + int (*compress2)(char *, int *, const char *, int, int); + OSDynLoad_FindExport((u32) zlib_handle, 0, "compress2", &compress2); + + int destinationBufferSize; + int status = compress2((char *) compressedBuffer, &destinationBufferSize, + (const char *) rawBuffer, length, Z_DEFAULT_COMPRESSION); + + ret = sendwait(bss, clientfd, &status, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (status)") + + if (status == Z_OK) { + // Send the compressed buffer size and content + ((int *) buffer)[0] = destinationBufferSize; + memcpy(buffer + 4, compressedBuffer, destinationBufferSize); + + ret = sendwait(bss, clientfd, buffer, 4 + destinationBufferSize); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (Compressed data)") + } + + free(rawBuffer); + OSFreeToSystem(compressedBuffer); + + break;*/ + } + case COMMAND_KERNEL_WRITE: { + void *ptr, *value; + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0) + + ptr = ((void **) buffer)[0]; + value = ((void **) buffer)[1]; + + kern_write(ptr, (uint32_t) value); + break; + } + case COMMAND_KERNEL_READ: { + void *ptr, *value; + ret = recvwait(bss, clientfd, buffer, 4); + CHECK_ERROR(ret < 0); + + ptr = ((void **) buffer)[0]; + + value = (void *) kern_read(ptr); + + *(void **) buffer = value; + sendwait(bss, clientfd, buffer, 4); + break; + } + case COMMAND_TAKE_SCREEN_SHOT: { + GX2ColorBuffer colorBuffer; + // TODO Initialize colorBuffer! + GX2Surface surface = colorBuffer.surface; + void *image_data = surface.image_data; + u32 image_size = surface.image_size; + + // Send the image size so that the client knows how much to read + ret = sendwait(bss, clientfd, &image_size, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (image size)") + + unsigned int imageBytesSent = 0; + while (imageBytesSent < image_size) { + int length = image_size - imageBytesSent; + + // Do not smash the buffer + if (length > DATA_BUFFER_SIZE) { + length = DATA_BUFFER_SIZE; + } + + // Send the image bytes + memcpy(buffer, image_data, length); + ret = sendwait(bss, clientfd, buffer, length); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (image bytes)") + + imageBytesSent += length; + } + + break; + } + case COMMAND_UPLOAD_MEMORY: { + // Receive the starting and ending addresses + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0) + unsigned char *current_address = ((unsigned char **) buffer)[0]; + unsigned char *end_address = ((unsigned char **) buffer)[1]; + + while (current_address != end_address) { + int length; + + length = (int) (end_address - current_address); + if (length > DATA_BUFFER_SIZE) { + length = DATA_BUFFER_SIZE; + } + + ret = recvwait(bss, clientfd, buffer, length); + CHECK_ERROR(ret < 0) + pygecko_memcpy(current_address, buffer, (unsigned int) length); + + current_address += length; + } + + break; + } + case COMMAND_GET_DATA_BUFFER_SIZE: { + ((int *) buffer)[0] = DATA_BUFFER_SIZE; + ret = sendwait(bss, clientfd, buffer, 4); + CHECK_ERROR(ret < 0) + + break; + } + case COMMAND_READ_FILE: { + char file_path[FS_MAX_FULLPATH_SIZE] = {0}; + receiveString(bss, clientfd, file_path, FS_MAX_FULLPATH_SIZE); + + considerInitializingFileSystem(); + + int handle; + int status = FSOpenFile(client, commandBlock, file_path, "r", &handle, FS_RET_ALL_ERROR); + + if (status == FS_STATUS_OK) { + // Send the OK status + ((int *) buffer)[0] = status; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (OK status)") + + // Retrieve the file statistics + FSStat stat; + ret = FSGetStatFile(client, commandBlock, handle, &stat, FS_RET_ALL_ERROR); + ASSERT_FUNCTION_SUCCEEDED(ret, "FSGetStatFile") + + // Send the total bytes count + int totalBytes = (int) stat.size; + ((int *) buffer)[0] = totalBytes; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (total bytes)") + + // Allocate the file bytes buffer + unsigned int file_buffer_size = 0x2000; + char *fileBuffer = (char *) OSAllocFromSystem(file_buffer_size, FS_IO_BUFFER_ALIGN); + ASSERT_ALLOCATED(fileBuffer, "File buffer") + + int totalBytesRead = 0; + while (totalBytesRead < totalBytes) { + int bytesRead = FSReadFile(client, commandBlock, fileBuffer, 1, file_buffer_size, + handle, 0, FS_RET_ALL_ERROR); + ASSERT_FUNCTION_SUCCEEDED(bytesRead, "FSReadFile") + + // Send file bytes + ret = sendwait(bss, clientfd, fileBuffer, bytesRead); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (file buffer)") + + totalBytesRead += bytesRead; + } + + ret = FSCloseFile(client, commandBlock, handle, FS_RET_ALL_ERROR); + ASSERT_FUNCTION_SUCCEEDED(ret, "FSCloseFile") + + OSFreeToSystem(fileBuffer); + } else { + // Send the error status + ((int *) buffer)[0] = status; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (error status)") + } + + break; + } + case COMMAND_READ_DIRECTORY: { + char directory_path[FS_MAX_FULLPATH_SIZE] = {0}; + receiveString(bss, clientfd, directory_path, FS_MAX_FULLPATH_SIZE); + + considerInitializingFileSystem(); + + int handle; + FSDirEntry entry; + + ret = FSOpenDir(client, commandBlock, directory_path, &handle, FS_RET_ALL_ERROR); + + if (ret == FS_STATUS_OK) { + // Send the success status + ((int *) buffer)[0] = ret; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (success status)") + + int entrySize = sizeof(FSDirEntry); + + // Read every entry in the given directory + while (FSReadDir(client, commandBlock, handle, &entry, -1) == FS_STATUS_OK) { + // Let the client know how much data is going to be sent (even though this is constant) + ((int *) buffer)[0] = entrySize; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (data coming)") + + // Send the struct + ret = sendwait(bss, clientfd, &entry, entrySize); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (directory entry)") + } + + // No more data will be sent, hence a 0 byte + ((int *) buffer)[0] = 0; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (no more data)") + + // Done, close the directory also + ret = FSCloseDir(client, commandBlock, handle, FS_RET_ALL_ERROR); + ASSERT_FUNCTION_SUCCEEDED(ret, "FSCloseDir") + } else { + // Send the status + ((int *) buffer)[0] = ret; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (error status)") + } + + break; + } + case COMMAND_REPLACE_FILE: { + // TODO Write file + + // Receive the file path + char file_path[FS_MAX_FULLPATH_SIZE] = {0}; + receiveString(bss, clientfd, file_path, FS_MAX_FULLPATH_SIZE); + + considerInitializingFileSystem(); + + // Create an empty file for writing. Its contents will be erased + int handle; + int status = FSOpenFile(client, commandBlock, file_path, "w", &handle, FS_RET_ALL_ERROR); + + if (status == FS_STATUS_OK) { + // Send the OK status + ((int *) buffer)[0] = status; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (OK status)") + + // Set the file handle position to the beginning + ret = FSSetPosFile(client, commandBlock, handle, 0, FS_RET_ALL_ERROR); + ASSERT_FUNCTION_SUCCEEDED(ret, "FSSetPosFile") + + // Allocate the file bytes buffer + unsigned int file_buffer_size = 0x2000; + char *fileBuffer = (char *) OSAllocFromSystem(file_buffer_size, FS_IO_BUFFER_ALIGN); + ASSERT_ALLOCATED(fileBuffer, "File buffer") + + // Send the maximum file buffer size + ret = sendwait(bss, clientfd, &file_buffer_size, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (maximum file buffer size)") + + while (true) { + // Receive the data bytes length + unsigned int dataLength; + ret = recvwait(bss, clientfd, &dataLength, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (File bytes length)") + ASSERT_MAXIMUM_HOLDS(file_buffer_size, dataLength, "File buffer overrun attempted") + + if (dataLength > 0) { + // Receive the data + ret = recvwait(bss, clientfd, fileBuffer, dataLength); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (File buffer)") + + // Write the data and advance file handle position + ret = FSWriteFile(client, commandBlock, fileBuffer, 1, + dataLength, handle, 0, FS_RET_ALL_ERROR); + ASSERT_FUNCTION_SUCCEEDED(ret, "FSWriteFile") + } else { + // Done + break; + } + } + + /*// Flush the file back + ret = FSFlushFile(client, commandBlock, handle, FS_RET_ALL_ERROR); + CHECK_FUNCTION_FAILED(ret, "FSFlushFile")*/ + + // Close the file + ret = FSCloseFile(client, commandBlock, handle, FS_RET_ALL_ERROR); + ASSERT_FUNCTION_SUCCEEDED(ret, "FSCloseFile") + + // Free the file buffer + OSFreeToSystem(fileBuffer); + } else { + // Send the status + ((int *) buffer)[0] = status; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (status)") + } + + break; + } + case COMMAND_GET_CODE_HANDLER_ADDRESS: { + ((int *) buffer)[0] = CODE_HANDLER_INSTALL_ADDRESS; + ret = sendwait(bss, clientfd, buffer, 4); + CHECK_ERROR(ret < 0) + + break; + } + case COMMAND_READ_THREADS: { + int OS_THREAD_SIZE = 0x6A0; + + int currentThreadAddress = OSGetCurrentThread(); + ASSERT_VALID_EFFECTIVE_ADDRESS(currentThreadAddress, "OSGetCurrentThread") + int iterationThreadAddress = currentThreadAddress; + int temporaryThreadAddress; + + // Follow "previous thread" pointers back to the beginning + while ((temporaryThreadAddress = *(int *) (iterationThreadAddress + 0x390)) != 0) { + iterationThreadAddress = temporaryThreadAddress; + ASSERT_VALID_EFFECTIVE_ADDRESS(iterationThreadAddress, "iterationThreadAddress going backwards") + } + + // Send all threads by following the "next thread" pointers + while ((temporaryThreadAddress = *(int *) (iterationThreadAddress + 0x38C)) != 0) { + // Send the starting thread's address + ((int *) buffer)[0] = iterationThreadAddress; + + // Send the thread struct itself + memcpy(buffer + 4, (void *) iterationThreadAddress, OS_THREAD_SIZE); + ret = sendwait(bss, clientfd, buffer, 4 + OS_THREAD_SIZE); + CHECK_ERROR(ret < 0) + + iterationThreadAddress = temporaryThreadAddress; + ASSERT_VALID_EFFECTIVE_ADDRESS(iterationThreadAddress, "iterationThreadAddress going forwards") + } + + // The previous while would skip the last thread so send it also + ((int *) buffer)[0] = iterationThreadAddress; + memcpy(buffer + 4, (void *) iterationThreadAddress, OS_THREAD_SIZE); + ret = sendwait(bss, clientfd, buffer, 4 + OS_THREAD_SIZE); + CHECK_ERROR(ret < 0) + + // Let the client know that no more threads are coming + ((int *) buffer)[0] = 0; + ret = sendwait(bss, clientfd, buffer, 4); + CHECK_ERROR(ret < 0) + + break; + } + case COMMAND_ACCOUNT_IDENTIFIER: { + // Acquire the RPL + unsigned int nn_act_handle; + OSDynLoad_Acquire("nn_act.rpl", &nn_act_handle); + + // Acquire the functions via their mangled file names + int (*nn_act_Initialize)(void); + OSDynLoad_FindExport(nn_act_handle, 0, "Initialize__Q2_2nn3actFv", &nn_act_Initialize); + ASSERT_ALLOCATED(nn_act_Initialize, "nn_act_Initialize") + unsigned char (*nn_act_GetSlotNo)(void); + OSDynLoad_FindExport(nn_act_handle, 0, "GetSlotNo__Q2_2nn3actFv", &nn_act_GetSlotNo); + ASSERT_ALLOCATED(nn_act_GetSlotNo, "nn_act_GetSlotNo") + unsigned int (*nn_act_GetPersistentIdEx)(unsigned char); + OSDynLoad_FindExport(nn_act_handle, 0, "GetPersistentIdEx__Q2_2nn3actFUc", &nn_act_GetPersistentIdEx); + ASSERT_ALLOCATED(nn_act_GetPersistentIdEx, "nn_act_GetPersistentIdEx") + int (*nn_act_Finalize)(void); + OSDynLoad_FindExport(nn_act_handle, 0, "Finalize__Q2_2nn3actFv", &nn_act_Finalize); + ASSERT_ALLOCATED(nn_act_Finalize, "nn_act_Finalize") + + // Get the identifier + ret = nn_act_Initialize(); + // ASSERT_INTEGER(ret, 1, "Initializing account library"); + unsigned char slotNumber = nn_act_GetSlotNo(); + unsigned int persistentIdentifier = nn_act_GetPersistentIdEx(slotNumber); + ret = nn_act_Finalize(); + ASSERT_FUNCTION_SUCCEEDED(ret, "nn_act_Finalize"); + + // Send it + ret = sendwait(bss, clientfd, &persistentIdentifier, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (persistent identifier)") + + break; + } + case COMMAND_WRITE_SCREEN: { + char message[100]; + ret = recvwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (write screen seconds)") + int seconds = ((int *) buffer)[0]; + receiveString(bss, clientfd, message, 100); + writeScreen(message, seconds); + + break; + } + case COMMAND_FOLLOW_POINTER: { + ret = recvwait(bss, clientfd, buffer, 8); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (Pointer address and offsets count)") + + // Retrieve the pointer address and amount of offsets + int baseAddress = ((int *) buffer)[0]; + int offsetsCount = ((int *) buffer)[1]; + + // Receive the offsets + ret = recvwait(bss, clientfd, buffer, offsetsCount * 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (offsets)") + int offsets[offsetsCount]; + int offsetIndex = 0; + for (; offsetIndex < offsetsCount; offsetIndex++) { + offsets[offsetIndex] = ((int *) buffer)[offsetIndex]; + } + + int destinationAddress = baseAddress; + if (isValidDataAddress(destinationAddress)) { + // Apply pointer offsets + for (offsetIndex = 0; offsetIndex < offsetsCount; offsetIndex++) { + int pointerValue = *(int *) destinationAddress; + int offset = offsets[offsetIndex]; + destinationAddress = pointerValue + offset; + + // Validate the pointer address + bool isValidDestinationAddress = isValidDataAddress(destinationAddress); + + // Bail out if invalid + if (!isValidDestinationAddress) { + destinationAddress = -1; + + break; + } + } + } else { + destinationAddress = -1; + } + + // Return the destination address + ((int *) buffer)[0] = destinationAddress; + ret = sendwait(bss, clientfd, buffer, 4); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (destination address)") + + break; + } + case COMMAND_SERVER_STATUS: { + ret = sendbyte(bss, clientfd, 1); + CHECK_ERROR(ret < 0) + break; + } + case COMMAND_RPC: { + long long (*fun)(int, int, int, int, int, int, int, int); + int r3, r4, r5, r6, r7, r8, r9, r10; + long long result; + + ret = recvwait(bss, clientfd, buffer, 4 + 8 * 4); + CHECK_ERROR(ret < 0); + + fun = ((void **) buffer)[0]; + r3 = ((int *) buffer)[1]; + r4 = ((int *) buffer)[2]; + r5 = ((int *) buffer)[3]; + r6 = ((int *) buffer)[4]; + r7 = ((int *) buffer)[5]; + r8 = ((int *) buffer)[6]; + r9 = ((int *) buffer)[7]; + r10 = ((int *) buffer)[8]; + + result = fun(r3, r4, r5, r6, r7, r8, r9, r10); + + ((long long *) buffer)[0] = result; + ret = sendwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0) + + break; + } + case COMMAND_GET_SYMBOL: { + int size = recvbyte(bss, clientfd); + CHECK_ERROR(size < 0) + + ret = recvwait(bss, clientfd, buffer, size); + CHECK_ERROR(ret < 0) + + /* Identify the RPL name and symbol name */ + char *rplname = (char *) &((int *) buffer)[2]; + char *symname = (char *) (&buffer[0] + ((int *) buffer)[1]); + + /* Get the symbol and store it in the buffer */ + unsigned int module_handle, function_address; + OSDynLoad_Acquire(rplname, &module_handle); + + char data = (char) recvbyte(bss, clientfd); + OSDynLoad_FindExport(module_handle, data, symname, &function_address); + + ((int *) buffer)[0] = (int) function_address; + ret = sendwait(bss, clientfd, buffer, 4); + CHECK_ERROR(ret < 0) + + break; + } + case COMMAND_MEMORY_SEARCH: { + // Receive the initial data + ret = recvwait(bss, clientfd, buffer, 4 * 6); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (memory search information)") + int bufferIndex = 0; + int startingAddress = ((int *) buffer)[bufferIndex++]; + int length = ((int *) buffer)[bufferIndex++]; + int kernelRead = ((int *) buffer)[bufferIndex++]; + int resultsLimit = ((int *) buffer)[bufferIndex++]; + int aligned = ((int *) buffer)[bufferIndex++]; + int searchBytesCount = ((int *) buffer)[bufferIndex]; + + // Receive the search bytes + char searchBytes[searchBytesCount]; + ret = recvwait(bss, clientfd, searchBytes, searchBytesCount); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (memory search bytes)") + + int iterationIncrement = aligned ? searchBytesCount : 1; + int searchBytesOccurrences = 0; + + // Perform the bytes search and collect the results + for (int currentAddress = startingAddress; + currentAddress < startingAddress + length; + currentAddress += iterationIncrement) { + + int comparisonResult; + + if (kernelRead) { + comparisonResult = kernelMemoryCompare((void *) currentAddress, searchBytes, searchBytesCount); + } else { + comparisonResult = memcmp((void *) currentAddress, searchBytes, searchBytesCount); + } + if (comparisonResult == 0) { + // Search bytes have been found + ((int *) buffer)[1 + searchBytesOccurrences] = currentAddress; + searchBytesOccurrences++; + + if ((resultsLimit == searchBytesOccurrences) + || (searchBytesOccurrences == ((DATA_BUFFER_SIZE / 4) - 1))) { + // We bail out + break; + } + } + } + + ((int *) buffer)[0] = searchBytesOccurrences * 4; + ret = sendwait(bss, clientfd, buffer, 4 + (searchBytesOccurrences * 4)); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (Sending search bytes occurrences)") + + break; + } + case COMMAND_SERVER_VERSION: { + char versionBuffer[50]; + strcpy(versionBuffer, SERVER_VERSION); + int versionLength = strlen(versionBuffer); + ((int *) buffer)[0] = versionLength; + memcpy(buffer + 4, versionBuffer, versionLength); + + // Send the length and the version string + ret = sendwait(bss, clientfd, buffer, 4 + versionLength); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (server version)"); + + break; + } + case COMMAND_OS_VERSION: { + ((int *) buffer)[0] = (int) OS_FIRMWARE; + ret = sendwait(bss, clientfd, buffer, 4); + CHECK_ERROR(ret < 0) + + break; + } + case COMMAND_RUN_KERNEL_COPY_SERVICE: { + if (!kernelCopyServiceStarted) { + kernelCopyServiceStarted = true; + startKernelCopyService(); + } + + break; + } + default: + reportIllegalCommandByte(ret); + + break; + } + } + + error: + bss->error = ret; + return 0; +} + +static int start(int argc, void *argv) { + int sockfd = -1, clientfd = -1, ret = 0, len; + struct sockaddr_in addr; + struct pygecko_bss_t *bss = argv; + + setup_os_exceptions(); + socket_lib_init(); + + while (1) { + addr.sin_family = AF_INET; + addr.sin_port = 7331; + addr.sin_addr.s_addr = 0; + + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + CHECK_ERROR(sockfd == -1) + + ret = bind(sockfd, (void *) &addr, 16); + CHECK_ERROR(ret < 0) + + ret = listen(sockfd, 20); + CHECK_ERROR(ret < 0) + + while (1) { + len = 16; + clientfd = accept(sockfd, (void *) &addr, &len); + CHECK_ERROR(clientfd == -1) + ret = rungecko(bss, clientfd); + CHECK_ERROR(ret < 0) + socketclose(clientfd); + clientfd = -1; + } + + error: + if (clientfd != -1) + socketclose(clientfd); + if (sockfd != -1) + socketclose(sockfd); + bss->error = ret; + + // Fix the console freezing when e.g. going to the friend list + GX2WaitForVsync(); + } + + return 0; +} + +static int CCThread(int argc, void *argv) { + struct pygecko_bss_t *bss; + + bss = memalign(0x40, sizeof(struct pygecko_bss_t)); + if (bss == 0) + return 0; + memset(bss, 0, sizeof(struct pygecko_bss_t)); + + if (OSCreateThread(&bss->thread, start, 1, bss, (u32) bss->stack + sizeof(bss->stack), sizeof(bss->stack), 0, + 0xc) == 1) { + OSResumeThread(&bss->thread); + } else { + free(bss); + } + + if (CCHandler == 1) { + void (*entrypoint)() = (void *) CODE_HANDLER_INSTALL_ADDRESS; + + while (1) { + usleep(9000); + entrypoint(); + } + } + return 0; +} + +void start_pygecko() { + // Force the debugger to be initialized by default + // writeInt((unsigned int) (OSIsDebuggerInitialized + 0x1C), 0x38000001); // li r3, 1 + + unsigned int stack = (unsigned int) memalign(0x40, 0x100); + ASSERT_ALLOCATED(stack, "TCP Gecko stack") + stack += 0x100; + void *thread = memalign(0x40, 0x1000); + ASSERT_ALLOCATED(thread, "TCP Gecko thread") + + int status = OSCreateThread(thread, CCThread, 1, + NULL, (u32) stack + sizeof(stack), + sizeof(stack), 0, + OS_THREAD_ATTR_AFFINITY_CORE1 | OS_THREAD_ATTR_PINNED_AFFINITY | OS_THREAD_ATTR_DETACH); + ASSERT_INTEGER(status, 1, "Creating TCP Gecko thread") + // OSSetThreadName(thread, "TCP Gecko"); + OSResumeThread(thread); +} \ No newline at end of file diff --git a/src/pygecko.h b/src/pygecko.h new file mode 100644 index 0000000..b4e6c55 --- /dev/null +++ b/src/pygecko.h @@ -0,0 +1,19 @@ +#ifndef _PYGECKO_H_ +#define _PYGECKO_H_ + +#include "common/types.h" +#include "dynamic_libs/os_functions.h" + +/* Main */ +#ifdef __cplusplus +extern "C" { +#endif + +//! C wrapper for our C++ functions +void start_pygecko(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/system/exception_handler.c b/src/system/exception_handler.c new file mode 100644 index 0000000..7dbd6d6 --- /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); +} \ No newline at end of file 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..e560cc7 --- /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); +} \ No newline at end of file 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..49ab1ef --- /dev/null +++ b/src/utils/logger.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include "common/common.h" +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "logger.h" + +static int log_socket = 0; +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); +} + diff --git a/src/utils/logger.h b/src/utils/logger.h new file mode 100644 index 0000000..32fab70 --- /dev/null +++ b/src/utils/logger.h @@ -0,0 +1,89 @@ +#ifndef __LOGGER_H_ +#define __LOGGER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Communication bytes with the server */ +// Com +#define BYTE_NORMAL 0xff +#define BYTE_SPECIAL 0xfe +#define BYTE_OK 0xfd +#define BYTE_PING 0xfc +#define BYTE_LOG_STR 0xfb +#define BYTE_DISCONNECT 0xfa + +// SD +#define BYTE_MOUNT_SD 0xe0 +#define BYTE_MOUNT_SD_OK 0xe1 +#define BYTE_MOUNT_SD_BAD 0xe2 + +// Replacement +#define BYTE_STAT 0x00 +#define BYTE_STAT_ASYNC 0x01 +#define BYTE_OPEN_FILE 0x02 +#define BYTE_OPEN_FILE_ASYNC 0x03 +#define BYTE_OPEN_DIR 0x04 +#define BYTE_OPEN_DIR_ASYNC 0x05 +#define BYTE_CHANGE_DIR 0x06 +#define BYTE_CHANGE_DIR_ASYNC 0x07 +#define BYTE_MAKE_DIR 0x08 +#define BYTE_MAKE_DIR_ASYNC 0x09 +#define BYTE_RENAME 0x0A +#define BYTE_RENAME_ASYNC 0x0B +#define BYTE_REMOVE 0x0C +#define BYTE_REMOVE_ASYNC 0x0D + +// Log +#define BYTE_CLOSE_FILE 0x40 +#define BYTE_CLOSE_FILE_ASYNC 0x41 +#define BYTE_CLOSE_DIR 0x42 +#define BYTE_CLOSE_DIR_ASYNC 0x43 +#define BYTE_FLUSH_FILE 0x44 +#define BYTE_GET_ERROR_CODE_FOR_VIEWER 0x45 +#define BYTE_GET_LAST_ERROR 0x46 +#define BYTE_GET_MOUNT_SOURCE 0x47 +#define BYTE_GET_MOUNT_SOURCE_NEXT 0x48 +#define BYTE_GET_POS_FILE 0x49 +#define BYTE_SET_POS_FILE 0x4A +#define BYTE_GET_STAT_FILE 0x4B +#define BYTE_EOF 0x4C +#define BYTE_READ_FILE 0x4D +#define BYTE_READ_FILE_ASYNC 0x4E +#define BYTE_READ_FILE_WITH_POS 0x4F +#define BYTE_READ_DIR 0x50 +#define BYTE_READ_DIR_ASYNC 0x51 +#define BYTE_GET_CWD 0x52 +#define BYTE_SET_STATE_CHG_NOTIF 0x53 +#define BYTE_TRUNCATE_FILE 0x54 +#define BYTE_WRITE_FILE 0x55 +#define BYTE_WRITE_FILE_WITH_POS 0x56 + +#define BYTE_SAVE_INIT 0x57 +#define BYTE_SAVE_SHUTDOWN 0x58 +#define BYTE_SAVE_INIT_SAVE_DIR 0x59 +#define BYTE_SAVE_FLUSH_QUOTA 0x5A +#define BYTE_SAVE_OPEN_DIR 0x5B +#define BYTE_SAVE_REMOVE 0x5C + +#define BYTE_CREATE_THREAD 0x60 + +#define LOADIINE_LOGGER_IP "192.168.178.3" + +int logger_connect(int *socket); +void logger_disconnect(int socket); +void log_string(int sock, const char* str, char byte); +void log_byte(int sock, char byte); + +void log_init(const char * ip); +void log_deinit(void); +void log_print(const char *str); +void log_printf(const char *format, ...); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/utils/net.c b/src/utils/net.c new file mode 100644 index 0000000..800fdc6 --- /dev/null +++ b/src/utils/net.c @@ -0,0 +1,561 @@ +#include +#include +#include "common/common.h" +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "net.h" + +static volatile int iLock = 0; + +#define CHECK_ERROR(cond) if (cond) { goto error; } + +void cafiine_connect(int *psock,u32 server_ip) { + struct sockaddr_in addr; + int sock, ret; + + socket_lib_init(); + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + CHECK_ERROR(sock == -1); + + addr.sin_family = AF_INET; + addr.sin_port = 7332; + addr.sin_addr.s_addr = server_ip; + + ret = connect(sock, (void *)&addr, sizeof(addr)); + CHECK_ERROR(ret < 0); + ret = cafiine_handshake(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret == BYTE_NORMAL); + + *psock = sock; + return; +error: + if (sock != -1) + socketclose(sock); + *psock = -1; + return; +} + +void cafiine_disconnect(int sock) { + CHECK_ERROR(sock == -1); + socketclose(sock); +error: + return; +} + +int cafiine_handshake(int sock) { + int ret; + + unsigned char buffer[16]; + + u64 title_id = OSGetTitleID(); + memcpy(buffer, &title_id, 16); + + ret = sendwait(sock, buffer, sizeof(buffer)); + CHECK_ERROR(ret < 0); + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + return ret; +error: + return ret; +} + +int getMode(int sock,int * result) +{ + while (iLock) + usleep(5000); + iLock = 1; + int ret = 0; + CHECK_ERROR(sock == -1); + + // create and send buffer with : [cmd id][fd][size][buffer data ...] + { + ret = sendbyte(sock, BYTE_G_MODE); + + // wait reply + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + if(ret == BYTE_MODE_D) *result = BYTE_MODE_D; + if(ret == BYTE_MODE_I) *result = BYTE_MODE_I; + ret = 1; + } +error: + iLock = 0; + return ret; +} + +int cafiine_fsetpos(int sock, int *result, int fd, int set) { + while (iLock) + usleep(5000); + iLock = 1; + + CHECK_ERROR(sock == -1); + + int ret; + char buffer[1 + 8]; + buffer[0] = BYTE_SETPOS; + *(int *)(buffer + 1) = fd; + *(int *)(buffer + 5) = set; + ret = sendwait(sock, buffer, 1 + 8); + CHECK_ERROR(ret < 0); + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret == BYTE_NORMAL); + ret = recvwait(sock, result, 4); + CHECK_ERROR(ret < 0); + + iLock = 0; + return 0; +error: + iLock = 0; + return -1; +} + +int cafiine_send_handle(int sock, const char *path, int handle) +{ + while (iLock) + usleep(5000); + iLock = 1; + + CHECK_ERROR(sock == -1); + + // create and send buffer with : [cmd id][handle][path length][path data ...] + { + int ret; + int len_path = 0; + while (path[len_path++]); + char buffer[1 + 4 + 4 + len_path]; + + buffer[0] = BYTE_HANDLE; + *(int *)(buffer + 1) = handle; + *(int *)(buffer + 5) = len_path; + for (ret = 0; ret < len_path; ret++) + buffer[9 + ret] = path[ret]; + + // send buffer, wait for reply + ret = sendwait(sock, buffer, 1 + 4 + 4 + len_path); + CHECK_ERROR(ret < 0); + + // wait reply + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret == BYTE_SPECIAL); + if(ret == BYTE_REQUEST){ + ret = 1; + }else{ + ret = 2; + } + // wait reply + int special_ret = recvbyte(sock); + CHECK_ERROR(special_ret < 0); + CHECK_ERROR(special_ret != BYTE_SPECIAL); + iLock = 0; + return ret; + } + +error: + iLock = 0; + return -1; +} + +int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int *handle) { + while (iLock) + usleep(5000); + iLock = 1; + + int final_result = -1; + CHECK_ERROR(sock == -1); + + int ret; + int len_path = 0; + while (path[len_path++]); + int len_mode = 0; + while (mode[len_mode++]); + + // + { + char buffer[1 + 8 + len_path + len_mode]; + buffer[0] = BYTE_OPEN; + *(int *)(buffer + 1) = len_path; + *(int *)(buffer + 5) = len_mode; + for (ret = 0; ret < len_path; ret++) + buffer[9 + ret] = path[ret]; + for (ret = 0; ret < len_mode; ret++) + buffer[9 + len_path + ret] = mode[ret]; + + ret = sendwait(sock, buffer, 1 + 8 + len_path + len_mode); + CHECK_ERROR(ret < 0); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret == BYTE_NORMAL); + + ret = recvwait(sock, result, 4); + CHECK_ERROR(ret < 0); + ret = recvwait(sock, handle, 4); + CHECK_ERROR(ret < 0); + } + final_result = 0; + + +error: + iLock = 0; + return final_result; +} + +void cafiine_send_file(int sock, char *file, int size, int fd) { + while (iLock) + usleep(5000); + iLock = 1; + + CHECK_ERROR(sock == -1); + + int ret; + + // create and send buffer with : [cmd id][fd][size][buffer data ...] + { + char buffer[1 + 4 + 4 + size]; + + buffer[0] = BYTE_DUMP; + *(int *)(buffer + 1) = fd; + *(int *)(buffer + 5) = size; + for (ret = 0; ret < size; ret++) + buffer[9 + ret] = file[ret]; + + // send buffer, wait for reply + ret = sendwait(sock, buffer, 1 + 4 + 4 + size); + CHECK_ERROR(ret < 0); + // wait reply + ret = recvbyte(sock); + CHECK_ERROR(ret != BYTE_SPECIAL); + } + +error: + iLock = 0; + return; +} + +int cafiine_fread(int sock, int *result, void *ptr, int size, int fd) { + while (iLock) + usleep(5000); + iLock = 1; + + CHECK_ERROR(sock == -1); + + int ret; + char buffer[1 + 8]; + buffer[0] = BYTE_READ; + *(int *)(buffer + 1) = size; + *(int *)(buffer + 5) = fd; + ret = sendwait(sock, buffer, 1 + 8); + CHECK_ERROR(ret < 0); + ret = recvbyte(sock); + CHECK_ERROR(ret == BYTE_NORMAL); + int sz; + ret = recvwait(sock, &sz, 4); + CHECK_ERROR(ret < 0); + ret = recvwaitlen(sock, ptr, sz); + *result = sz - ret; + ret = sendbyte(sock, BYTE_OK); + CHECK_ERROR(ret < 0); + + iLock = 0; + return 0; +error: + iLock = 0; + return -1; +} + +int cafiine_fclose(int sock, int *result, int fd,int dumpclose) { + while (iLock) + usleep(5000); + iLock = 1; + + CHECK_ERROR(sock == -1); + + int ret; + char buffer[1 + 4]; + buffer[0] = BYTE_CLOSE; + if(dumpclose)buffer[0] = BYTE_CLOSE_DUMP; + *(int *)(buffer + 1) = fd; + ret = sendwait(sock, buffer, 1 + 4); + CHECK_ERROR(ret < 0); + ret = recvbyte(sock); + CHECK_ERROR(ret == BYTE_NORMAL); + ret = recvwait(sock, result, 4); + CHECK_ERROR(ret < 0); + + iLock = 0; + return 0; +error: + iLock = 0; + return -1; +} + +int saviine_start_injection(int sock, long persistentID,int * mask){ + while (iLock) + usleep(5000); + iLock = 1; + + int result = 0; + CHECK_ERROR(sock == -1); + int ret; + { + char buffer[1+4]; + + buffer[0] = BYTE_INJECTSTART; + *(long *)(buffer + 1) = persistentID; + ret = sendwait(sock, buffer, 1 + 4); + CHECK_ERROR(ret < 0); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + + ret = recvwait(sock, mask, 4); + CHECK_ERROR(ret < 0); + CHECK_ERROR((*mask & MASK_NORMAL) != MASK_NORMAL); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + result = 1; + } +error: + iLock = 0; + return result; +} + +int saviine_end_injection(int sock){ + while (iLock) + usleep(5000); + iLock = 1; + + int result = 0; + CHECK_ERROR(sock == -1); + int ret; + { + ret = sendbyte(sock, BYTE_INJECTEND); + CHECK_ERROR(ret < 0); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_OK); + result = 1; + } +error: + iLock = 0; + return result; +} + +int saviine_start_dump(int sock, long persistentID,int * mask){ + while (iLock) + usleep(5000); + iLock = 1; + + int result = 0; + CHECK_ERROR(sock == -1); + int ret; + { + char buffer[1+4]; + + buffer[0] = BYTE_DUMPSTART; + *(long *)(buffer + 1) = persistentID; + ret = sendwait(sock, buffer, 1 + 4); + CHECK_ERROR(ret < 0); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + + ret = recvwait(sock, mask, 4); + CHECK_ERROR(ret < 0); + CHECK_ERROR((*mask & MASK_NORMAL) != MASK_NORMAL); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + result = 1; + } +error: + iLock = 0; + return result; +} + +int saviine_end_dump(int sock){ + while (iLock) + usleep(5000); + iLock = 1; + + int result = 0; + CHECK_ERROR(sock == -1); + int ret; + { + ret = sendbyte(sock, BYTE_DUMPEND); + CHECK_ERROR(ret < 0); + + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_OK); + result = 1; + } +error: + iLock = 0; + return result; +} + +int saviine_readdir(int sock, char * path,char * resultname, int * resulttype, int * filesize){ + while (iLock) + usleep(5000); + iLock = 1; + + int result = 0; + CHECK_ERROR(sock == -1); + int ret; + // create and send buffer with : [cmd id][len_path][path][filesize] + { + int size = 0; + while (path[size++]); + char buffer[1+4+size]; + + buffer[0] = BYTE_READ_DIR; + *(int *)(buffer + 1) = size; + for (ret = 0; ret < size; ret++) + buffer[5 + ret] = path[ret]; + + // send buffer, wait for reply + ret = sendwait(sock, buffer, 1+4+size); + CHECK_ERROR(ret < 0); + + // wait reply + ret = recvbyte(sock); + CHECK_ERROR(ret != BYTE_OK); + + ret = recvbyte(sock); + CHECK_ERROR(ret != BYTE_FILE && ret != BYTE_FOLDER); + *resulttype = ret; + size = 0; + ret = recvwait(sock, &size, 4); + CHECK_ERROR(ret < 0); + + ret = recvwait(sock, resultname, size+1); + CHECK_ERROR(ret < 0); + + size = 0; + ret = recvwait(sock, &size, 4); + CHECK_ERROR(ret < 0); + *filesize = size; + ret = recvbyte(sock); + CHECK_ERROR(ret < 0); + CHECK_ERROR(ret != BYTE_SPECIAL); + result = 1; + + } +error: + iLock = 0; + return result; +} + +void cafiine_send_ping(int sock, int val1, int val2) { + while (iLock) + usleep(5000); + iLock = 1; + + int ret; + char buffer[1 + 4 + 4]; + buffer[0] = BYTE_PING; + *(int *)(buffer + 1) = val1; + *(int *)(buffer + 5) = val2; + + ret = sendwait(sock, buffer, 1 + 4 + 4); + CHECK_ERROR(ret < 0); + + error: + iLock = 0; + return; +} + + int recvwait(int sock, void *buffer, int len) { + int ret; + while (len > 0) { + ret = recv(sock, buffer, len, 0); + CHECK_ERROR(ret < 0); + len -= ret; + buffer += ret; + } + return 0; +error: + return ret; +} + + int recvwaitlen(int sock, void *buffer, int len) { + int ret; + while (len > 0) { + ret = recv(sock, buffer, len, 0); + CHECK_ERROR(ret < 0); + len -= ret; + buffer += ret; + } + return 0; +error: + return len; +} + + + int recvbyte(int sock) { + unsigned char buffer[1]; + int ret; + + ret = recvwait(sock, buffer, 1); + if (ret < 0) return ret; + return buffer[0]; +} + + int sendwait(int sock, const void *buffer, int len) { + int ret; + while (len > 0) { + ret = send(sock, buffer, len, 0); + CHECK_ERROR(ret < 0); + len -= ret; + buffer += ret; + } + return 0; +error: + return ret; +} + +void log_string(int sock, const char* str, char flag_byte) { + if(sock == -1) { + return; + } + while (iLock) + usleep(5000); + iLock = 1; + + int i; + int len_str = 0; + while (str[len_str++]); + + // + { + char buffer[1 + 4 + len_str]; + buffer[0] = flag_byte; + *(int *)(buffer + 1) = len_str; + for (i = 0; i < len_str; i++) + buffer[5 + i] = str[i]; + + buffer[5 + i] = 0; + + sendwait(sock, buffer, 1 + 4 + len_str); + } + + iLock = 0; +} + +int sendbyte(int sock, unsigned char byte) { + unsigned char buffer[1]; + + buffer[0] = byte; + return sendwait(sock, buffer, 1); +} diff --git a/src/utils/net.h b/src/utils/net.h new file mode 100644 index 0000000..75ccb8b --- /dev/null +++ b/src/utils/net.h @@ -0,0 +1,63 @@ +#ifndef NETWORK_H_ +#define NETWORK_H_ + + +#define BYTE_NORMAL 0xff +#define BYTE_SPECIAL 0xfe +#define BYTE_OPEN 0x00 +#define BYTE_READ 0x01 +#define BYTE_CLOSE 0x02 +#define BYTE_OK 0x03 +#define BYTE_SETPOS 0x04 +#define BYTE_STATFILE 0x05 +#define BYTE_EOF 0x06 +#define BYTE_GETPOS 0x07 +#define BYTE_REQUEST 0x08 +#define BYTE_REQUEST_SLOW 0x09 +#define BYTE_HANDLE 0x0A +#define BYTE_DUMP 0x0B +#define BYTE_PING 0x0C +#define BYTE_G_MODE 0x0D +#define BYTE_MODE_D 0x0E +#define BYTE_MODE_I 0x0F +#define BYTE_CLOSE_DUMP 0x10 +#define BYTE_LOG_STR 0xfb +#define BYTE_FILE 0xC0 +#define BYTE_FOLDER 0xC1 +#define BYTE_READ_DIR 0xCC +#define BYTE_INJECTSTART 0x40 +#define BYTE_INJECTEND 0x41 +#define BYTE_DUMPSTART 0x42 +#define BYTE_DUMPEND 0x43 +#define BYTE_END 0xfd + +#define MASK_NORMAL 0x8000 +#define MASK_USER 0x0100 +#define MASK_COMMON 0x0200 +#define MASK_COMMON_CLEAN 0x0400 + +void cafiine_connect(int *psock,u32 ip); +void cafiine_disconnect(int sock); +int cafiine_handshake(int sock); +int getMode(int sock,int * result); +int cafiine_fsetpos(int sock, int *result, int fd, int set); +int cafiine_send_handle(int sock, const char *path, int handle); +int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int *handle); +void cafiine_send_file(int sock, char *file, int size, int fd); +int cafiine_fread(int sock, int *result, void *ptr, int size, int fd); +int cafiine_fclose(int sock, int *result, int fd,int dumpclose); +int saviine_start_injection(int sock, long persistentID,int * mask); +int saviine_end_injection(int sock); +int saviine_start_dump(int sock, long persistentID,int * mask); +int saviine_end_dump(int sock); +int saviine_readdir(int sock, char * path,char * resultname, int * resulttype, int * filesize); +void cafiine_send_ping(int sock, int val1, int val2); + int recvwait(int sock, void *buffer, int len); + int recvwaitlen(int sock, void *buffer, int len); + int recvbyte(int sock); + int sendwait(int sock, const void *buffer, int len); +void log_string(int sock, const char* str, char flag_byte); +int sendbyte(int sock, unsigned char byte); + + +#endif diff --git a/src/utils/utils.c b/src/utils/utils.c new file mode 100644 index 0000000..09123fe --- /dev/null +++ b/src/utils/utils.c @@ -0,0 +1,27 @@ + + +void m_DCFlushRange(unsigned int startAddr, unsigned int size) +{ + register unsigned int addr = startAddr & ~0x1F; + register unsigned int end_addr = startAddr + size; + + while(addr < end_addr) + { + asm volatile("dcbf 0, %0" : : "r"(addr)); + addr += 0x20; + } + asm volatile("sync; eieio"); +} + + +void m_DCInvalidateRange(unsigned int startAddr, unsigned int size) +{ + register unsigned int addr = startAddr & ~0x1F; + register unsigned int end_addr = startAddr + size; + + while(addr < end_addr) + { + asm volatile("dcbi 0, %0" : : "r"(addr)); + addr += 0x20; + } +} diff --git a/src/utils/utils.h b/src/utils/utils.h new file mode 100644 index 0000000..b5d5e7d --- /dev/null +++ b/src/utils/utils.h @@ -0,0 +1,49 @@ +#ifndef __UTILS_H_ +#define __UTILS_H_ + +#include +#include "../common/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void m_DCInvalidateRange(unsigned int startAddr, unsigned int size); + +#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/tcpgecko.elf b/tcpgecko.elf new file mode 100644 index 0000000..e02effb Binary files /dev/null and b/tcpgecko.elf differ