From 4f69a6bc52ddc98f67bfe720a5d3f3f9487c8683 Mon Sep 17 00:00:00 2001 From: wj444 Date: Sun, 31 Jul 2016 19:37:57 +0200 Subject: [PATCH] Initial commit --- .gitattributes | 17 - .gitignore | 2 + LICENSE | 674 ++++++++++ Makefile | 218 ++++ README.md | 2 + codehandler.bin | Bin 0 -> 13196 bytes meta/icon.png | Bin 0 -> 37763 bytes meta/meta.xml | 14 + src/common/common.h | 58 + src/common/fs_defs.h | 67 + src/common/kernel_defs.h | 116 ++ src/common/loader_defs.h | 40 + src/common/os_defs.h | 25 + src/common/types.h | 7 + src/dynamic_libs/aoc_functions.c | 49 + src/dynamic_libs/aoc_functions.h | 46 + src/dynamic_libs/ax_functions.c | 74 ++ src/dynamic_libs/ax_functions.h | 59 + src/dynamic_libs/fs_functions.c | 126 ++ src/dynamic_libs/fs_functions.h | 90 ++ src/dynamic_libs/gx2_functions.c | 162 +++ src/dynamic_libs/gx2_functions.h | 205 +++ src/dynamic_libs/gx2_types.h | 699 ++++++++++ src/dynamic_libs/os_functions.c | 306 +++++ src/dynamic_libs/os_functions.h | 162 +++ src/dynamic_libs/padscore_functions.c | 50 + src/dynamic_libs/padscore_functions.h | 122 ++ src/dynamic_libs/socket_functions.c | 84 ++ src/dynamic_libs/socket_functions.h | 96 ++ src/dynamic_libs/sys_functions.c | 42 + src/dynamic_libs/sys_functions.h | 43 + src/dynamic_libs/vpad_functions.c | 39 + src/dynamic_libs/vpad_functions.h | 102 ++ src/entry.c | 43 + src/fs/CFile.cpp | 197 +++ src/fs/CFile.hpp | 57 + src/fs/DirList.cpp | 227 ++++ src/fs/DirList.h | 95 ++ src/fs/fs_utils.c | 182 +++ src/fs/fs_utils.h | 23 + src/fs/sd_fat_devoptab.c | 1019 +++++++++++++++ src/fs/sd_fat_devoptab.h | 38 + src/game/memory_area_table.c | 1729 +++++++++++++++++++++++++ src/game/memory_area_table.h | 40 + src/game/rpx_rpl_table.c | 210 +++ src/game/rpx_rpl_table.h | 37 + src/include/Put titledumper here.txt | 0 src/include/titledumper.exe | Bin 0 -> 40819 bytes src/kernel/kernel_functions.c | 81 ++ src/kernel/kernel_functions.h | 22 + src/kernel/kernel_hooks.S | 174 +++ src/kernel/syscalls.c | 255 ++++ src/kernel/syscalls.h | 25 + src/kernel/syscalls_asm.S | 19 + src/link.ld | 43 + src/main.c | 242 ++++ src/main.h | 22 + src/patcher/fs_logger.c | 154 +++ src/patcher/fs_logger.h | 75 ++ src/patcher/function_hooks.c | 141 ++ src/patcher/function_hooks.h | 15 + src/pygecko.c | 431 ++++++ src/pygecko.h | 19 + src/system/exception_handler.c | 169 +++ src/system/exception_handler.h | 14 + src/system/memory.c | 198 +++ src/system/memory.h | 42 + src/utils/StringTools.cpp | 207 +++ src/utils/StringTools.h | 78 ++ src/utils/logger.c | 88 ++ src/utils/logger.h | 89 ++ src/utils/net.c | 561 ++++++++ src/utils/net.h | 63 + src/utils/utils.c | 27 + src/utils/utils.h | 49 + 75 files changed, 10979 insertions(+), 17 deletions(-) delete mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 codehandler.bin create mode 100644 meta/icon.png create mode 100644 meta/meta.xml create mode 100644 src/common/common.h create mode 100644 src/common/fs_defs.h create mode 100644 src/common/kernel_defs.h create mode 100644 src/common/loader_defs.h create mode 100644 src/common/os_defs.h create mode 100644 src/common/types.h create mode 100644 src/dynamic_libs/aoc_functions.c create mode 100644 src/dynamic_libs/aoc_functions.h create mode 100644 src/dynamic_libs/ax_functions.c create mode 100644 src/dynamic_libs/ax_functions.h create mode 100644 src/dynamic_libs/fs_functions.c create mode 100644 src/dynamic_libs/fs_functions.h create mode 100644 src/dynamic_libs/gx2_functions.c create mode 100644 src/dynamic_libs/gx2_functions.h create mode 100644 src/dynamic_libs/gx2_types.h create mode 100644 src/dynamic_libs/os_functions.c create mode 100644 src/dynamic_libs/os_functions.h create mode 100644 src/dynamic_libs/padscore_functions.c create mode 100644 src/dynamic_libs/padscore_functions.h create mode 100644 src/dynamic_libs/socket_functions.c create mode 100644 src/dynamic_libs/socket_functions.h create mode 100644 src/dynamic_libs/sys_functions.c create mode 100644 src/dynamic_libs/sys_functions.h create mode 100644 src/dynamic_libs/vpad_functions.c create mode 100644 src/dynamic_libs/vpad_functions.h create mode 100644 src/entry.c create mode 100644 src/fs/CFile.cpp create mode 100644 src/fs/CFile.hpp create mode 100644 src/fs/DirList.cpp create mode 100644 src/fs/DirList.h create mode 100644 src/fs/fs_utils.c create mode 100644 src/fs/fs_utils.h create mode 100644 src/fs/sd_fat_devoptab.c create mode 100644 src/fs/sd_fat_devoptab.h create mode 100644 src/game/memory_area_table.c create mode 100644 src/game/memory_area_table.h create mode 100644 src/game/rpx_rpl_table.c create mode 100644 src/game/rpx_rpl_table.h create mode 100644 src/include/Put titledumper here.txt create mode 100644 src/include/titledumper.exe create mode 100644 src/kernel/kernel_functions.c create mode 100644 src/kernel/kernel_functions.h create mode 100644 src/kernel/kernel_hooks.S create mode 100644 src/kernel/syscalls.c create mode 100644 src/kernel/syscalls.h create mode 100644 src/kernel/syscalls_asm.S create mode 100644 src/link.ld create mode 100644 src/main.c create mode 100644 src/main.h create mode 100644 src/patcher/fs_logger.c create mode 100644 src/patcher/fs_logger.h create mode 100644 src/patcher/function_hooks.c create mode 100644 src/patcher/function_hooks.h create mode 100644 src/pygecko.c create mode 100644 src/pygecko.h create mode 100644 src/system/exception_handler.c create mode 100644 src/system/exception_handler.h create mode 100644 src/system/memory.c create mode 100644 src/system/memory.h create mode 100644 src/utils/StringTools.cpp create mode 100644 src/utils/StringTools.h create mode 100644 src/utils/logger.c create mode 100644 src/utils/logger.h create mode 100644 src/utils/net.c create mode 100644 src/utils/net.h create mode 100644 src/utils/utils.c create mode 100644 src/utils/utils.h diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index bdb0cab..0000000 --- a/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1fda396 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/build +/*.elf \ No newline at end of file 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..2a80dd4 --- /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 := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CURDIR) \ + $(DEVKITPPC)/lib \ + $(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2 + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- +export PROJECTDIR := $(CURDIR) +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +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..3f7b615 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# TCPGecko +TCPGecko Installer diff --git a/codehandler.bin b/codehandler.bin new file mode 100644 index 0000000000000000000000000000000000000000..45c0dfce0c21259f0e75f1f4563db1fc027abe07 GIT binary patch literal 13196 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 Y|Nr7X6r3r;9`PdnkIMy<&;H{5A2rqz3;+NC literal 0 HcmV?d00001 diff --git a/meta/icon.png b/meta/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..add83d8cc0dc6d51c0bd9e81d5682d2721344eb3 GIT binary patch literal 37763 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 literal 0 HcmV?d00001 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..46a8f46 --- /dev/null +++ b/src/common/common.h @@ -0,0 +1,58 @@ +#ifndef COMMON_H +#define COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "os_defs.h" + +#define INSTALL_ADDR 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 +// 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..702e9ef --- /dev/null +++ b/src/common/fs_defs.h @@ -0,0 +1,67 @@ +#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 + +#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..48a4c8f --- /dev/null +++ b/src/common/os_defs.h @@ -0,0 +1,25 @@ +#ifndef __OS_DEFS_H_ +#define __OS_DEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _OsSpecifics +{ + unsigned int addr_OSDynLoad_Acquire; + unsigned int addr_OSDynLoad_FindExport; + unsigned int addr_OSTitle_main_entry; + + unsigned int addr_KernSyscallTbl1; + unsigned int addr_KernSyscallTbl2; + unsigned int addr_KernSyscallTbl3; + unsigned int addr_KernSyscallTbl4; + unsigned int addr_KernSyscallTbl5; +} OsSpecifics; + +#ifdef __cplusplus +} +#endif + +#endif // __OS_DEFS_H_ diff --git a/src/common/types.h b/src/common/types.h new file mode 100644 index 0000000..3435e56 --- /dev/null +++ b/src/common/types.h @@ -0,0 +1,7 @@ +#ifndef TYPES_H +#define TYPES_H + +#include + +#endif /* TYPES_H */ + diff --git a/src/dynamic_libs/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..af8856e --- /dev/null +++ b/src/dynamic_libs/fs_functions.c @@ -0,0 +1,126 @@ +/**************************************************************************** + * 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..6721a45 --- /dev/null +++ b/src/dynamic_libs/fs_functions.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __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..00ac52f --- /dev/null +++ b/src/dynamic_libs/os_functions.c @@ -0,0 +1,306 @@ +/**************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "common/common.h" +#include "os_functions.h" + +unsigned int coreinit_handle __attribute__((section(".data"))) = 0; + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Lib handle functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, OSDynLoad_Acquire, const char* rpl, u32 *handle); +EXPORT_DECL(int, OSDynLoad_FindExport, u32 handle, int isdata, const char *symbol, void *address); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Security functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EXPORT_DECL(int, OSGetSecurityLevel, void); +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, 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(int, 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, __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); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! 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); +} + +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, __os_snprintf); + OS_FIND_EXPORT(coreinit_handle, __gh_errno_ptr); + + OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &__Exit); + + OS_FIND_EXPORT(coreinit_handle, OSScreenInit); + OS_FIND_EXPORT(coreinit_handle, 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, 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..11af74d --- /dev/null +++ b/src/dynamic_libs/os_functions.h @@ -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. + ***************************************************************************/ +#ifndef __OS_FUNCTIONS_H_ +#define __OS_FUNCTIONS_H_ + +#include +#include "common/os_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BUS_SPEED 248625000 +#define SECS_TO_TICKS(sec) (((unsigned long long)(sec)) * (BUS_SPEED/4)) +#define MILLISECS_TO_TICKS(msec) (SECS_TO_TICKS(msec) / 1000) +#define MICROSECS_TO_TICKS(usec) (SECS_TO_TICKS(usec) / 1000000) + +#define usleep(usecs) OSSleepTicks(MICROSECS_TO_TICKS(usecs)) +#define sleep(secs) OSSleepTicks(SECS_TO_TICKS(secs)) + +#define FLUSH_DATA_BLOCK(addr) asm volatile("dcbf 0, %0; sync" : : "r"(((addr) & ~31))) +#define INVAL_DATA_BLOCK(addr) asm volatile("dcbi 0, %0; sync" : : "r"(((addr) & ~31))) + +#define EXPORT_DECL(res, func, ...) res (* func)(__VA_ARGS__) __attribute__((section(".data"))) = 0; +#define EXPORT_VAR(type, var) type var __attribute__((section(".data"))); + + +#define EXPORT_FUNC_WRITE(func, val) *(u32*)(((u32)&func) + 0) = (u32)val + +#define OS_FIND_EXPORT(handle, func) funcPointer = 0; \ + OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ + if(!funcPointer) \ + OSFatal("Function " # func " is NULL"); \ + EXPORT_FUNC_WRITE(func, funcPointer); + +#define OS_FIND_EXPORT_EX(handle, func, func_p) \ + funcPointer = 0; \ + OSDynLoad_FindExport(handle, 0, # func, &funcPointer); \ + if(!funcPointer) \ + OSFatal("Function " # func " is NULL"); \ + EXPORT_FUNC_WRITE(func_p, funcPointer); + +#define OS_MUTEX_SIZE 44 + +/* Handle for coreinit */ +extern unsigned int coreinit_handle; +void InitOSFunctionPointers(void); +void InitAcquireOS(void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Lib handle functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* OSDynLoad_Acquire)(const char* rpl, u32 *handle); +extern int (* OSDynLoad_FindExport)(u32 handle, int isdata, const char *symbol, void *address); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Security functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* OSGetSecurityLevel)(void); +extern void (* __OSSetCoreTrace)(int core); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Thread functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* OSCreateThread)(void *thread, s32 (*callback)(s32, void*), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); +extern int (* OSResumeThread)(void *thread); +extern int (* OSSleepThread)(void *thread); +extern int (* OSWakeupThread)(void *thread); +extern int (* 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 (* __os_snprintf)(char* s, int n, const char * format, ...); +extern int * (* __gh_errno_ptr)(void); + +extern void (*OSScreenInit)(void); +extern unsigned int (*OSScreenGetBufferSizeEx)(unsigned int bufferNum); +extern int (*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr); +extern int (*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp); +extern int (*OSScreenFlipBuffersEx)(unsigned int bufferNum); +extern int (*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer); +extern int (*OSScreenEnableEx)(unsigned int bufferNum, int enable); + +typedef unsigned char (*exception_callback)(void * interruptedContext); +extern void (* OSSetExceptionCallback)(u8 exceptionType, exception_callback newCallback); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! MCP functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* MCP_Open)(void); +extern int (* MCP_Close)(int handle); +extern int (* MCP_GetOwnTitleInfo)(int handle, void * data); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! LOADER functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (* LiWaitIopComplete)(int unknown_syscall_arg_r3, int * remaining_bytes); +extern int (* LiWaitIopCompleteWithInterrupts)(int unknown_syscall_arg_r3, int * remaining_bytes); +extern void (* addr_LiWaitOneChunk)(void); +extern void (* addr_sgIsLoadingBuffer)(void); +extern void (* addr_gDynloadInitialized)(void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Kernel function addresses +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern void (* addr_PrepareTitle_hook)(void); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Other function addresses +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern void (*DCInvalidateRange)(void *buffer, uint32_t length); + +#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..40960b8 --- /dev/null +++ b/src/entry.c @@ -0,0 +1,43 @@ +#include +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/fs_functions.h" +#include "dynamic_libs/gx2_functions.h" +#include "dynamic_libs/sys_functions.h" +#include "dynamic_libs/vpad_functions.h" +#include "dynamic_libs/padscore_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "dynamic_libs/ax_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/exception_handler.h" +#include "system/memory.h" +#include "utils/logger.h" +#include "utils/utils.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(); +} 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..d889efc --- /dev/null +++ b/src/fs/DirList.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** + * 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; + + if(strcasecmp(f1.FilePath, f2.FilePath) > 0) + return false; + + return true; +} + +void DirList::SortList() +{ + if(FileInfo.size() > 1) + std::sort(FileInfo.begin(), FileInfo.end(), SortCallback); +} + +void DirList::SortList(bool (*SortFunc)(const DirEntry &a, const DirEntry &b)) +{ + if(FileInfo.size() > 1) + std::sort(FileInfo.begin(), FileInfo.end(), SortFunc); +} + +u64 DirList::GetFilesize(int index) const +{ + struct stat st; + const char *path = GetFilepath(index); + + if(!path || stat(path, &st) != 0) + return 0; + + return st.st_size; +} + +int DirList::GetFileIndex(const char *filename) const +{ + if(!filename) + return -1; + + for (u32 i = 0; i < FileInfo.size(); ++i) + { + if (strcasecmp(GetFilename(i), filename) == 0) + return i; + } + + return -1; +} diff --git a/src/fs/DirList.h b/src/fs/DirList.h new file mode 100644 index 0000000..2a34208 --- /dev/null +++ b/src/fs/DirList.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * DirList Class + * for WiiXplorer 2010 + ***************************************************************************/ +#ifndef ___DIRLIST_H_ +#define ___DIRLIST_H_ + +#include +#include +#include + +typedef struct +{ + char * FilePath; + bool isDir; +} DirEntry; + +class DirList +{ +public: + //!Constructor + DirList(void); + //!\param path Path from where to load the filelist of all files + //!\param filter A fileext that needs to be filtered + //!\param flags search/filter flags from the enum + DirList(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs); + //!Destructor + virtual ~DirList(); + //! Load all the files from a directory + bool LoadPath(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs); + //! Get a filename of the list + //!\param list index + const char * GetFilename(int index) const; + //! Get the a filepath of the list + //!\param list index + const char *GetFilepath(int index) const { if (!valid(index)) return ""; else return FileInfo[index].FilePath; } + //! Get the a filesize of the list + //!\param list index + u64 GetFilesize(int index) const; + //! Is index a dir or a file + //!\param list index + bool IsDir(int index) const { if(!valid(index)) return false; return FileInfo[index].isDir; }; + //! Get the filecount of the whole list + int GetFilecount() const { return FileInfo.size(); }; + //! Sort list by filepath + void SortList(); + //! Custom sort command for custom sort functions definitions + void SortList(bool (*SortFunc)(const DirEntry &a, const DirEntry &b)); + //! Get the index of the specified filename + int GetFileIndex(const char *filename) const; + //! Enum for search/filter flags + enum + { + Files = 0x01, + Dirs = 0x02, + CheckSubfolders = 0x08, + }; +protected: + // Internal parser + bool InternalLoadPath(std::string &path); + //!Add a list entrie + void AddEntrie(const std::string &filepath, const char * filename, bool isDir); + //! Clear the list + void ClearList(); + //! Check if valid pos is requested + inline bool valid(u32 pos) const { return (pos < FileInfo.size()); }; + + u32 Flags; + const char *Filter; + std::vector FileInfo; +}; + +#endif diff --git a/src/fs/fs_utils.c b/src/fs/fs_utils.c new file mode 100644 index 0000000..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/include/Put titledumper here.txt b/src/include/Put titledumper here.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/include/titledumper.exe b/src/include/titledumper.exe new file mode 100644 index 0000000000000000000000000000000000000000..546dc9e1e28bc9b49ad4b8f23b58b353dc585f25 GIT binary patch literal 40819 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 WKI2FzRWf9qH`XN|PzuHFc>f#F9 +#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 __attribute__((section(".data"))); +/* + * This function is a kernel hook function. It is called directly from kernel code at position 0xFFF18558. + */ +void my_PrepareTitle(CosAppXmlInfo *xmlKernelInfo) +{ + /** + * DBAT for access to our data region is setup at this point for the 0xC0000000 area. + */ + + //! Copy all data from the XML info + strncpy(cosAppXmlInfoStruct.rpx_name, xmlKernelInfo->rpx_name, FS_MAX_ENTNAME_SIZE); + + cosAppXmlInfoStruct.version_cos_xml = xmlKernelInfo->version_cos_xml; + cosAppXmlInfoStruct.os_version = xmlKernelInfo->os_version; + cosAppXmlInfoStruct.title_id = xmlKernelInfo->title_id; + cosAppXmlInfoStruct.app_type = xmlKernelInfo->app_type; + cosAppXmlInfoStruct.cmdFlags = xmlKernelInfo->cmdFlags; + cosAppXmlInfoStruct.max_size = xmlKernelInfo->max_size; + cosAppXmlInfoStruct.avail_size = xmlKernelInfo->avail_size; + cosAppXmlInfoStruct.codegen_size = xmlKernelInfo->codegen_size; + cosAppXmlInfoStruct.codegen_core = xmlKernelInfo->codegen_core; + cosAppXmlInfoStruct.max_codesize = xmlKernelInfo->max_codesize; + cosAppXmlInfoStruct.overlay_arena = xmlKernelInfo->overlay_arena; + cosAppXmlInfoStruct.default_stack0_size = xmlKernelInfo->default_stack0_size; + cosAppXmlInfoStruct.default_stack1_size = xmlKernelInfo->default_stack1_size; + cosAppXmlInfoStruct.default_stack2_size = xmlKernelInfo->default_stack2_size; + cosAppXmlInfoStruct.default_redzone0_size = xmlKernelInfo->default_redzone0_size; + cosAppXmlInfoStruct.default_redzone1_size = xmlKernelInfo->default_redzone1_size; + cosAppXmlInfoStruct.default_redzone2_size = xmlKernelInfo->default_redzone2_size; + cosAppXmlInfoStruct.exception_stack0_size = xmlKernelInfo->exception_stack0_size; + cosAppXmlInfoStruct.exception_stack1_size = xmlKernelInfo->exception_stack1_size; + cosAppXmlInfoStruct.exception_stack2_size = xmlKernelInfo->exception_stack2_size; + cosAppXmlInfoStruct.sdk_version = xmlKernelInfo->sdk_version; + cosAppXmlInfoStruct.title_version = xmlKernelInfo->title_version; + + // 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..73c01be --- /dev/null +++ b/src/kernel/syscalls.c @@ -0,0 +1,255 @@ +#include "common/os_defs.h" +#include "common/kernel_defs.h" +#include "common/common.h" +#include "dynamic_libs/os_functions.h" +#include "utils/utils.h" +#include "syscalls.h" + +extern void my_PrepareTitle_hook(void); + +static unsigned int origPrepareTitleInstr __attribute__((section(".data"))) = 0; + +static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len) +{ + /* + * Setup a DBAT access with cache inhibited to write through and read directly from memory + */ + unsigned int dbatu0, dbatl0, dbatu1, dbatl1; + // save the original DBAT value + asm volatile("mfdbatu %0, 0" : "=r" (dbatu0)); + asm volatile("mfdbatl %0, 0" : "=r" (dbatl0)); + asm volatile("mfdbatu %0, 1" : "=r" (dbatu1)); + asm volatile("mfdbatl %0, 1" : "=r" (dbatl1)); + + unsigned int target_dbatu0 = 0; + unsigned int target_dbatl0 = 0; + unsigned int target_dbatu1 = 0; + unsigned int target_dbatl1 = 0; + + unsigned char *dst_p = (unsigned char*)addr; + unsigned char *src_p = (unsigned char*)src; + + // we only need DBAT modification for addresses out of our own DBAT range + // as our own DBAT is available everywhere for user and supervisor + // since our own DBAT is on DBAT5 position we don't collide here + if(addr < 0x00800000 || addr >= 0x01000000) + { + target_dbatu0 = (addr & 0x00F00000) | 0xC0000000 | 0x1F; + target_dbatl0 = (addr & 0xFFF00000) | 0x32; + asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); + asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); + dst_p = (unsigned char*)((addr & 0xFFFFFF) | 0xC0000000); + } + if(src < 0x00800000 || src >= 0x01000000) + { + target_dbatu1 = (src & 0x00F00000) | 0xB0000000 | 0x1F; + target_dbatl1 = (src & 0xFFF00000) | 0x32; + + asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); + asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); + src_p = (unsigned char*)((src & 0xFFFFFF) | 0xB0000000); + } + + asm volatile("eieio; isync"); + + unsigned int i; + for(i = 0; i < len; i++) + { + // if we are on the edge to next chunk + if((target_dbatu0 != 0) && (((unsigned int)dst_p & 0x00F00000) != (target_dbatu0 & 0x00F00000))) + { + target_dbatu0 = ((addr + i) & 0x00F00000) | 0xC0000000 | 0x1F; + target_dbatl0 = ((addr + i) & 0xFFF00000) | 0x32; + dst_p = (unsigned char*)(((addr + i) & 0xFFFFFF) | 0xC0000000); + + asm volatile("eieio; isync"); + asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0)); + asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0)); + asm volatile("eieio; isync"); + } + if((target_dbatu1 != 0) && (((unsigned int)src_p & 0x00F00000) != (target_dbatu1 & 0x00F00000))) + { + target_dbatu1 = ((src + i) & 0x00F00000) | 0xB0000000 | 0x1F; + target_dbatl1 = ((src + i) & 0xFFF00000) | 0x32; + src_p = (unsigned char*)(((src + i) & 0xFFFFFF) | 0xB0000000); + + asm volatile("eieio; isync"); + asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1)); + asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1)); + asm volatile("eieio; isync"); + } + + *dst_p = *src_p; + + ++dst_p; + ++src_p; + } + + /* + * Restore original DBAT value +*/ + asm volatile("eieio; isync"); + asm volatile("mtdbatu 0, %0" : : "r" (dbatu0)); + asm volatile("mtdbatl 0, %0" : : "r" (dbatl0)); + asm volatile("mtdbatu 1, %0" : : "r" (dbatu1)); + asm volatile("mtdbatl 1, %0" : : "r" (dbatl1)); + asm volatile("eieio; isync"); +} + +static void KernelReadDBATs(bat_table_t * table) +{ + u32 i = 0; + + asm volatile("eieio; isync"); + + asm volatile("mfspr %0, 536" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 537" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 538" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 539" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 540" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 541" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 542" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 543" : "=r" (table->bat[i].l)); + i++; + + asm volatile("mfspr %0, 568" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 569" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 570" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 571" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 572" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 573" : "=r" (table->bat[i].l)); + i++; + asm volatile("mfspr %0, 574" : "=r" (table->bat[i].h)); + asm volatile("mfspr %0, 575" : "=r" (table->bat[i].l)); +} + +static void KernelWriteDBATs(bat_table_t * table) +{ + u32 i = 0; + + asm volatile("eieio; isync"); + + asm volatile("mtspr 536, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 537, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 538, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 539, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 540, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 541, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 542, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 543, %0" : : "r" (table->bat[i].l)); + i++; + + asm volatile("mtspr 568, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 569, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 570, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 571, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 572, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 573, %0" : : "r" (table->bat[i].l)); + i++; + asm volatile("mtspr 574, %0" : : "r" (table->bat[i].h)); + asm volatile("mtspr 575, %0" : : "r" (table->bat[i].l)); + + asm volatile("eieio; isync"); +} + +/* Read a 32-bit word with kernel permissions */ +uint32_t __attribute__ ((noinline)) kern_read(const void *addr) +{ + uint32_t result; + asm volatile ( + "li 3,1\n" + "li 4,0\n" + "li 5,0\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%1\n" + "li 0,0x3400\n" + "mr %0,1\n" + "sc\n" + "nop\n" + "mr 1,%0\n" + "mr %0,3\n" + : "=r"(result) + : "b"(addr) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" + ); + + return result; +} + +/* Write a 32-bit word with kernel permissions */ +void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value) +{ + asm volatile ( + "li 3,1\n" + "li 4,0\n" + "mr 5,%1\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%0\n" + "mr %1,1\n" + "li 0,0x3500\n" + "sc\n" + "nop\n" + "mr 1,%1\n" + : + : "r"(addr), "r"(value) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" + ); +} + +void KernelSetupSyscalls(void) +{ + //! assign 1 so that this variable gets into the retained .data section + static uint8_t ucSyscallsSetupRequired = 1; + if(!ucSyscallsSetupRequired) + return; + + ucSyscallsSetupRequired = 0; + + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x36 * 4)), (unsigned int)KernelReadDBATs); + + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x37 * 4)), (unsigned int)KernelWriteDBATs); + + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x25 * 4)), (unsigned int)KernelCopyData); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x25 * 4)), (unsigned int)KernelCopyData); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x25 * 4)), (unsigned int)KernelCopyData); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x25 * 4)), (unsigned int)KernelCopyData); + kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x25 * 4)), (unsigned int)KernelCopyData); + + //! write our hook to the + u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003; + DCFlushRange(&addr_my_PrepareTitle_hook, sizeof(addr_my_PrepareTitle_hook)); + + SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4); + SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)OSEffectiveToPhysical(&addr_my_PrepareTitle_hook), 4); +} + + +void KernelRestoreInstructions(void) +{ + if(origPrepareTitleInstr != 0) + SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)&origPrepareTitleInstr, 4); +} diff --git a/src/kernel/syscalls.h b/src/kernel/syscalls.h new file mode 100644 index 0000000..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..b844188 --- /dev/null +++ b/src/main.c @@ -0,0 +1,242 @@ +#include +#include +#include +#include +#include + +#include +#include +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/fs_functions.h" +#include "dynamic_libs/gx2_functions.h" +#include "dynamic_libs/sys_functions.h" +#include "dynamic_libs/vpad_functions.h" +#include "dynamic_libs/padscore_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "dynamic_libs/ax_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/exception_handler.h" +#include "system/memory.h" +#include "utils/logger.h" +#include "utils/utils.h" +#include "common/common.h" +#include "pygecko.h" + +#define BUFFER_SIZE 40000 + +int pygecko; +int CCHandler; +char *buffer[BUFFER_SIZE] __attribute__((section(".data"))); + +#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(); + + + + log_init("192.168.178.49"); + log_deinit(); + log_init("192.168.178.49"); + 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 pressedBtns = vpad_data.btns_d | vpad_data.btns_h; + + // Check for buttons + // Home Button + if (pressedBtns & VPAD_BUTTON_HOME) { + launchMethod = 0; + break; + } + // A Button + if (pressedBtns & VPAD_BUTTON_A) { + launchMethod = 2; + break; + } + // X Button + if (pressedBtns & 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>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*)INSTALL_ADDR); + + 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 = (pressedBtns & (VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN)) ? 1 : 0; + usleep(20000); + } + 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) + { + char buf_vol_odd[20]; + snprintf(buf_vol_odd, sizeof(buf_vol_odd), "%s", "/vol/storage_odd03"); + _SYSLaunchTitleByPathFromLauncher(buf_vol_odd, 18, 0); + } + else + { + pygecko = 1; + SYSLaunchMenu(); + } + + return EXIT_RELAUNCH_ON_LOAD; +} 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..894509d --- /dev/null +++ b/src/patcher/function_hooks.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include "common/common.h" +#include "common/fs_defs.h" +#include "common/loader_defs.h" +#include "game/rpx_rpl_table.h" +#include "dynamic_libs/fs_functions.h" +#include "dynamic_libs/os_functions.h" +#include "kernel/kernel_functions.h" +#include "function_hooks.h" +#include "pygecko.h" + +#define LIB_CODE_RW_BASE_OFFSET 0xC1000000 +#define CODE_RW_BASE_OFFSET 0x00000000 + +#define USE_EXTRA_LOG_FUNCTIONS 0 + +#define DECL(res, name, ...) \ + res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \ + res my_ ## name(__VA_ARGS__) + +/* ***************************************************************************** + * Creates function pointer array + * ****************************************************************************/ +#define MAKE_MAGIC(x, lib) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x } + + +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[30]; +} method_hooks[] = { + MAKE_MAGIC(FSInit, LIB_CORE_INIT), + MAKE_MAGIC(socket_lib_finish, LIB_CORE_INIT), +}; + +//! 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] __attribute__((section(".data"))); + +void PatchMethodHooks(void) +{ + restore_instructions_t * restore = (restore_instructions_t *)(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 = (unsigned int)method_hooks[i].replaceAddr; + unsigned int call_addr = (unsigned int)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_instructions_t *)(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), 4); + ICInvalidateRange((void*)restore->data[i].addr, 4); + } + + } + restore->magic = 0; + restore->instr_count = 0; + + KernelRestoreDBATs(&table); + KernelRestoreInstructions(); +} 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..9c19396 --- /dev/null +++ b/src/pygecko.c @@ -0,0 +1,431 @@ +#include +#include +#include +#include "common/common.h" +#include "main.h" +#include "dynamic_libs/os_functions.h" +#include "dynamic_libs/socket_functions.h" +#include "dynamic_libs/gx2_functions.h" +#include "kernel/syscalls.h" +#include "system/exception_handler.h" + +struct pygecko_bss_t { + int error, line; + void* thread; + unsigned char stack[0x8000]; +}; + + +#define CHECK_ERROR(cond) if (cond) { bss->line = __LINE__; goto error; } +#define errno (*__gh_errno_ptr()) +#define MSG_DONTWAIT 32 +#define EWOULDBLOCK 6 + +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(struct pygecko_bss_t *bss, 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); +} + +static int rungecko(struct pygecko_bss_t *bss, int clientfd) { + int ret; + unsigned char buffer[0x401]; + + while (1) { + ret = checkbyte(bss, clientfd); + + if (ret < 0) { + CHECK_ERROR(errno != EWOULDBLOCK); + GX2WaitForVsync(); + continue; + } + + switch (ret) { + case 0x01: { /* cmd_poke08 */ + char *ptr; + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0); + + ptr = ((char **)buffer)[0]; + *ptr = buffer[7]; + DCFlushRange(ptr, 1); + break; + } + case 0x02: { /* cmd_poke16 */ + short *ptr; + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0); + + ptr = ((short **)buffer)[0]; + *ptr = ((short *)buffer)[3]; + DCFlushRange(ptr, 2); + break; + } + case 0x03: { /* cmd_pokemem */ + int *ptr; + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0); + + ptr = ((int **)buffer)[0]; + *ptr = ((int *)buffer)[1]; + DCFlushRange(ptr, 4); + break; + } + case 0x04: { /* cmd_readmem */ + const unsigned char *ptr, *end; + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0); + ptr = ((const unsigned char **)buffer)[0]; + end = ((const unsigned char **)buffer)[1]; + + while (ptr != end) { + int len, i; + + len = end - ptr; + if (len > 0x400) + len = 0x400; + for (i = 0; i < len; i++) + if (ptr[i] != 0) break; + + if (i == len) { // all zero! + ret = sendbyte(bss, clientfd, 0xb0); + CHECK_ERROR(ret < 0); + } else { + memcpy(buffer + 1, ptr, len); + buffer[0] = 0xbd; + ret = sendwait(bss, clientfd, buffer, len + 1); + CHECK_ERROR(ret < 0); + } + + ret = checkbyte(bss, clientfd); + if (ret == 0xcc) /* GCFAIL */ + goto next_cmd; + ptr += len; + } + break; + } + case 0x0b: { /* cmd_writekern */ + 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 0x0c: { /* cmd_readkern */ + 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 0x41: { /* cmd_upload */ + unsigned char *ptr, *end, *dst; + ret = recvwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0); + ptr = ((unsigned char **)buffer)[0]; + end = ((unsigned char **)buffer)[1]; + + while (ptr != end) { + int len; + + len = end - ptr; + if (len > 0x400) + len = 0x400; + if ((int)ptr >= 0x10000000 && (int)ptr <= 0x50000000) { + dst = ptr; + } else { + dst = buffer; + } + ret = recvwait(bss, clientfd, dst, len); + CHECK_ERROR(ret < 0); + if (dst == buffer) { + memcpy(ptr, buffer, len); + } + + ptr += len; + } + + sendbyte(bss, clientfd, 0xaa); /* GCACK */ + break; + } + case 0x50: { /* cmd_status */ + ret = sendbyte(bss, clientfd, 1); /* running */ + CHECK_ERROR(ret < 0); + break; + } + case 0x70: { /* cmd_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 0x71: { /* cmd_getsymbol */ + 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 = 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 0x72: { /* cmd_search32 */ + ret = recvwait(bss, clientfd, buffer, 12); + CHECK_ERROR(ret < 0); + int addr = ((int *) buffer)[0]; + int val = ((int *) buffer)[1]; + int size = ((int *) buffer)[2]; + int i; + int resaddr = 0; + for(i = addr; i < (addr+size); i+=4) + { + if(*(int*)i == val) + { + resaddr = i; + break; + } + } + ((int *)buffer)[0] = resaddr; + ret = sendwait(bss, clientfd, buffer, 4); + CHECK_ERROR(ret < 0); + break; + } + case 0x80: { /* cmd_rpc_big */ + long long (*fun)(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); + int r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18; + long long result; + + ret = recvwait(bss, clientfd, buffer, 4 + 16 * 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]; + r11 = ((int *)buffer)[9]; + r12 = ((int *)buffer)[10]; + r13 = ((int *)buffer)[11]; + r14 = ((int *)buffer)[12]; + r15 = ((int *)buffer)[13]; + r16 = ((int *)buffer)[14]; + r17 = ((int *)buffer)[15]; + r18 = ((int *)buffer)[16]; + + result = fun(r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18); + + ((long long *)buffer)[0] = result; + ret = sendwait(bss, clientfd, buffer, 8); + CHECK_ERROR(ret < 0); + break; + } + case 0x99: { /* cmd_version */ + ret = sendbyte(bss, clientfd, 0x82); /* WiiU */ + CHECK_ERROR(ret < 0); + break; + } + case 0x9A: { /* cmd_os_version */ + ((int *)buffer)[0] = (int)OS_FIRMWARE; + ret = sendwait(bss, clientfd, buffer, 4); + CHECK_ERROR(ret < 0); + break; + } + case 0xcc: { /* GCFAIL */ + break; + } + default: + ret = -1; + CHECK_ERROR(0); + break; + } +next_cmd: + continue; + } + return 0; +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; + + 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); //open a file handle to socket + 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; + } + + socketclose(sockfd); + sockfd = -1; +error: + if (clientfd != -1) + socketclose(clientfd); + if (sockfd != -1) + socketclose(sockfd); + bss->error = ret; + + } + 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*)INSTALL_ADDR; + + while(1) + { + usleep(9000); + entrypoint(); + } + } + return 0; +} + +void start_pygecko(void) +{ + unsigned int stack = (unsigned int) memalign(0x40, 0x1000); + stack += 0x1000; + + /* Create the thread */ + void *thread = memalign(0x40, 0x1000); + + if(OSCreateThread(thread, CCThread, 1, NULL, (u32)stack + sizeof(stack), sizeof(stack), 0, 2 | 0x10 | 8) == 1) + { + OSResumeThread(thread); + } + else + { + free(thread); + } + +} 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..b642248 --- /dev/null +++ b/src/system/exception_handler.c @@ -0,0 +1,169 @@ +#include +#include "dynamic_libs/os_functions.h" +#include "utils/logger.h" +#include "exception_handler.h" + +#define OS_EXCEPTION_MODE_GLOBAL_ALL_CORES 4 + +#define OS_EXCEPTION_DSI 2 +#define OS_EXCEPTION_ISI 3 +#define OS_EXCEPTION_PROGRAM 6 + +/* Exceptions */ +typedef struct OSContext +{ + /* OSContext identifier */ + uint32_t tag1; + uint32_t tag2; + + /* GPRs */ + uint32_t gpr[32]; + + /* Special registers */ + uint32_t cr; + uint32_t lr; + uint32_t ctr; + uint32_t xer; + + /* Initial PC and MSR */ + uint32_t srr0; + uint32_t srr1; + + /* Only valid during DSI exception */ + uint32_t exception_specific0; + uint32_t exception_specific1; + + /* There is actually a lot more here but we don't need the rest*/ +} OSContext; + +#define CPU_STACK_TRACE_DEPTH 10 +#define __stringify(rn) #rn + +#define mfspr(_rn) \ +({ register uint32_t _rval = 0; \ + asm volatile("mfspr %0," __stringify(_rn) \ + : "=r" (_rval));\ + _rval; \ +}) + +typedef struct _framerec { + struct _framerec *up; + void *lr; +} frame_rec, *frame_rec_t; + +static const char *exception_names[] = { + "DSI", + "ISI", + "PROGRAM" +}; + +static const char exception_print_formats[18][45] = { + "Exception type %s occurred!\n", // 0 + "GPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n", // 1 + "GPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n", // 2 + "GPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n", // 3 + "GPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n", // 4 + "GPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n", // 5 + "GPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n", // 6 + "GPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n", // 7 + "GPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n", // 8 + "LR %08X SRR0 %08x SRR1 %08x\n", // 9 + "DAR %08X DSISR %08X\n", // 10 + "\nSTACK DUMP:", // 11 + " --> ", // 12 + " -->\n", // 13 + "\n", // 14 + "%p", // 15 + "\nCODE DUMP:\n", // 16 + "%p: %08X %08X %08X %08X\n", // 17 +}; + +static unsigned char exception_cb(void * c, unsigned char exception_type) { + char buf[850]; + int pos = 0; + + OSContext *context = (OSContext *) c; + /* + * This part is mostly from libogc. Thanks to the devs over there. + */ + pos += sprintf(buf + pos, exception_print_formats[0], exception_names[exception_type]); + pos += sprintf(buf + pos, exception_print_formats[1], context->gpr[0], context->gpr[8], context->gpr[16], context->gpr[24]); + pos += sprintf(buf + pos, exception_print_formats[2], context->gpr[1], context->gpr[9], context->gpr[17], context->gpr[25]); + pos += sprintf(buf + pos, exception_print_formats[3], context->gpr[2], context->gpr[10], context->gpr[18], context->gpr[26]); + pos += sprintf(buf + pos, exception_print_formats[4], context->gpr[3], context->gpr[11], context->gpr[19], context->gpr[27]); + pos += sprintf(buf + pos, exception_print_formats[5], context->gpr[4], context->gpr[12], context->gpr[20], context->gpr[28]); + pos += sprintf(buf + pos, exception_print_formats[6], context->gpr[5], context->gpr[13], context->gpr[21], context->gpr[29]); + pos += sprintf(buf + pos, exception_print_formats[7], context->gpr[6], context->gpr[14], context->gpr[22], context->gpr[30]); + pos += sprintf(buf + pos, exception_print_formats[8], context->gpr[7], context->gpr[15], context->gpr[23], context->gpr[31]); + pos += sprintf(buf + pos, exception_print_formats[9], context->lr, context->srr0, context->srr1); + + //if(exception_type == OS_EXCEPTION_DSI) { + pos += sprintf(buf + pos, exception_print_formats[10], context->exception_specific1, context->exception_specific0); // this freezes + //} + + void *pc = (void*)context->srr0; + void *lr = (void*)context->lr; + void *r1 = (void*)context->gpr[1]; + register uint32_t i = 0; + register frame_rec_t l,p = (frame_rec_t)lr; + + l = p; + p = r1; + if(!p) + asm volatile("mr %0,%%r1" : "=r"(p)); + + pos += sprintf(buf + pos, exception_print_formats[11]); + + for(i = 0; i < CPU_STACK_TRACE_DEPTH-1 && p->up; p = p->up, i++) { + if(i % 4) + pos += sprintf(buf + pos, exception_print_formats[12]); + else { + if(i > 0) + pos += sprintf(buf + pos, exception_print_formats[13]); + else + pos += sprintf(buf + pos, exception_print_formats[14]); + } + + switch(i) { + case 0: + if(pc) + pos += sprintf(buf + pos, exception_print_formats[15],pc); + break; + case 1: + if(!l) + l = (frame_rec_t)mfspr(8); + pos += sprintf(buf + pos, exception_print_formats[15],(void*)l); + break; + default: + pos += sprintf(buf + pos, exception_print_formats[15],(void*)(p->up->lr)); + break; + } + } + + //if(exception_type == OS_EXCEPTION_DSI) { + uint32_t *pAdd = (uint32_t*)context->srr0; + pos += sprintf(buf + pos, exception_print_formats[16]); + // TODO by Dimok: this was actually be 3 instead of 2 lines in libogc .... but there is just no more space anymore on the screen + for (i = 0; i < 8; i += 4) + pos += sprintf(buf + pos, exception_print_formats[17], &(pAdd[i]),pAdd[i], pAdd[i+1], pAdd[i+2], pAdd[i+3]); + //} + log_print(buf); + OSFatal(buf); + return 1; +} + +static unsigned char dsi_exception_cb(void * context) { + return exception_cb(context, 0); +} +static unsigned char isi_exception_cb(void * context) { + return exception_cb(context, 1); +} +static unsigned char program_exception_cb(void * context) { + return exception_cb(context, 2); +} + +void setup_os_exceptions(void) { + OSSetExceptionCallback(OS_EXCEPTION_DSI, &dsi_exception_cb); + OSSetExceptionCallback(OS_EXCEPTION_ISI, &isi_exception_cb); + OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb); +} diff --git a/src/system/exception_handler.h b/src/system/exception_handler.h new file mode 100644 index 0000000..7626f92 --- /dev/null +++ b/src/system/exception_handler.h @@ -0,0 +1,14 @@ +#ifndef __EXCEPTION_HANDLER_H_ +#define __EXCEPTION_HANDLER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void setup_os_exceptions(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/system/memory.c b/src/system/memory.c new file mode 100644 index 0000000..91f5392 --- /dev/null +++ b/src/system/memory.c @@ -0,0 +1,198 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#include +#include +#include "dynamic_libs/os_functions.h" +#include "common/common.h" +#include "memory.h" + +#define MEMORY_ARENA_1 0 +#define MEMORY_ARENA_2 1 +#define MEMORY_ARENA_3 2 +#define MEMORY_ARENA_4 3 +#define MEMORY_ARENA_5 4 +#define MEMORY_ARENA_6 5 +#define MEMORY_ARENA_7 6 +#define MEMORY_ARENA_8 7 +#define MEMORY_ARENA_FG_BUCKET 8 + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Memory functions +//! This is the only place where those are needed so lets keep them more or less private +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern unsigned int * pMEMAllocFromDefaultHeapEx; +extern unsigned int * pMEMAllocFromDefaultHeap; +extern unsigned int * pMEMFreeToDefaultHeap; + +extern int (* MEMGetBaseHeapHandle)(int mem_arena); +extern unsigned int (* MEMGetAllocatableSizeForFrmHeapEx)(int heap, int align); +extern void *(* MEMAllocFromFrmHeapEx)(int heap, unsigned int size, int align); +extern void (* MEMFreeToFrmHeap)(int heap, int mode); +extern void *(* MEMAllocFromExpHeapEx)(int heap, unsigned int size, int align); +extern int (* MEMCreateExpHeapEx)(void* address, unsigned int size, unsigned short flags); +extern void *(* MEMDestroyExpHeap)(int heap); +extern void (* MEMFreeToExpHeap)(int heap, void* ptr); + +static int mem1_heap = -1; +static int bucket_heap = -1; + +void memoryInitialize(void) +{ + int mem1_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_1); + unsigned int mem1_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(mem1_heap_handle, 4); + void *mem1_memory = MEMAllocFromFrmHeapEx(mem1_heap_handle, mem1_allocatable_size, 4); + if(mem1_memory) + mem1_heap = MEMCreateExpHeapEx(mem1_memory, mem1_allocatable_size, 0); + + int bucket_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET); + unsigned int bucket_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(bucket_heap_handle, 4); + void *bucket_memory = MEMAllocFromFrmHeapEx(bucket_heap_handle, bucket_allocatable_size, 4); + if(bucket_memory) + bucket_heap = MEMCreateExpHeapEx(bucket_memory, bucket_allocatable_size, 0); +} + +void memoryRelease(void) +{ + MEMDestroyExpHeap(mem1_heap); + MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_1), 3); + mem1_heap = -1; + + MEMDestroyExpHeap(bucket_heap); + MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET), 3); + bucket_heap = -1; +} + +//!------------------------------------------------------------------------------------------- +//! wraps +//!------------------------------------------------------------------------------------------- +void *__wrap_malloc(size_t size) +{ + // pointer to a function resolve + return ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(size); +} + +void *__wrap_memalign(size_t align, size_t size) +{ + if (align < 4) + align = 4; + + // pointer to a function resolve + return ((void * (*)(size_t, size_t))(*pMEMAllocFromDefaultHeapEx))(size, align); +} + +void __wrap_free(void *p) +{ + // pointer to a function resolve + if(p != 0) + ((void (*)(void *))(*pMEMFreeToDefaultHeap))(p); +} + +void *__wrap_calloc(size_t n, size_t size) +{ + void *p = __wrap_malloc(n * size); + if (p != 0) { + memset(p, 0, n * size); + } + return p; +} + +size_t __wrap_malloc_usable_size(void *p) +{ + //! TODO: this is totally wrong and needs to be addressed + return 0x7FFFFFFF; +} + +void *__wrap_realloc(void *p, size_t size) +{ + void *new_ptr = __wrap_malloc(size); + if (new_ptr != 0) + { + memcpy(new_ptr, p, __wrap_malloc_usable_size(p) < size ? __wrap_malloc_usable_size(p) : size); + __wrap_free(p); + } + return new_ptr; +} + +//!------------------------------------------------------------------------------------------- +//! reent versions +//!------------------------------------------------------------------------------------------- +void *__wrap__malloc_r(struct _reent *r, size_t size) +{ + return __wrap_malloc(size); +} + +void *__wrap__calloc_r(struct _reent *r, size_t n, size_t size) +{ + return __wrap_calloc(n, size); +} + +void *__wrap__memalign_r(struct _reent *r, size_t align, size_t size) +{ + return __wrap_memalign(align, size); +} + +void __wrap__free_r(struct _reent *r, void *p) +{ + __wrap_free(p); +} + +size_t __wrap__malloc_usable_size_r(struct _reent *r, void *p) +{ + return __wrap_malloc_usable_size(p); +} + +void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) +{ + return __wrap_realloc(p, size); +} + +//!------------------------------------------------------------------------------------------- +//! some wrappers +//!------------------------------------------------------------------------------------------- +void * MEM2_alloc(unsigned int size, unsigned int align) +{ + return __wrap_memalign(align, size); +} + +void MEM2_free(void *ptr) +{ + __wrap_free(ptr); +} + +void * MEM1_alloc(unsigned int size, unsigned int align) +{ + if (align < 4) + align = 4; + return MEMAllocFromExpHeapEx(mem1_heap, size, align); +} + +void MEM1_free(void *ptr) +{ + MEMFreeToExpHeap(mem1_heap, ptr); +} + +void * MEMBucket_alloc(unsigned int size, unsigned int align) +{ + if (align < 4) + align = 4; + return MEMAllocFromExpHeapEx(bucket_heap, size, align); +} + +void MEMBucket_free(void *ptr) +{ + MEMFreeToExpHeap(bucket_heap, ptr); +} diff --git a/src/system/memory.h b/src/system/memory.h new file mode 100644 index 0000000..59764d0 --- /dev/null +++ b/src/system/memory.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#ifndef __MEMORY_H_ +#define __MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void memoryInitialize(void); +void memoryRelease(void); + +void * MEM2_alloc(unsigned int size, unsigned int align); +void MEM2_free(void *ptr); + +void * MEM1_alloc(unsigned int size, unsigned int align); +void MEM1_free(void *ptr); + +void * MEMBucket_alloc(unsigned int size, unsigned int align); +void MEMBucket_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif // __MEMORY_H_ diff --git a/src/utils/StringTools.cpp b/src/utils/StringTools.cpp new file mode 100644 index 0000000..debb6c7 --- /dev/null +++ b/src/utils/StringTools.cpp @@ -0,0 +1,207 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +const char * fmt(const char * format, ...) +{ + static char strChar[512]; + strChar[0] = 0; + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + snprintf(strChar, sizeof(strChar), tmp); + free(tmp); + va_end(va); + return (const char *) strChar; + } + va_end(va); + + if(tmp) + free(tmp); + + return NULL; +} + +const wchar_t * wfmt(const char * format, ...) +{ + static wchar_t strWChar[512]; + strWChar[0] = 0; + + if(!format) + return (const wchar_t *) strWChar; + + if(strcmp(format, "") == 0) + return (const wchar_t *) strWChar; + + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + int bt; + int strlength = strlen(tmp); + bt = mbstowcs(strWChar, tmp, (strlength < 512) ? strlength : 512 ); + free(tmp); + tmp = 0; + + if(bt > 0) + { + strWChar[bt] = 0; + return (const wchar_t *) strWChar; + } + } + va_end(va); + + if(tmp) + free(tmp); + + return NULL; +} + +int strprintf(std::string &str, const char * format, ...) +{ + int result = 0; + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + str = tmp; + result = str.size(); + } + va_end(va); + + if(tmp) + free(tmp); + + return result; +} + +std::string strfmt(const char * format, ...) +{ + std::string str; + char * tmp = NULL; + + va_list va; + va_start(va, format); + if((vasprintf(&tmp, format, va) >= 0) && tmp) + { + str = tmp; + } + va_end(va); + + if(tmp) + free(tmp); + + return str; +} + +bool char2wchar_t(const char * strChar, wchar_t * dest) +{ + if(!strChar || !dest) + return false; + + int bt; + bt = mbstowcs(dest, strChar, strlen(strChar)); + if (bt > 0) { + dest[bt] = 0; + return true; + } + + return false; +} + +int strtokcmp(const char * string, const char * compare, const char * separator) +{ + if(!string || !compare) + return -1; + + char TokCopy[512]; + strncpy(TokCopy, compare, sizeof(TokCopy)); + TokCopy[511] = '\0'; + + char * strTok = strtok(TokCopy, separator); + + while (strTok != NULL) + { + if (strcasecmp(string, strTok) == 0) + { + return 0; + } + strTok = strtok(NULL,separator); + } + + return -1; +} + +int strextcmp(const char * string, const char * extension, char seperator) +{ + if(!string || !extension) + return -1; + + char *ptr = strrchr(string, seperator); + if(!ptr) + return -1; + + return strcasecmp(ptr + 1, extension); +} + + +std::vector stringSplit(const std::string & inValue, const std::string & splitter) +{ + std::string value = inValue; + std::vector result; + while (true) { + unsigned int index = value.find(splitter); + if (index == std::string::npos) { + result.push_back(value); + break; + } + std::string first = value.substr(0, index); + result.push_back(first); + if (index + splitter.size() == value.length()) { + result.push_back(""); + break; + } + if(index + splitter.size() > value.length()) { + break; + } + value = value.substr(index + splitter.size(), value.length()); + } + return result; +} diff --git a/src/utils/StringTools.h b/src/utils/StringTools.h new file mode 100644 index 0000000..bcf89c4 --- /dev/null +++ b/src/utils/StringTools.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * for WiiXplorer 2010 + ***************************************************************************/ +#ifndef __STRING_TOOLS_H +#define __STRING_TOOLS_H + +#include +#include +#include + +const char * fmt(const char * format, ...); +const wchar_t * wfmt(const char * format, ...); +int strprintf(std::string &str, const char * format, ...); +std::string strfmt(const char * format, ...); +bool char2wchar_t(const char * src, wchar_t * dest); +int strtokcmp(const char * string, const char * compare, const char * separator); +int strextcmp(const char * string, const char * extension, char seperator); + +inline const char * FullpathToFilename(const char *path) +{ + if(!path) return path; + + const char * ptr = path; + const char * Filename = ptr; + + while(*ptr != '\0') + { + if(ptr[0] == '/' && ptr[1] != '\0') + Filename = ptr+1; + + ++ptr; + } + + return Filename; +} + +inline void RemoveDoubleSlashs(std::string &str) +{ + u32 length = str.size(); + + //! clear path of double slashes + for(u32 i = 1; i < length; ++i) + { + if(str[i-1] == '/' && str[i] == '/') + { + str.erase(i, 1); + i--; + length--; + } + } +} + +std::vector stringSplit(const std::string & value, const std::string & splitter); + +#endif /* __STRING_TOOLS_H */ + diff --git a/src/utils/logger.c b/src/utils/logger.c new file mode 100644 index 0000000..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_